blob: 36b1a76cfc8ca8579e60713243db3243dd69ddb7 [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) {
2818 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00002819 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002820 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
2821 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
2822 HasRequiresUnifiedSharedMemory))
Alexey Bataevd01b7492018-08-15 19:45:12 +00002823 return CGM.getLangOpts().OpenMPIsDevice;
Alexey Bataev34f8a702018-03-28 14:28:54 +00002824 VD = VD->getDefinition(CGM.getContext());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00002825 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second)
Alexey Bataev34f8a702018-03-28 14:28:54 +00002826 return CGM.getLangOpts().OpenMPIsDevice;
2827
2828 QualType ASTTy = VD->getType();
2829
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002830 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc();
Alexey Bataev34f8a702018-03-28 14:28:54 +00002831 // Produce the unique prefix to identify the new target regions. We use
2832 // the source location of the variable declaration which we know to not
2833 // conflict with any target region.
2834 unsigned DeviceID;
2835 unsigned FileID;
2836 unsigned Line;
2837 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line);
2838 SmallString<128> Buffer, Out;
2839 {
2840 llvm::raw_svector_ostream OS(Buffer);
2841 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID)
2842 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
2843 }
2844
2845 const Expr *Init = VD->getAnyInitializer();
2846 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
2847 llvm::Constant *Ctor;
2848 llvm::Constant *ID;
2849 if (CGM.getLangOpts().OpenMPIsDevice) {
2850 // Generate function that re-emits the declaration's initializer into
2851 // the threadprivate copy of the variable VD
2852 CodeGenFunction CtorCGF(CGM);
2853
2854 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2855 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2856 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
2857 FTy, Twine(Buffer, "_ctor"), FI, Loc);
2858 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF);
2859 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
2860 FunctionArgList(), Loc, Loc);
2861 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF);
2862 CtorCGF.EmitAnyExprToMem(Init,
2863 Address(Addr, CGM.getContext().getDeclAlign(VD)),
2864 Init->getType().getQualifiers(),
2865 /*IsInitializer=*/true);
2866 CtorCGF.FinishFunction();
2867 Ctor = Fn;
2868 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
Alexey Bataeve253f2f2018-05-09 14:15:18 +00002869 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor));
Alexey Bataev34f8a702018-03-28 14:28:54 +00002870 } else {
2871 Ctor = new llvm::GlobalVariable(
2872 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
2873 llvm::GlobalValue::PrivateLinkage,
2874 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor"));
2875 ID = Ctor;
2876 }
2877
2878 // Register the information for the entry associated with the constructor.
2879 Out.clear();
2880 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
2881 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor,
Alexey Bataev03f270c2018-03-30 18:31:07 +00002882 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor);
Alexey Bataev34f8a702018-03-28 14:28:54 +00002883 }
2884 if (VD->getType().isDestructedType() != QualType::DK_none) {
2885 llvm::Constant *Dtor;
2886 llvm::Constant *ID;
2887 if (CGM.getLangOpts().OpenMPIsDevice) {
2888 // Generate function that emits destructor call for the threadprivate
2889 // copy of the variable VD
2890 CodeGenFunction DtorCGF(CGM);
2891
2892 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2893 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2894 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
2895 FTy, Twine(Buffer, "_dtor"), FI, Loc);
2896 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
2897 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
2898 FunctionArgList(), Loc, Loc);
2899 // Create a scope with an artificial location for the body of this
2900 // function.
2901 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
2902 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)),
2903 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()),
2904 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
2905 DtorCGF.FinishFunction();
2906 Dtor = Fn;
2907 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
Alexey Bataeve253f2f2018-05-09 14:15:18 +00002908 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor));
Alexey Bataev34f8a702018-03-28 14:28:54 +00002909 } else {
2910 Dtor = new llvm::GlobalVariable(
2911 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
2912 llvm::GlobalValue::PrivateLinkage,
2913 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor"));
2914 ID = Dtor;
2915 }
2916 // Register the information for the entry associated with the destructor.
2917 Out.clear();
2918 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
2919 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor,
Alexey Bataev03f270c2018-03-30 18:31:07 +00002920 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor);
Alexey Bataev34f8a702018-03-28 14:28:54 +00002921 }
2922 return CGM.getLangOpts().OpenMPIsDevice;
2923}
2924
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002925Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
2926 QualType VarType,
2927 StringRef Name) {
Alexey Bataev18fa2322018-05-02 14:20:50 +00002928 std::string Suffix = getName({"artificial", ""});
2929 std::string CacheSuffix = getName({"cache", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002930 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002931 llvm::Value *GAddr =
2932 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002933 llvm::Value *Args[] = {
2934 emitUpdateLocation(CGF, SourceLocation()),
2935 getThreadID(CGF, SourceLocation()),
2936 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy),
2937 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00002938 /*isSigned=*/false),
Alexey Bataev18fa2322018-05-02 14:20:50 +00002939 getOrCreateInternalVariable(
2940 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))};
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002941 return Address(
2942 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2943 CGF.EmitRuntimeCall(
2944 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
2945 VarLVType->getPointerTo(/*AddrSpace=*/0)),
2946 CGM.getPointerAlign());
2947}
2948
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +00002949void CGOpenMPRuntime::emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
2950 const RegionCodeGenTy &ThenGen,
2951 const RegionCodeGenTy &ElseGen) {
Alexey Bataev1d677132015-04-22 13:57:31 +00002952 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
2953
2954 // If the condition constant folds and can be elided, try to avoid emitting
2955 // the condition and the dead arm of the if/else.
2956 bool CondConstant;
2957 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002958 if (CondConstant)
Alexey Bataev1d677132015-04-22 13:57:31 +00002959 ThenGen(CGF);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002960 else
Alexey Bataev1d677132015-04-22 13:57:31 +00002961 ElseGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00002962 return;
2963 }
2964
2965 // Otherwise, the condition did not fold, or we couldn't elide it. Just
2966 // emit the conditional branch.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002967 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then");
2968 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else");
2969 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end");
Alexey Bataev1d677132015-04-22 13:57:31 +00002970 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
2971
2972 // Emit the 'then' code.
2973 CGF.EmitBlock(ThenBlock);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002974 ThenGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00002975 CGF.EmitBranch(ContBlock);
2976 // Emit the 'else' code if present.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002977 // There is no need to emit line number for unconditional branch.
2978 (void)ApplyDebugLocation::CreateEmpty(CGF);
2979 CGF.EmitBlock(ElseBlock);
2980 ElseGen(CGF);
2981 // There is no need to emit line number for unconditional branch.
2982 (void)ApplyDebugLocation::CreateEmpty(CGF);
2983 CGF.EmitBranch(ContBlock);
Alexey Bataev1d677132015-04-22 13:57:31 +00002984 // Emit the continuation block for code after the if.
2985 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00002986}
2987
Alexey Bataev1d677132015-04-22 13:57:31 +00002988void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00002989 llvm::Function *OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00002990 ArrayRef<llvm::Value *> CapturedVars,
Alexey Bataev1d677132015-04-22 13:57:31 +00002991 const Expr *IfCond) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002992 if (!CGF.HaveInsertPoint())
2993 return;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002994 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002995 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF,
2996 PrePostActionTy &) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00002997 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002998 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev2377fe92015-09-10 08:12:02 +00002999 llvm::Value *Args[] = {
3000 RTLoc,
3001 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003002 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())};
Alexey Bataev2377fe92015-09-10 08:12:02 +00003003 llvm::SmallVector<llvm::Value *, 16> RealArgs;
3004 RealArgs.append(std::begin(Args), std::end(Args));
3005 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
3006
James Y Knight9871db02019-02-05 16:42:33 +00003007 llvm::FunctionCallee RTLFn =
3008 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call);
Alexey Bataev2377fe92015-09-10 08:12:02 +00003009 CGF.EmitRuntimeCall(RTLFn, RealArgs);
3010 };
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003011 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF,
3012 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003013 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
3014 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc);
Alexey Bataev1d677132015-04-22 13:57:31 +00003015 // Build calls:
3016 // __kmpc_serialized_parallel(&Loc, GTid);
3017 llvm::Value *Args[] = {RTLoc, ThreadID};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003018 CGF.EmitRuntimeCall(
3019 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +00003020
Alexey Bataev1d677132015-04-22 13:57:31 +00003021 // OutlinedFn(&GTid, &zero, CapturedStruct);
Alexey Bataev18fa2322018-05-02 14:20:50 +00003022 Address ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty,
3023 /*Name*/ ".zero.addr");
Alexey Bataev1d677132015-04-22 13:57:31 +00003024 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
Alexey Bataev2377fe92015-09-10 08:12:02 +00003025 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
Alexey Bataev8521ff62018-07-25 20:03:01 +00003026 // ThreadId for serialized parallels is 0.
3027 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
Alexey Bataev2377fe92015-09-10 08:12:02 +00003028 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
3029 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
Alexey Bataev3c595a62017-08-14 15:01:03 +00003030 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +00003031
Alexey Bataev1d677132015-04-22 13:57:31 +00003032 // __kmpc_end_serialized_parallel(&Loc, GTid);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003033 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID};
Alexey Bataev1d677132015-04-22 13:57:31 +00003034 CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003035 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel),
3036 EndArgs);
Alexey Bataev1d677132015-04-22 13:57:31 +00003037 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003038 if (IfCond) {
Alexey Bataev1d677132015-04-22 13:57:31 +00003039 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003040 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003041 RegionCodeGenTy ThenRCG(ThenGen);
3042 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00003043 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00003044}
3045
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00003046// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +00003047// thread-ID variable (it is passed in a first argument of the outlined function
3048// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
3049// regular serial code region, get thread ID by calling kmp_int32
3050// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
3051// return the address of that temp.
John McCall7f416cc2015-09-08 08:05:57 +00003052Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
3053 SourceLocation Loc) {
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003054 if (auto *OMPRegionInfo =
Alexey Bataevd74d0602014-10-13 06:02:40 +00003055 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003056 if (OMPRegionInfo->getThreadIDVariable())
Alexey Bataev62b63b12015-03-10 07:28:44 +00003057 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003058
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003059 llvm::Value *ThreadID = getThreadID(CGF, Loc);
3060 QualType Int32Ty =
Alexey Bataevd74d0602014-10-13 06:02:40 +00003061 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003062 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
Alexey Bataevd74d0602014-10-13 06:02:40 +00003063 CGF.EmitStoreOfScalar(ThreadID,
John McCall7f416cc2015-09-08 08:05:57 +00003064 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
Alexey Bataevd74d0602014-10-13 06:02:40 +00003065
3066 return ThreadIDTemp;
3067}
3068
Alexey Bataev1af5bd52019-03-05 17:47:18 +00003069llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable(
3070 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003071 SmallString<256> Buffer;
3072 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00003073 Out << Name;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003074 StringRef RuntimeName = Out.str();
Alexey Bataev43a919f2018-04-13 17:48:43 +00003075 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first;
David Blaikie13156b62014-11-19 03:06:06 +00003076 if (Elem.second) {
3077 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00003078 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00003079 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00003080 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003081
David Blaikie13156b62014-11-19 03:06:06 +00003082 return Elem.second = new llvm::GlobalVariable(
3083 CGM.getModule(), Ty, /*IsConstant*/ false,
3084 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
Alexey Bataev1af5bd52019-03-05 17:47:18 +00003085 Elem.first(), /*InsertBefore=*/nullptr,
3086 llvm::GlobalValue::NotThreadLocal, AddressSpace);
Alexey Bataev97720002014-11-11 04:05:39 +00003087}
3088
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003089llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev18fa2322018-05-02 14:20:50 +00003090 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str();
3091 std::string Name = getName({Prefix, "var"});
3092 return getOrCreateInternalVariable(KmpCriticalNameTy, Name);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003093}
3094
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003095namespace {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003096/// Common pre(post)-action for different OpenMP constructs.
3097class CommonActionTy final : public PrePostActionTy {
James Y Knight9871db02019-02-05 16:42:33 +00003098 llvm::FunctionCallee EnterCallee;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003099 ArrayRef<llvm::Value *> EnterArgs;
James Y Knight9871db02019-02-05 16:42:33 +00003100 llvm::FunctionCallee ExitCallee;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003101 ArrayRef<llvm::Value *> ExitArgs;
3102 bool Conditional;
3103 llvm::BasicBlock *ContBlock = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003104
3105public:
James Y Knight9871db02019-02-05 16:42:33 +00003106 CommonActionTy(llvm::FunctionCallee EnterCallee,
3107 ArrayRef<llvm::Value *> EnterArgs,
3108 llvm::FunctionCallee ExitCallee,
3109 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003110 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
3111 ExitArgs(ExitArgs), Conditional(Conditional) {}
3112 void Enter(CodeGenFunction &CGF) override {
3113 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs);
3114 if (Conditional) {
3115 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes);
3116 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
3117 ContBlock = CGF.createBasicBlock("omp_if.end");
3118 // Generate the branch (If-stmt)
3119 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
3120 CGF.EmitBlock(ThenBlock);
3121 }
Alexey Bataeva744ff52015-05-05 09:24:37 +00003122 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003123 void Done(CodeGenFunction &CGF) {
3124 // Emit the rest of blocks/branches
3125 CGF.EmitBranch(ContBlock);
3126 CGF.EmitBlock(ContBlock, true);
3127 }
3128 void Exit(CodeGenFunction &CGF) override {
3129 CGF.EmitRuntimeCall(ExitCallee, ExitArgs);
Alexey Bataev3e6124b2015-04-10 07:48:12 +00003130 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003131};
Hans Wennborg7eb54642015-09-10 17:07:54 +00003132} // anonymous namespace
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003133
3134void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
3135 StringRef CriticalName,
3136 const RegionCodeGenTy &CriticalOpGen,
Alexey Bataevfc57d162015-12-15 10:55:09 +00003137 SourceLocation Loc, const Expr *Hint) {
3138 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
Alexey Bataev75ddfab2014-12-01 11:32:38 +00003139 // CriticalOpGen();
3140 // __kmpc_end_critical(ident_t *, gtid, Lock);
3141 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev8ef31412015-12-18 07:58:25 +00003142 if (!CGF.HaveInsertPoint())
3143 return;
Alexey Bataevfc57d162015-12-15 10:55:09 +00003144 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3145 getCriticalRegionLock(CriticalName)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003146 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args),
3147 std::end(Args));
Alexey Bataevfc57d162015-12-15 10:55:09 +00003148 if (Hint) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003149 EnterArgs.push_back(CGF.Builder.CreateIntCast(
3150 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false));
3151 }
3152 CommonActionTy Action(
3153 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint
3154 : OMPRTL__kmpc_critical),
3155 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args);
3156 CriticalOpGen.setAction(Action);
Alexey Bataevfc57d162015-12-15 10:55:09 +00003157 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003158}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003159
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003160void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003161 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003162 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003163 if (!CGF.HaveInsertPoint())
3164 return;
Alexey Bataev8d690652014-12-04 07:23:53 +00003165 // if(__kmpc_master(ident_t *, gtid)) {
3166 // MasterOpGen();
3167 // __kmpc_end_master(ident_t *, gtid);
3168 // }
3169 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00003170 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003171 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args,
3172 createRuntimeFunction(OMPRTL__kmpc_end_master), Args,
3173 /*Conditional=*/true);
3174 MasterOpGen.setAction(Action);
3175 emitInlinedDirective(CGF, OMPD_master, MasterOpGen);
3176 Action.Done(CGF);
Alexey Bataev8d690652014-12-04 07:23:53 +00003177}
3178
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003179void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
3180 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003181 if (!CGF.HaveInsertPoint())
3182 return;
Alexey Bataev9f797f32015-02-05 05:57:51 +00003183 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
3184 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003185 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00003186 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003187 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00003188 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
3189 Region->emitUntiedSwitch(CGF);
Alexey Bataev9f797f32015-02-05 05:57:51 +00003190}
3191
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003192void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
3193 const RegionCodeGenTy &TaskgroupOpGen,
3194 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003195 if (!CGF.HaveInsertPoint())
3196 return;
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003197 // __kmpc_taskgroup(ident_t *, gtid);
3198 // TaskgroupOpGen();
3199 // __kmpc_end_taskgroup(ident_t *, gtid);
3200 // Prepare arguments and build a call to __kmpc_taskgroup
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003201 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
3202 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args,
3203 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
3204 Args);
3205 TaskgroupOpGen.setAction(Action);
3206 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003207}
3208
John McCall7f416cc2015-09-08 08:05:57 +00003209/// Given an array of pointers to variables, project the address of a
3210/// given variable.
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003211static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
3212 unsigned Index, const VarDecl *Var) {
John McCall7f416cc2015-09-08 08:05:57 +00003213 // Pull out the pointer to the variable.
James Y Knight751fe282019-02-09 22:22:28 +00003214 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index);
John McCall7f416cc2015-09-08 08:05:57 +00003215 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
3216
3217 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003218 Addr = CGF.Builder.CreateElementBitCast(
3219 Addr, CGF.ConvertTypeForMem(Var->getType()));
John McCall7f416cc2015-09-08 08:05:57 +00003220 return Addr;
3221}
3222
Alexey Bataeva63048e2015-03-23 06:18:07 +00003223static llvm::Value *emitCopyprivateCopyFunction(
Alexey Bataev420d45b2015-04-14 05:11:24 +00003224 CodeGenModule &CGM, llvm::Type *ArgsType,
3225 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003226 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps,
3227 SourceLocation Loc) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003228 ASTContext &C = CGM.getContext();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003229 // void copy_func(void *LHSArg, void *RHSArg);
3230 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003231 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3232 ImplicitParamDecl::Other);
3233 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3234 ImplicitParamDecl::Other);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003235 Args.push_back(&LHSArg);
3236 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003237 const auto &CGFI =
3238 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00003239 std::string Name =
3240 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"});
3241 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
3242 llvm::GlobalValue::InternalLinkage, Name,
3243 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00003244 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00003245 Fn->setDoesNotRecurse();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003246 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003247 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev420d45b2015-04-14 05:11:24 +00003248 // Dest = (void*[n])(LHSArg);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003249 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00003250 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3251 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
3252 ArgsType), CGF.getPointerAlign());
3253 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3254 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
3255 ArgsType), CGF.getPointerAlign());
Alexey Bataeva63048e2015-03-23 06:18:07 +00003256 // *(Type0*)Dst[0] = *(Type0*)Src[0];
3257 // *(Type1*)Dst[1] = *(Type1*)Src[1];
3258 // ...
3259 // *(Typen*)Dst[n] = *(Typen*)Src[n];
Alexey Bataeva63048e2015-03-23 06:18:07 +00003260 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003261 const auto *DestVar =
3262 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +00003263 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
3264
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003265 const auto *SrcVar =
3266 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +00003267 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
3268
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003269 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003270 QualType Type = VD->getType();
John McCall7f416cc2015-09-08 08:05:57 +00003271 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003272 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00003273 CGF.FinishFunction();
3274 return Fn;
3275}
3276
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003277void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003278 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00003279 SourceLocation Loc,
3280 ArrayRef<const Expr *> CopyprivateVars,
3281 ArrayRef<const Expr *> SrcExprs,
3282 ArrayRef<const Expr *> DstExprs,
3283 ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003284 if (!CGF.HaveInsertPoint())
3285 return;
Alexey Bataeva63048e2015-03-23 06:18:07 +00003286 assert(CopyprivateVars.size() == SrcExprs.size() &&
3287 CopyprivateVars.size() == DstExprs.size() &&
3288 CopyprivateVars.size() == AssignmentOps.size());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003289 ASTContext &C = CGM.getContext();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003290 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003291 // if(__kmpc_single(ident_t *, gtid)) {
3292 // SingleOpGen();
3293 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003294 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003295 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00003296 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3297 // <copy_func>, did_it);
3298
John McCall7f416cc2015-09-08 08:05:57 +00003299 Address DidIt = Address::invalid();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003300 if (!CopyprivateVars.empty()) {
3301 // int32 did_it = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003302 QualType KmpInt32Ty =
3303 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003304 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
John McCall7f416cc2015-09-08 08:05:57 +00003305 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003306 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003307 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00003308 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003309 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args,
3310 createRuntimeFunction(OMPRTL__kmpc_end_single), Args,
3311 /*Conditional=*/true);
3312 SingleOpGen.setAction(Action);
3313 emitInlinedDirective(CGF, OMPD_single, SingleOpGen);
3314 if (DidIt.isValid()) {
3315 // did_it = 1;
3316 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
3317 }
3318 Action.Done(CGF);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003319 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3320 // <copy_func>, did_it);
John McCall7f416cc2015-09-08 08:05:57 +00003321 if (DidIt.isValid()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00003322 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003323 QualType CopyprivateArrayTy =
Alexey Bataeva63048e2015-03-23 06:18:07 +00003324 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
3325 /*IndexTypeQuals=*/0);
3326 // Create a list of all private variables for copyprivate.
John McCall7f416cc2015-09-08 08:05:57 +00003327 Address CopyprivateList =
Alexey Bataeva63048e2015-03-23 06:18:07 +00003328 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
3329 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +00003330 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I);
John McCall7f416cc2015-09-08 08:05:57 +00003331 CGF.Builder.CreateStore(
Alexey Bataeva63048e2015-03-23 06:18:07 +00003332 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00003333 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy),
3334 Elem);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003335 }
3336 // Build function that copies private values from single region to all other
3337 // threads in the corresponding parallel region.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003338 llvm::Value *CpyFn = emitCopyprivateCopyFunction(
Alexey Bataeva63048e2015-03-23 06:18:07 +00003339 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003340 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003341 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00003342 Address CL =
3343 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
3344 CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003345 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003346 llvm::Value *Args[] = {
3347 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
3348 getThreadID(CGF, Loc), // i32 <gtid>
Alexey Bataev66beaa92015-04-30 03:47:32 +00003349 BufSize, // size_t <buf_size>
John McCall7f416cc2015-09-08 08:05:57 +00003350 CL.getPointer(), // void *<copyprivate list>
Alexey Bataeva63048e2015-03-23 06:18:07 +00003351 CpyFn, // void (*) (void *, void *) <copy_func>
3352 DidItVal // i32 did_it
3353 };
3354 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
3355 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003356}
3357
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003358void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
3359 const RegionCodeGenTy &OrderedOpGen,
Alexey Bataev5f600d62015-09-29 03:48:57 +00003360 SourceLocation Loc, bool IsThreads) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003361 if (!CGF.HaveInsertPoint())
3362 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003363 // __kmpc_ordered(ident_t *, gtid);
3364 // OrderedOpGen();
3365 // __kmpc_end_ordered(ident_t *, gtid);
3366 // Prepare arguments and build a call to __kmpc_ordered
Alexey Bataev5f600d62015-09-29 03:48:57 +00003367 if (IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003368 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003369 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args,
3370 createRuntimeFunction(OMPRTL__kmpc_end_ordered),
3371 Args);
3372 OrderedOpGen.setAction(Action);
3373 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
3374 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003375 }
Alexey Bataev5f600d62015-09-29 03:48:57 +00003376 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003377}
3378
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003379unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) {
Alexey Bataev50b3c952016-02-19 10:38:26 +00003380 unsigned Flags;
3381 if (Kind == OMPD_for)
3382 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
3383 else if (Kind == OMPD_sections)
3384 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
3385 else if (Kind == OMPD_single)
3386 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
3387 else if (Kind == OMPD_barrier)
3388 Flags = OMP_IDENT_BARRIER_EXPL;
3389 else
3390 Flags = OMP_IDENT_BARRIER_IMPL;
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003391 return Flags;
3392}
3393
Alexey Bataevf6a53d62019-03-18 18:40:00 +00003394void CGOpenMPRuntime::getDefaultScheduleAndChunk(
3395 CodeGenFunction &CGF, const OMPLoopDirective &S,
3396 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const {
3397 // Check if the loop directive is actually a doacross loop directive. In this
3398 // case choose static, 1 schedule.
3399 if (llvm::any_of(
3400 S.getClausesOfKind<OMPOrderedClause>(),
3401 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) {
3402 ScheduleKind = OMPC_SCHEDULE_static;
3403 // Chunk size is 1 in this case.
3404 llvm::APInt ChunkSize(32, 1);
3405 ChunkExpr = IntegerLiteral::Create(
3406 CGF.getContext(), ChunkSize,
3407 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
3408 SourceLocation());
3409 }
3410}
3411
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003412void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
3413 OpenMPDirectiveKind Kind, bool EmitChecks,
3414 bool ForceSimpleCall) {
3415 if (!CGF.HaveInsertPoint())
3416 return;
3417 // Build call __kmpc_cancel_barrier(loc, thread_id);
3418 // Build call __kmpc_barrier(loc, thread_id);
3419 unsigned Flags = getDefaultFlagsForBarriers(Kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003420 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
3421 // thread_id);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003422 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
3423 getThreadID(CGF, Loc)};
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003424 if (auto *OMPRegionInfo =
3425 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00003426 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003427 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003428 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev25e5b442015-09-15 12:52:43 +00003429 if (EmitChecks) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003430 // if (__kmpc_cancel_barrier()) {
3431 // exit from construct;
3432 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003433 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
3434 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
3435 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003436 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
3437 CGF.EmitBlock(ExitBB);
3438 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003439 CodeGenFunction::JumpDest CancelDestination =
Alexey Bataev25e5b442015-09-15 12:52:43 +00003440 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003441 CGF.EmitBranchThroughCleanup(CancelDestination);
3442 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
3443 }
3444 return;
3445 }
3446 }
3447 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003448}
3449
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003450/// Map the OpenMP loop schedule to the runtime enumeration.
Alexander Musmanc6388682014-12-15 07:07:06 +00003451static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003452 bool Chunked, bool Ordered) {
Alexander Musmanc6388682014-12-15 07:07:06 +00003453 switch (ScheduleKind) {
3454 case OMPC_SCHEDULE_static:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003455 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
3456 : (Ordered ? OMP_ord_static : OMP_sch_static);
Alexander Musmanc6388682014-12-15 07:07:06 +00003457 case OMPC_SCHEDULE_dynamic:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003458 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00003459 case OMPC_SCHEDULE_guided:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003460 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00003461 case OMPC_SCHEDULE_runtime:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003462 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
3463 case OMPC_SCHEDULE_auto:
3464 return Ordered ? OMP_ord_auto : OMP_sch_auto;
Alexander Musmanc6388682014-12-15 07:07:06 +00003465 case OMPC_SCHEDULE_unknown:
3466 assert(!Chunked && "chunk was specified but schedule kind not known");
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003467 return Ordered ? OMP_ord_static : OMP_sch_static;
Alexander Musmanc6388682014-12-15 07:07:06 +00003468 }
3469 llvm_unreachable("Unexpected runtime schedule");
3470}
3471
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003472/// Map the OpenMP distribute schedule to the runtime enumeration.
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003473static OpenMPSchedType
3474getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
3475 // only static is allowed for dist_schedule
3476 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
3477}
3478
Alexander Musmanc6388682014-12-15 07:07:06 +00003479bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
3480 bool Chunked) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003481 OpenMPSchedType Schedule =
3482 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
Alexander Musmanc6388682014-12-15 07:07:06 +00003483 return Schedule == OMP_sch_static;
3484}
3485
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003486bool CGOpenMPRuntime::isStaticNonchunked(
3487 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003488 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003489 return Schedule == OMP_dist_sch_static;
3490}
3491
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00003492bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind,
3493 bool Chunked) const {
3494 OpenMPSchedType Schedule =
3495 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
3496 return Schedule == OMP_sch_static_chunked;
3497}
3498
3499bool CGOpenMPRuntime::isStaticChunked(
3500 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
3501 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
3502 return Schedule == OMP_dist_sch_static_chunked;
3503}
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003504
Alexander Musmandf7a8e22015-01-22 08:49:35 +00003505bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003506 OpenMPSchedType Schedule =
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003507 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00003508 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
3509 return Schedule != OMP_sch_static;
3510}
3511
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003512static int addMonoNonMonoModifier(OpenMPSchedType Schedule,
3513 OpenMPScheduleClauseModifier M1,
3514 OpenMPScheduleClauseModifier M2) {
Alexey Bataev6cff6242016-05-30 13:05:14 +00003515 int Modifier = 0;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003516 switch (M1) {
3517 case OMPC_SCHEDULE_MODIFIER_monotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003518 Modifier = OMP_sch_modifier_monotonic;
3519 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003520 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003521 Modifier = OMP_sch_modifier_nonmonotonic;
3522 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003523 case OMPC_SCHEDULE_MODIFIER_simd:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003524 if (Schedule == OMP_sch_static_chunked)
3525 Schedule = OMP_sch_static_balanced_chunked;
3526 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003527 case OMPC_SCHEDULE_MODIFIER_last:
3528 case OMPC_SCHEDULE_MODIFIER_unknown:
3529 break;
3530 }
3531 switch (M2) {
3532 case OMPC_SCHEDULE_MODIFIER_monotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003533 Modifier = OMP_sch_modifier_monotonic;
3534 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003535 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003536 Modifier = OMP_sch_modifier_nonmonotonic;
3537 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003538 case OMPC_SCHEDULE_MODIFIER_simd:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003539 if (Schedule == OMP_sch_static_chunked)
3540 Schedule = OMP_sch_static_balanced_chunked;
3541 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003542 case OMPC_SCHEDULE_MODIFIER_last:
3543 case OMPC_SCHEDULE_MODIFIER_unknown:
3544 break;
3545 }
Alexey Bataev6cff6242016-05-30 13:05:14 +00003546 return Schedule | Modifier;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003547}
3548
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003549void CGOpenMPRuntime::emitForDispatchInit(
3550 CodeGenFunction &CGF, SourceLocation Loc,
3551 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
3552 bool Ordered, const DispatchRTInput &DispatchValues) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003553 if (!CGF.HaveInsertPoint())
3554 return;
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003555 OpenMPSchedType Schedule = getRuntimeSchedule(
3556 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered);
John McCall7f416cc2015-09-08 08:05:57 +00003557 assert(Ordered ||
3558 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
Alexey Bataev6cff6242016-05-30 13:05:14 +00003559 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
3560 Schedule != OMP_sch_static_balanced_chunked));
John McCall7f416cc2015-09-08 08:05:57 +00003561 // Call __kmpc_dispatch_init(
3562 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
3563 // kmp_int[32|64] lower, kmp_int[32|64] upper,
3564 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00003565
John McCall7f416cc2015-09-08 08:05:57 +00003566 // If the Chunk was not specified in the clause - use default value 1.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003567 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk
3568 : CGF.Builder.getIntN(IVSize, 1);
John McCall7f416cc2015-09-08 08:05:57 +00003569 llvm::Value *Args[] = {
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003570 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3571 CGF.Builder.getInt32(addMonoNonMonoModifier(
3572 Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003573 DispatchValues.LB, // Lower
3574 DispatchValues.UB, // Upper
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003575 CGF.Builder.getIntN(IVSize, 1), // Stride
3576 Chunk // Chunk
John McCall7f416cc2015-09-08 08:05:57 +00003577 };
3578 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
3579}
3580
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003581static void emitForStaticInitCall(
3582 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
James Y Knight9871db02019-02-05 16:42:33 +00003583 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003584 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003585 const CGOpenMPRuntime::StaticRTInput &Values) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003586 if (!CGF.HaveInsertPoint())
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003587 return;
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003588
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003589 assert(!Values.Ordered);
3590 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
3591 Schedule == OMP_sch_static_balanced_chunked ||
3592 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
3593 Schedule == OMP_dist_sch_static ||
3594 Schedule == OMP_dist_sch_static_chunked);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003595
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003596 // Call __kmpc_for_static_init(
3597 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
3598 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
3599 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
3600 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
3601 llvm::Value *Chunk = Values.Chunk;
3602 if (Chunk == nullptr) {
3603 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
3604 Schedule == OMP_dist_sch_static) &&
3605 "expected static non-chunked schedule");
3606 // If the Chunk was not specified in the clause - use default value 1.
3607 Chunk = CGF.Builder.getIntN(Values.IVSize, 1);
3608 } else {
3609 assert((Schedule == OMP_sch_static_chunked ||
3610 Schedule == OMP_sch_static_balanced_chunked ||
3611 Schedule == OMP_ord_static_chunked ||
3612 Schedule == OMP_dist_sch_static_chunked) &&
3613 "expected static chunked schedule");
3614 }
3615 llvm::Value *Args[] = {
3616 UpdateLocation,
3617 ThreadId,
3618 CGF.Builder.getInt32(addMonoNonMonoModifier(Schedule, M1,
3619 M2)), // Schedule type
3620 Values.IL.getPointer(), // &isLastIter
3621 Values.LB.getPointer(), // &LB
3622 Values.UB.getPointer(), // &UB
3623 Values.ST.getPointer(), // &Stride
3624 CGF.Builder.getIntN(Values.IVSize, 1), // Incr
3625 Chunk // Chunk
3626 };
3627 CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003628}
3629
John McCall7f416cc2015-09-08 08:05:57 +00003630void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
3631 SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003632 OpenMPDirectiveKind DKind,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003633 const OpenMPScheduleTy &ScheduleKind,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003634 const StaticRTInput &Values) {
3635 OpenMPSchedType ScheduleNum = getRuntimeSchedule(
3636 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered);
3637 assert(isOpenMPWorksharingDirective(DKind) &&
3638 "Expected loop-based or sections-based directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003639 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003640 isOpenMPLoopDirective(DKind)
3641 ? OMP_IDENT_WORK_LOOP
3642 : OMP_IDENT_WORK_SECTIONS);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003643 llvm::Value *ThreadId = getThreadID(CGF, Loc);
James Y Knight9871db02019-02-05 16:42:33 +00003644 llvm::FunctionCallee StaticInitFunction =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003645 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003646 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003647 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003648}
John McCall7f416cc2015-09-08 08:05:57 +00003649
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003650void CGOpenMPRuntime::emitDistributeStaticInit(
3651 CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003652 OpenMPDistScheduleClauseKind SchedKind,
3653 const CGOpenMPRuntime::StaticRTInput &Values) {
3654 OpenMPSchedType ScheduleNum =
3655 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003656 llvm::Value *UpdatedLocation =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003657 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE);
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,
3662 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003663 OMPC_SCHEDULE_MODIFIER_unknown, Values);
Alexander Musmanc6388682014-12-15 07:07:06 +00003664}
3665
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003666void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
Alexey Bataevf43f7142017-09-06 16:17:35 +00003667 SourceLocation Loc,
3668 OpenMPDirectiveKind DKind) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003669 if (!CGF.HaveInsertPoint())
3670 return;
Alexander Musmanc6388682014-12-15 07:07:06 +00003671 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataevf43f7142017-09-06 16:17:35 +00003672 llvm::Value *Args[] = {
3673 emitUpdateLocation(CGF, Loc,
3674 isOpenMPDistributeDirective(DKind)
3675 ? OMP_IDENT_WORK_DISTRIBUTE
3676 : isOpenMPLoopDirective(DKind)
3677 ? OMP_IDENT_WORK_LOOP
3678 : OMP_IDENT_WORK_SECTIONS),
3679 getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003680 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
3681 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00003682}
3683
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003684void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
3685 SourceLocation Loc,
3686 unsigned IVSize,
3687 bool IVSigned) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003688 if (!CGF.HaveInsertPoint())
3689 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003690 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00003691 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003692 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
3693}
3694
Alexander Musman92bdaab2015-03-12 13:37:50 +00003695llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
3696 SourceLocation Loc, unsigned IVSize,
John McCall7f416cc2015-09-08 08:05:57 +00003697 bool IVSigned, Address IL,
3698 Address LB, Address UB,
3699 Address ST) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00003700 // Call __kmpc_dispatch_next(
3701 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
3702 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
3703 // kmp_int[32|64] *p_stride);
3704 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00003705 emitUpdateLocation(CGF, Loc),
3706 getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00003707 IL.getPointer(), // &isLastIter
3708 LB.getPointer(), // &Lower
3709 UB.getPointer(), // &Upper
3710 ST.getPointer() // &Stride
Alexander Musman92bdaab2015-03-12 13:37:50 +00003711 };
3712 llvm::Value *Call =
3713 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
3714 return CGF.EmitScalarConversion(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003715 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00003716 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00003717}
3718
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003719void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
3720 llvm::Value *NumThreads,
3721 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003722 if (!CGF.HaveInsertPoint())
3723 return;
Alexey Bataevb2059782014-10-13 08:23:51 +00003724 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
3725 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003726 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00003727 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003728 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
3729 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00003730}
3731
Alexey Bataev7f210c62015-06-18 13:40:03 +00003732void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
3733 OpenMPProcBindClauseKind ProcBind,
3734 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003735 if (!CGF.HaveInsertPoint())
3736 return;
Alexey Bataev7f210c62015-06-18 13:40:03 +00003737 // Constants for proc bind value accepted by the runtime.
3738 enum ProcBindTy {
3739 ProcBindFalse = 0,
3740 ProcBindTrue,
3741 ProcBindMaster,
3742 ProcBindClose,
3743 ProcBindSpread,
3744 ProcBindIntel,
3745 ProcBindDefault
3746 } RuntimeProcBind;
3747 switch (ProcBind) {
3748 case OMPC_PROC_BIND_master:
3749 RuntimeProcBind = ProcBindMaster;
3750 break;
3751 case OMPC_PROC_BIND_close:
3752 RuntimeProcBind = ProcBindClose;
3753 break;
3754 case OMPC_PROC_BIND_spread:
3755 RuntimeProcBind = ProcBindSpread;
3756 break;
3757 case OMPC_PROC_BIND_unknown:
3758 llvm_unreachable("Unsupported proc_bind value.");
3759 }
3760 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
3761 llvm::Value *Args[] = {
3762 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3763 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
3764 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
3765}
3766
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003767void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
3768 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003769 if (!CGF.HaveInsertPoint())
3770 return;
Alexey Bataevd76df6d2015-02-24 12:55:09 +00003771 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003772 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
3773 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00003774}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003775
Alexey Bataev62b63b12015-03-10 07:28:44 +00003776namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003777/// Indexes of fields for type kmp_task_t.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003778enum KmpTaskTFields {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003779 /// List of shared variables.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003780 KmpTaskTShareds,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003781 /// Task routine.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003782 KmpTaskTRoutine,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003783 /// Partition id for the untied tasks.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003784 KmpTaskTPartId,
Alexey Bataevad537bb2016-05-30 09:06:50 +00003785 /// Function with call of destructors for private variables.
3786 Data1,
3787 /// Task priority.
3788 Data2,
Alexey Bataev7292c292016-04-25 12:22:29 +00003789 /// (Taskloops only) Lower bound.
3790 KmpTaskTLowerBound,
3791 /// (Taskloops only) Upper bound.
3792 KmpTaskTUpperBound,
3793 /// (Taskloops only) Stride.
3794 KmpTaskTStride,
3795 /// (Taskloops only) Is last iteration flag.
3796 KmpTaskTLastIter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003797 /// (Taskloops only) Reduction data.
3798 KmpTaskTReductions,
Alexey Bataev62b63b12015-03-10 07:28:44 +00003799};
Hans Wennborg7eb54642015-09-10 17:07:54 +00003800} // anonymous namespace
Alexey Bataev62b63b12015-03-10 07:28:44 +00003801
Samuel Antaoee8fb302016-01-06 13:42:12 +00003802bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003803 return OffloadEntriesTargetRegion.empty() &&
3804 OffloadEntriesDeviceGlobalVar.empty();
Samuel Antaoee8fb302016-01-06 13:42:12 +00003805}
3806
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003807/// Initialize target region entry.
Samuel Antaoee8fb302016-01-06 13:42:12 +00003808void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3809 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3810 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00003811 unsigned Order) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003812 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
3813 "only required for the device "
3814 "code generation.");
Samuel Antao2de62b02016-02-13 23:35:10 +00003815 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
Samuel Antaof83efdb2017-01-05 16:02:49 +00003816 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003817 OMPTargetRegionEntryTargetRegion);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003818 ++OffloadingEntriesNum;
3819}
3820
3821void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3822 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3823 StringRef ParentName, unsigned LineNum,
Samuel Antaof83efdb2017-01-05 16:02:49 +00003824 llvm::Constant *Addr, llvm::Constant *ID,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003825 OMPTargetRegionEntryKind Flags) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003826 // If we are emitting code for a target, the entry is already initialized,
3827 // only has to be registered.
3828 if (CGM.getLangOpts().OpenMPIsDevice) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00003829 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) {
3830 unsigned DiagID = CGM.getDiags().getCustomDiagID(
3831 DiagnosticsEngine::Error,
3832 "Unable to find target region on line '%0' in the device code.");
3833 CGM.getDiags().Report(DiagID) << LineNum;
3834 return;
3835 }
Samuel Antao2de62b02016-02-13 23:35:10 +00003836 auto &Entry =
3837 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
Samuel Antaoee8fb302016-01-06 13:42:12 +00003838 assert(Entry.isValid() && "Entry not initialized!");
3839 Entry.setAddress(Addr);
3840 Entry.setID(ID);
Samuel Antaof83efdb2017-01-05 16:02:49 +00003841 Entry.setFlags(Flags);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003842 } else {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003843 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags);
Samuel Antao2de62b02016-02-13 23:35:10 +00003844 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00003845 ++OffloadingEntriesNum;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003846 }
3847}
3848
3849bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00003850 unsigned DeviceID, unsigned FileID, StringRef ParentName,
3851 unsigned LineNum) const {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003852 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
3853 if (PerDevice == OffloadEntriesTargetRegion.end())
3854 return false;
3855 auto PerFile = PerDevice->second.find(FileID);
3856 if (PerFile == PerDevice->second.end())
3857 return false;
3858 auto PerParentName = PerFile->second.find(ParentName);
3859 if (PerParentName == PerFile->second.end())
3860 return false;
3861 auto PerLine = PerParentName->second.find(LineNum);
3862 if (PerLine == PerParentName->second.end())
3863 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003864 // Fail if this entry is already registered.
Samuel Antao2de62b02016-02-13 23:35:10 +00003865 if (PerLine->second.getAddress() || PerLine->second.getID())
Samuel Antaoee8fb302016-01-06 13:42:12 +00003866 return false;
3867 return true;
3868}
3869
3870void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
3871 const OffloadTargetRegionEntryInfoActTy &Action) {
3872 // Scan all target region entries and perform the provided action.
Alexey Bataev03f270c2018-03-30 18:31:07 +00003873 for (const auto &D : OffloadEntriesTargetRegion)
3874 for (const auto &F : D.second)
3875 for (const auto &P : F.second)
3876 for (const auto &L : P.second)
Samuel Antao2de62b02016-02-13 23:35:10 +00003877 Action(D.first, F.first, P.first(), L.first, L.second);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003878}
3879
Alexey Bataev03f270c2018-03-30 18:31:07 +00003880void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3881 initializeDeviceGlobalVarEntryInfo(StringRef Name,
3882 OMPTargetGlobalVarEntryKind Flags,
3883 unsigned Order) {
3884 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
3885 "only required for the device "
3886 "code generation.");
3887 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
3888 ++OffloadingEntriesNum;
3889}
Samuel Antaoee8fb302016-01-06 13:42:12 +00003890
Alexey Bataev03f270c2018-03-30 18:31:07 +00003891void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3892 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr,
3893 CharUnits VarSize,
3894 OMPTargetGlobalVarEntryKind Flags,
3895 llvm::GlobalValue::LinkageTypes Linkage) {
3896 if (CGM.getLangOpts().OpenMPIsDevice) {
3897 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3898 assert(Entry.isValid() && Entry.getFlags() == Flags &&
3899 "Entry not initialized!");
3900 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
3901 "Resetting with the new address.");
Alexey Bataev8259cc32019-03-12 20:05:17 +00003902 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) {
3903 if (Entry.getVarSize().isZero()) {
3904 Entry.setVarSize(VarSize);
3905 Entry.setLinkage(Linkage);
3906 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003907 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00003908 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003909 Entry.setVarSize(VarSize);
3910 Entry.setLinkage(Linkage);
Alexey Bataev8259cc32019-03-12 20:05:17 +00003911 Entry.setAddress(Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00003912 } else {
Alexey Bataev8259cc32019-03-12 20:05:17 +00003913 if (hasDeviceGlobalVarEntryInfo(VarName)) {
3914 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3915 assert(Entry.isValid() && Entry.getFlags() == Flags &&
3916 "Entry not initialized!");
3917 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
3918 "Resetting with the new address.");
3919 if (Entry.getVarSize().isZero()) {
3920 Entry.setVarSize(VarSize);
3921 Entry.setLinkage(Linkage);
3922 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003923 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00003924 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003925 OffloadEntriesDeviceGlobalVar.try_emplace(
3926 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage);
3927 ++OffloadingEntriesNum;
3928 }
3929}
3930
3931void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3932 actOnDeviceGlobalVarEntriesInfo(
3933 const OffloadDeviceGlobalVarEntryInfoActTy &Action) {
3934 // Scan all target region entries and perform the provided action.
3935 for (const auto &E : OffloadEntriesDeviceGlobalVar)
3936 Action(E.getKey(), E.getValue());
Samuel Antaoee8fb302016-01-06 13:42:12 +00003937}
3938
3939llvm::Function *
3940CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003941 // If we don't have entries or if we are emitting code for the device, we
3942 // don't need to do anything.
3943 if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty())
3944 return nullptr;
3945
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003946 llvm::Module &M = CGM.getModule();
3947 ASTContext &C = CGM.getContext();
Samuel Antaoee8fb302016-01-06 13:42:12 +00003948
3949 // Get list of devices we care about
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003950 const std::vector<llvm::Triple> &Devices = CGM.getLangOpts().OMPTargetTriples;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003951
3952 // We should be creating an offloading descriptor only if there are devices
3953 // specified.
3954 assert(!Devices.empty() && "No OpenMP offloading devices??");
3955
3956 // Create the external variables that will point to the begin and end of the
3957 // host entries section. These will be defined by the linker.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003958 llvm::Type *OffloadEntryTy =
Samuel Antaoee8fb302016-01-06 13:42:12 +00003959 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy());
Alexey Bataev18fa2322018-05-02 14:20:50 +00003960 std::string EntriesBeginName = getName({"omp_offloading", "entries_begin"});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003961 auto *HostEntriesBegin = new llvm::GlobalVariable(
Samuel Antaoee8fb302016-01-06 13:42:12 +00003962 M, OffloadEntryTy, /*isConstant=*/true,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00003963 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr,
Alexey Bataev18fa2322018-05-02 14:20:50 +00003964 EntriesBeginName);
3965 std::string EntriesEndName = getName({"omp_offloading", "entries_end"});
3966 auto *HostEntriesEnd =
3967 new llvm::GlobalVariable(M, OffloadEntryTy, /*isConstant=*/true,
3968 llvm::GlobalValue::ExternalLinkage,
3969 /*Initializer=*/nullptr, EntriesEndName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003970
3971 // Create all device images
Samuel Antaoee8fb302016-01-06 13:42:12 +00003972 auto *DeviceImageTy = cast<llvm::StructType>(
3973 CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy()));
John McCall23c9dc62016-11-28 22:18:27 +00003974 ConstantInitBuilder DeviceImagesBuilder(CGM);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003975 ConstantArrayBuilder DeviceImagesEntries =
3976 DeviceImagesBuilder.beginArray(DeviceImageTy);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003977
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003978 for (const llvm::Triple &Device : Devices) {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003979 StringRef T = Device.getTriple();
Alexey Bataev18fa2322018-05-02 14:20:50 +00003980 std::string BeginName = getName({"omp_offloading", "img_start", ""});
Samuel Antaoee8fb302016-01-06 13:42:12 +00003981 auto *ImgBegin = new llvm::GlobalVariable(
Alexey Bataev62a4cb02018-07-31 18:27:42 +00003982 M, CGM.Int8Ty, /*isConstant=*/true,
3983 llvm::GlobalValue::ExternalWeakLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00003984 /*Initializer=*/nullptr, Twine(BeginName).concat(T));
3985 std::string EndName = getName({"omp_offloading", "img_end", ""});
Samuel Antaoee8fb302016-01-06 13:42:12 +00003986 auto *ImgEnd = new llvm::GlobalVariable(
Alexey Bataev62a4cb02018-07-31 18:27:42 +00003987 M, CGM.Int8Ty, /*isConstant=*/true,
3988 llvm::GlobalValue::ExternalWeakLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00003989 /*Initializer=*/nullptr, Twine(EndName).concat(T));
Samuel Antaoee8fb302016-01-06 13:42:12 +00003990
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003991 llvm::Constant *Data[] = {ImgBegin, ImgEnd, HostEntriesBegin,
3992 HostEntriesEnd};
3993 createConstantGlobalStructAndAddToParent(CGM, getTgtDeviceImageQTy(), Data,
3994 DeviceImagesEntries);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003995 }
3996
3997 // Create device images global array.
Alexey Bataev18fa2322018-05-02 14:20:50 +00003998 std::string ImagesName = getName({"omp_offloading", "device_images"});
John McCall6c9f1fdb2016-11-19 08:17:24 +00003999 llvm::GlobalVariable *DeviceImages =
Alexey Bataev18fa2322018-05-02 14:20:50 +00004000 DeviceImagesEntries.finishAndCreateGlobal(ImagesName,
4001 CGM.getPointerAlign(),
4002 /*isConstant=*/true);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00004003 DeviceImages->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004004
4005 // This is a Zero array to be used in the creation of the constant expressions
4006 llvm::Constant *Index[] = {llvm::Constant::getNullValue(CGM.Int32Ty),
4007 llvm::Constant::getNullValue(CGM.Int32Ty)};
4008
4009 // Create the target region descriptor.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004010 llvm::Constant *Data[] = {
4011 llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()),
4012 llvm::ConstantExpr::getGetElementPtr(DeviceImages->getValueType(),
4013 DeviceImages, Index),
4014 HostEntriesBegin, HostEntriesEnd};
Alexey Bataev18fa2322018-05-02 14:20:50 +00004015 std::string Descriptor = getName({"omp_offloading", "descriptor"});
Mike Ricee1ca7b62018-08-29 15:45:11 +00004016 llvm::GlobalVariable *Desc = createGlobalStruct(
4017 CGM, getTgtBinaryDescriptorQTy(), /*IsConstant=*/true, Data, Descriptor);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004018
4019 // Emit code to register or unregister the descriptor at execution
4020 // startup or closing, respectively.
4021
Alexey Bataev03f270c2018-03-30 18:31:07 +00004022 llvm::Function *UnRegFn;
4023 {
4024 FunctionArgList Args;
4025 ImplicitParamDecl DummyPtr(C, C.VoidPtrTy, ImplicitParamDecl::Other);
4026 Args.push_back(&DummyPtr);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004027
Alexey Bataev03f270c2018-03-30 18:31:07 +00004028 CodeGenFunction CGF(CGM);
4029 // Disable debug info for global (de-)initializer because they are not part
4030 // of some particular construct.
4031 CGF.disableDebugInfo();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004032 const auto &FI =
4033 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
4034 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004035 std::string UnregName = getName({"omp_offloading", "descriptor_unreg"});
4036 UnRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, UnregName, FI);
Alexey Bataev03f270c2018-03-30 18:31:07 +00004037 CGF.StartFunction(GlobalDecl(), C.VoidTy, UnRegFn, FI, Args);
4038 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_unregister_lib),
4039 Desc);
4040 CGF.FinishFunction();
4041 }
4042 llvm::Function *RegFn;
4043 {
4044 CodeGenFunction CGF(CGM);
4045 // Disable debug info for global (de-)initializer because they are not part
4046 // of some particular construct.
4047 CGF.disableDebugInfo();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004048 const auto &FI = CGM.getTypes().arrangeNullaryFunction();
Alexey Bataev03f270c2018-03-30 18:31:07 +00004049 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Sergey Dmitrievbde9cf92018-08-03 20:19:28 +00004050
4051 // Encode offload target triples into the registration function name. It
4052 // will serve as a comdat key for the registration/unregistration code for
4053 // this particular combination of offloading targets.
4054 SmallVector<StringRef, 4U> RegFnNameParts(Devices.size() + 2U);
4055 RegFnNameParts[0] = "omp_offloading";
4056 RegFnNameParts[1] = "descriptor_reg";
4057 llvm::transform(Devices, std::next(RegFnNameParts.begin(), 2),
4058 [](const llvm::Triple &T) -> const std::string& {
4059 return T.getTriple();
4060 });
4061 llvm::sort(std::next(RegFnNameParts.begin(), 2), RegFnNameParts.end());
4062 std::string Descriptor = getName(RegFnNameParts);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004063 RegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, Descriptor, FI);
Alexey Bataev03f270c2018-03-30 18:31:07 +00004064 CGF.StartFunction(GlobalDecl(), C.VoidTy, RegFn, FI, FunctionArgList());
4065 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_lib), Desc);
4066 // Create a variable to drive the registration and unregistration of the
4067 // descriptor, so we can reuse the logic that emits Ctors and Dtors.
4068 ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(),
4069 SourceLocation(), nullptr, C.CharTy,
4070 ImplicitParamDecl::Other);
4071 CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc);
4072 CGF.FinishFunction();
4073 }
George Rokos29d0f002017-05-27 03:03:13 +00004074 if (CGM.supportsCOMDAT()) {
4075 // It is sufficient to call registration function only once, so create a
4076 // COMDAT group for registration/unregistration functions and associated
4077 // data. That would reduce startup time and code size. Registration
4078 // function serves as a COMDAT group key.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004079 llvm::Comdat *ComdatKey = M.getOrInsertComdat(RegFn->getName());
George Rokos29d0f002017-05-27 03:03:13 +00004080 RegFn->setLinkage(llvm::GlobalValue::LinkOnceAnyLinkage);
4081 RegFn->setVisibility(llvm::GlobalValue::HiddenVisibility);
4082 RegFn->setComdat(ComdatKey);
4083 UnRegFn->setComdat(ComdatKey);
4084 DeviceImages->setComdat(ComdatKey);
4085 Desc->setComdat(ComdatKey);
4086 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004087 return RegFn;
4088}
4089
Alexey Bataev03f270c2018-03-30 18:31:07 +00004090void CGOpenMPRuntime::createOffloadEntry(
4091 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags,
4092 llvm::GlobalValue::LinkageTypes Linkage) {
Samuel Antao2de62b02016-02-13 23:35:10 +00004093 StringRef Name = Addr->getName();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004094 llvm::Module &M = CGM.getModule();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004095 llvm::LLVMContext &C = M.getContext();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004096
4097 // Create constant string with the name.
4098 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
4099
Alexey Bataev18fa2322018-05-02 14:20:50 +00004100 std::string StringName = getName({"omp_offloading", "entry_name"});
4101 auto *Str = new llvm::GlobalVariable(
4102 M, StrPtrInit->getType(), /*isConstant=*/true,
4103 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00004104 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004105
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004106 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy),
4107 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy),
4108 llvm::ConstantInt::get(CGM.SizeTy, Size),
4109 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
4110 llvm::ConstantInt::get(CGM.Int32Ty, 0)};
Alexey Bataev18fa2322018-05-02 14:20:50 +00004111 std::string EntryName = getName({"omp_offloading", "entry", ""});
Mike Ricee1ca7b62018-08-29 15:45:11 +00004112 llvm::GlobalVariable *Entry = createGlobalStruct(
4113 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data,
4114 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004115
4116 // The entry has to be created in the section the linker expects it to be.
Alexey Bataev18fa2322018-05-02 14:20:50 +00004117 std::string Section = getName({"omp_offloading", "entries"});
4118 Entry->setSection(Section);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004119}
4120
4121void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
4122 // Emit the offloading entries and metadata so that the device codegen side
Samuel Antao4c8035b2016-12-12 18:00:20 +00004123 // can easily figure out what to emit. The produced metadata looks like
4124 // this:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004125 //
4126 // !omp_offload.info = !{!1, ...}
4127 //
4128 // Right now we only generate metadata for function that contain target
4129 // regions.
4130
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00004131 // If we do not have entries, we don't need to do anything.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004132 if (OffloadEntriesInfoManager.empty())
4133 return;
4134
4135 llvm::Module &M = CGM.getModule();
4136 llvm::LLVMContext &C = M.getContext();
Alexey Bataev03f270c2018-03-30 18:31:07 +00004137 SmallVector<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16>
Samuel Antaoee8fb302016-01-06 13:42:12 +00004138 OrderedEntries(OffloadEntriesInfoManager.size());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004139 llvm::SmallVector<StringRef, 16> ParentFunctions(
4140 OffloadEntriesInfoManager.size());
Samuel Antaoee8fb302016-01-06 13:42:12 +00004141
Simon Pilgrim2c518802017-03-30 14:13:19 +00004142 // Auxiliary methods to create metadata values and strings.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004143 auto &&GetMDInt = [this](unsigned V) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004144 return llvm::ConstantAsMetadata::get(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004145 llvm::ConstantInt::get(CGM.Int32Ty, V));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004146 };
4147
Alexey Bataev03f270c2018-03-30 18:31:07 +00004148 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); };
4149
4150 // Create the offloading info metadata node.
4151 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004152
4153 // Create function that emits metadata for each target region entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00004154 auto &&TargetRegionMetadataEmitter =
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004155 [&C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, &GetMDString](
Alexey Bataev03f270c2018-03-30 18:31:07 +00004156 unsigned DeviceID, unsigned FileID, StringRef ParentName,
4157 unsigned Line,
4158 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
4159 // Generate metadata for target regions. Each entry of this metadata
4160 // contains:
4161 // - Entry 0 -> Kind of this type of metadata (0).
4162 // - Entry 1 -> Device ID of the file where the entry was identified.
4163 // - Entry 2 -> File ID of the file where the entry was identified.
4164 // - Entry 3 -> Mangled name of the function where the entry was
4165 // identified.
4166 // - Entry 4 -> Line in the file where the entry was identified.
4167 // - Entry 5 -> Order the entry was created.
4168 // The first element of the metadata node is the kind.
4169 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID),
4170 GetMDInt(FileID), GetMDString(ParentName),
4171 GetMDInt(Line), GetMDInt(E.getOrder())};
Samuel Antaoee8fb302016-01-06 13:42:12 +00004172
Alexey Bataev03f270c2018-03-30 18:31:07 +00004173 // Save this entry in the right position of the ordered entries array.
4174 OrderedEntries[E.getOrder()] = &E;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004175 ParentFunctions[E.getOrder()] = ParentName;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004176
Alexey Bataev03f270c2018-03-30 18:31:07 +00004177 // Add metadata to the named metadata node.
4178 MD->addOperand(llvm::MDNode::get(C, Ops));
4179 };
Samuel Antaoee8fb302016-01-06 13:42:12 +00004180
4181 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
4182 TargetRegionMetadataEmitter);
4183
Alexey Bataev03f270c2018-03-30 18:31:07 +00004184 // Create function that emits metadata for each device global variable entry;
4185 auto &&DeviceGlobalVarMetadataEmitter =
4186 [&C, &OrderedEntries, &GetMDInt, &GetMDString,
4187 MD](StringRef MangledName,
4188 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar
4189 &E) {
4190 // Generate metadata for global variables. Each entry of this metadata
4191 // contains:
4192 // - Entry 0 -> Kind of this type of metadata (1).
4193 // - Entry 1 -> Mangled name of the variable.
4194 // - Entry 2 -> Declare target kind.
4195 // - Entry 3 -> Order the entry was created.
4196 // The first element of the metadata node is the kind.
4197 llvm::Metadata *Ops[] = {
4198 GetMDInt(E.getKind()), GetMDString(MangledName),
4199 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
4200
4201 // Save this entry in the right position of the ordered entries array.
4202 OrderedEntries[E.getOrder()] = &E;
4203
4204 // Add metadata to the named metadata node.
4205 MD->addOperand(llvm::MDNode::get(C, Ops));
4206 };
4207
4208 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo(
4209 DeviceGlobalVarMetadataEmitter);
4210
4211 for (const auto *E : OrderedEntries) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004212 assert(E && "All ordered entries must exist!");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004213 if (const auto *CE =
Samuel Antaoee8fb302016-01-06 13:42:12 +00004214 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
4215 E)) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004216 if (!CE->getID() || !CE->getAddress()) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004217 // Do not blame the entry if the parent funtion is not emitted.
4218 StringRef FnName = ParentFunctions[CE->getOrder()];
4219 if (!CGM.GetGlobalValue(FnName))
4220 continue;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004221 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4222 DiagnosticsEngine::Error,
Alexey Bataev7f01d202018-07-16 18:12:18 +00004223 "Offloading entry for target region is incorrect: either the "
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004224 "address or the ID is invalid.");
4225 CGM.getDiags().Report(DiagID);
4226 continue;
4227 }
Alexey Bataev34f8a702018-03-28 14:28:54 +00004228 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004229 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage);
4230 } else if (const auto *CE =
4231 dyn_cast<OffloadEntriesInfoManagerTy::
4232 OffloadEntryInfoDeviceGlobalVar>(E)) {
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004233 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags =
4234 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4235 CE->getFlags());
4236 switch (Flags) {
4237 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00004238 if (CGM.getLangOpts().OpenMPIsDevice &&
4239 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())
4240 continue;
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004241 if (!CE->getAddress()) {
4242 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4243 DiagnosticsEngine::Error,
4244 "Offloading entry for declare target variable is incorrect: the "
4245 "address is invalid.");
4246 CGM.getDiags().Report(DiagID);
4247 continue;
4248 }
Alexey Bataevb4dd6d22018-08-29 20:41:37 +00004249 // The vaiable has no definition - no need to add the entry.
4250 if (CE->getVarSize().isZero())
4251 continue;
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004252 break;
4253 }
4254 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink:
4255 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) ||
4256 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) &&
4257 "Declaret target link address is set.");
4258 if (CGM.getLangOpts().OpenMPIsDevice)
4259 continue;
4260 if (!CE->getAddress()) {
4261 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4262 DiagnosticsEngine::Error,
4263 "Offloading entry for declare target variable is incorrect: the "
4264 "address is invalid.");
4265 CGM.getDiags().Report(DiagID);
4266 continue;
4267 }
4268 break;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004269 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004270 createOffloadEntry(CE->getAddress(), CE->getAddress(),
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004271 CE->getVarSize().getQuantity(), Flags,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004272 CE->getLinkage());
4273 } else {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004274 llvm_unreachable("Unsupported entry kind.");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004275 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004276 }
4277}
4278
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004279/// Loads all the offload entries information from the host IR
Samuel Antaoee8fb302016-01-06 13:42:12 +00004280/// metadata.
4281void CGOpenMPRuntime::loadOffloadInfoMetadata() {
4282 // If we are in target mode, load the metadata from the host IR. This code has
4283 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
4284
4285 if (!CGM.getLangOpts().OpenMPIsDevice)
4286 return;
4287
4288 if (CGM.getLangOpts().OMPHostIRFile.empty())
4289 return;
4290
4291 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004292 if (auto EC = Buf.getError()) {
4293 CGM.getDiags().Report(diag::err_cannot_open_file)
4294 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004295 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004296 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004297
4298 llvm::LLVMContext C;
Peter Collingbourned9445c42016-11-13 07:00:17 +00004299 auto ME = expectedToErrorOrAndEmitErrors(
4300 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004301
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004302 if (auto EC = ME.getError()) {
4303 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4304 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'");
4305 CGM.getDiags().Report(DiagID)
4306 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004307 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004308 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004309
4310 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
4311 if (!MD)
4312 return;
4313
George Burgess IV00f70bd2018-03-01 05:43:23 +00004314 for (llvm::MDNode *MN : MD->operands()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004315 auto &&GetMDInt = [MN](unsigned Idx) {
4316 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004317 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
4318 };
4319
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004320 auto &&GetMDString = [MN](unsigned Idx) {
4321 auto *V = cast<llvm::MDString>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004322 return V->getString();
4323 };
4324
Alexey Bataev03f270c2018-03-30 18:31:07 +00004325 switch (GetMDInt(0)) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004326 default:
4327 llvm_unreachable("Unexpected metadata!");
4328 break;
4329 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
Alexey Bataev34f8a702018-03-28 14:28:54 +00004330 OffloadingEntryInfoTargetRegion:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004331 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
Alexey Bataev03f270c2018-03-30 18:31:07 +00004332 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2),
4333 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4),
4334 /*Order=*/GetMDInt(5));
4335 break;
4336 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
4337 OffloadingEntryInfoDeviceGlobalVar:
4338 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo(
4339 /*MangledName=*/GetMDString(1),
4340 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4341 /*Flags=*/GetMDInt(2)),
4342 /*Order=*/GetMDInt(3));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004343 break;
4344 }
4345 }
4346}
4347
Alexey Bataev62b63b12015-03-10 07:28:44 +00004348void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
4349 if (!KmpRoutineEntryPtrTy) {
4350 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004351 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004352 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
4353 FunctionProtoType::ExtProtoInfo EPI;
4354 KmpRoutineEntryPtrQTy = C.getPointerType(
4355 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
4356 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
4357 }
4358}
4359
Samuel Antaoee8fb302016-01-06 13:42:12 +00004360QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004361 // Make sure the type of the entry is already created. This is the type we
4362 // have to create:
4363 // struct __tgt_offload_entry{
4364 // void *addr; // Pointer to the offload entry info.
4365 // // (function or global)
4366 // char *name; // Name of the function or global.
4367 // size_t size; // Size of the entry info (0 if it a function).
Samuel Antaof83efdb2017-01-05 16:02:49 +00004368 // int32_t flags; // Flags associated with the entry, e.g. 'link'.
4369 // int32_t reserved; // Reserved, to use by the runtime library.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004370 // };
4371 if (TgtOffloadEntryQTy.isNull()) {
4372 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004373 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004374 RD->startDefinition();
4375 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4376 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
4377 addFieldToRecordDecl(C, RD, C.getSizeType());
Samuel Antaof83efdb2017-01-05 16:02:49 +00004378 addFieldToRecordDecl(
4379 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4380 addFieldToRecordDecl(
4381 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004382 RD->completeDefinition();
Jonas Hahnfeld5e4df282018-01-18 15:38:03 +00004383 RD->addAttr(PackedAttr::CreateImplicit(C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004384 TgtOffloadEntryQTy = C.getRecordType(RD);
4385 }
4386 return TgtOffloadEntryQTy;
4387}
4388
4389QualType CGOpenMPRuntime::getTgtDeviceImageQTy() {
4390 // These are the types we need to build:
4391 // struct __tgt_device_image{
4392 // void *ImageStart; // Pointer to the target code start.
4393 // void *ImageEnd; // Pointer to the target code end.
4394 // // We also add the host entries to the device image, as it may be useful
4395 // // for the target runtime to have access to that information.
4396 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all
4397 // // the entries.
4398 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
4399 // // entries (non inclusive).
4400 // };
4401 if (TgtDeviceImageQTy.isNull()) {
4402 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004403 RecordDecl *RD = C.buildImplicitRecord("__tgt_device_image");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004404 RD->startDefinition();
4405 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4406 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4407 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4408 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4409 RD->completeDefinition();
4410 TgtDeviceImageQTy = C.getRecordType(RD);
4411 }
4412 return TgtDeviceImageQTy;
4413}
4414
4415QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() {
4416 // struct __tgt_bin_desc{
4417 // int32_t NumDevices; // Number of devices supported.
4418 // __tgt_device_image *DeviceImages; // Arrays of device images
4419 // // (one per device).
4420 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the
4421 // // entries.
4422 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
4423 // // entries (non inclusive).
4424 // };
4425 if (TgtBinaryDescriptorQTy.isNull()) {
4426 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004427 RecordDecl *RD = C.buildImplicitRecord("__tgt_bin_desc");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004428 RD->startDefinition();
4429 addFieldToRecordDecl(
4430 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4431 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy()));
4432 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4433 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4434 RD->completeDefinition();
4435 TgtBinaryDescriptorQTy = C.getRecordType(RD);
4436 }
4437 return TgtBinaryDescriptorQTy;
4438}
4439
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004440namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00004441struct PrivateHelpersTy {
4442 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
4443 const VarDecl *PrivateElemInit)
4444 : Original(Original), PrivateCopy(PrivateCopy),
4445 PrivateElemInit(PrivateElemInit) {}
4446 const VarDecl *Original;
4447 const VarDecl *PrivateCopy;
4448 const VarDecl *PrivateElemInit;
4449};
4450typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Hans Wennborg7eb54642015-09-10 17:07:54 +00004451} // anonymous namespace
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004452
Alexey Bataev9e034042015-05-05 04:05:12 +00004453static RecordDecl *
Craig Topper8674c5c2015-09-29 04:30:07 +00004454createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004455 if (!Privates.empty()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004456 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004457 // Build struct .kmp_privates_t. {
4458 // /* private vars */
4459 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004460 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t");
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004461 RD->startDefinition();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004462 for (const auto &Pair : Privates) {
4463 const VarDecl *VD = Pair.second.Original;
4464 QualType Type = VD->getType().getNonReferenceType();
4465 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type);
Alexey Bataevc71a4092015-09-11 10:29:41 +00004466 if (VD->hasAttrs()) {
4467 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
4468 E(VD->getAttrs().end());
4469 I != E; ++I)
4470 FD->addAttr(*I);
4471 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004472 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004473 RD->completeDefinition();
4474 return RD;
4475 }
4476 return nullptr;
4477}
4478
Alexey Bataev9e034042015-05-05 04:05:12 +00004479static RecordDecl *
Alexey Bataev7292c292016-04-25 12:22:29 +00004480createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind,
4481 QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004482 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004483 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004484 // Build struct kmp_task_t {
4485 // void * shareds;
4486 // kmp_routine_entry_t routine;
4487 // kmp_int32 part_id;
Alexey Bataevad537bb2016-05-30 09:06:50 +00004488 // kmp_cmplrdata_t data1;
4489 // kmp_cmplrdata_t data2;
Alexey Bataev7292c292016-04-25 12:22:29 +00004490 // For taskloops additional fields:
4491 // kmp_uint64 lb;
4492 // kmp_uint64 ub;
4493 // kmp_int64 st;
4494 // kmp_int32 liter;
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004495 // void * reductions;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004496 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004497 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004498 UD->startDefinition();
4499 addFieldToRecordDecl(C, UD, KmpInt32Ty);
4500 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy);
4501 UD->completeDefinition();
4502 QualType KmpCmplrdataTy = C.getRecordType(UD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004503 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t");
Alexey Bataev62b63b12015-03-10 07:28:44 +00004504 RD->startDefinition();
4505 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4506 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
4507 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004508 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
4509 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004510 if (isOpenMPTaskLoopDirective(Kind)) {
4511 QualType KmpUInt64Ty =
4512 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
4513 QualType KmpInt64Ty =
4514 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
4515 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4516 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4517 addFieldToRecordDecl(C, RD, KmpInt64Ty);
4518 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004519 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004520 }
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004521 RD->completeDefinition();
4522 return RD;
4523}
4524
4525static RecordDecl *
4526createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004527 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004528 ASTContext &C = CGM.getContext();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004529 // Build struct kmp_task_t_with_privates {
4530 // kmp_task_t task_data;
4531 // .kmp_privates_t. privates;
4532 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004533 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004534 RD->startDefinition();
4535 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004536 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates))
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004537 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004538 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004539 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004540}
4541
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004542/// Emit a proxy function which accepts kmp_task_t as the second
Alexey Bataev62b63b12015-03-10 07:28:44 +00004543/// argument.
4544/// \code
4545/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00004546/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt,
Alexey Bataev7292c292016-04-25 12:22:29 +00004547/// For taskloops:
4548/// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004549/// tt->reductions, tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004550/// return 0;
4551/// }
4552/// \endcode
James Y Knight9871db02019-02-05 16:42:33 +00004553static llvm::Function *
Alexey Bataev62b63b12015-03-10 07:28:44 +00004554emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev7292c292016-04-25 12:22:29 +00004555 OpenMPDirectiveKind Kind, QualType KmpInt32Ty,
4556 QualType KmpTaskTWithPrivatesPtrQTy,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004557 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
James Y Knight9871db02019-02-05 16:42:33 +00004558 QualType SharedsPtrTy, llvm::Function *TaskFunction,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004559 llvm::Value *TaskPrivatesMap) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004560 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004561 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004562 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4563 ImplicitParamDecl::Other);
4564 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4565 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4566 ImplicitParamDecl::Other);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004567 Args.push_back(&GtidArg);
4568 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004569 const auto &TaskEntryFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004570 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004571 llvm::FunctionType *TaskEntryTy =
4572 CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004573 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""});
4574 auto *TaskEntry = llvm::Function::Create(
4575 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004576 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004577 TaskEntry->setDoesNotRecurse();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004578 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004579 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args,
4580 Loc, Loc);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004581
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004582 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
Alexey Bataev7292c292016-04-25 12:22:29 +00004583 // tt,
4584 // For taskloops:
4585 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
4586 // tt->task_data.shareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004587 llvm::Value *GtidParam = CGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00004588 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
Alexey Bataev31300ed2016-02-04 11:27:03 +00004589 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4590 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4591 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004592 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004593 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004594 LValue Base =
4595 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004596 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004597 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004598 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
4599 llvm::Value *PartidParam = PartIdLVal.getPointer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004600
4601 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004602 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
4603 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev1e491372018-01-23 18:44:14 +00004604 CGF.EmitLoadOfScalar(SharedsLVal, Loc),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004605 CGF.ConvertTypeForMem(SharedsPtrTy));
4606
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004607 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4608 llvm::Value *PrivatesParam;
4609 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004610 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004611 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00004612 PrivatesLVal.getPointer(), CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004613 } else {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004614 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004615 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004616
Alexey Bataev7292c292016-04-25 12:22:29 +00004617 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam,
4618 TaskPrivatesMap,
4619 CGF.Builder
4620 .CreatePointerBitCastOrAddrSpaceCast(
4621 TDBase.getAddress(), CGF.VoidPtrTy)
4622 .getPointer()};
4623 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs),
4624 std::end(CommonArgs));
4625 if (isOpenMPTaskLoopDirective(Kind)) {
4626 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004627 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI);
4628 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004629 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004630 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI);
4631 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004632 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004633 LValue StLVal = CGF.EmitLValueForField(Base, *StFI);
4634 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004635 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004636 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4637 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004638 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004639 LValue RLVal = CGF.EmitLValueForField(Base, *RFI);
4640 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004641 CallArgs.push_back(LBParam);
4642 CallArgs.push_back(UBParam);
4643 CallArgs.push_back(StParam);
4644 CallArgs.push_back(LIParam);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004645 CallArgs.push_back(RParam);
Alexey Bataev7292c292016-04-25 12:22:29 +00004646 }
4647 CallArgs.push_back(SharedsParam);
4648
Alexey Bataev3c595a62017-08-14 15:01:03 +00004649 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction,
4650 CallArgs);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004651 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)),
4652 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004653 CGF.FinishFunction();
4654 return TaskEntry;
4655}
4656
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004657static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
4658 SourceLocation Loc,
4659 QualType KmpInt32Ty,
4660 QualType KmpTaskTWithPrivatesPtrQTy,
4661 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004662 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004663 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004664 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4665 ImplicitParamDecl::Other);
4666 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4667 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4668 ImplicitParamDecl::Other);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004669 Args.push_back(&GtidArg);
4670 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004671 const auto &DestructorFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004672 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004673 llvm::FunctionType *DestructorFnTy =
4674 CGM.getTypes().GetFunctionType(DestructorFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004675 std::string Name =
4676 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""});
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004677 auto *DestructorFn =
4678 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00004679 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004680 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004681 DestructorFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004682 DestructorFn->setDoesNotRecurse();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004683 CodeGenFunction CGF(CGM);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004684 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004685 Args, Loc, Loc);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004686
Alexey Bataev31300ed2016-02-04 11:27:03 +00004687 LValue Base = CGF.EmitLoadOfPointerLValue(
4688 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4689 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004690 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004691 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
4692 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004693 Base = CGF.EmitLValueForField(Base, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004694 for (const auto *Field :
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004695 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004696 if (QualType::DestructionKind DtorKind =
4697 Field->getType().isDestructedType()) {
4698 LValue FieldLValue = CGF.EmitLValueForField(Base, Field);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004699 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
4700 }
4701 }
4702 CGF.FinishFunction();
4703 return DestructorFn;
4704}
4705
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004706/// Emit a privates mapping function for correct handling of private and
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004707/// firstprivate variables.
4708/// \code
4709/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
4710/// **noalias priv1,..., <tyn> **noalias privn) {
4711/// *priv1 = &.privates.priv1;
4712/// ...;
4713/// *privn = &.privates.privn;
4714/// }
4715/// \endcode
4716static llvm::Value *
4717emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Craig Topper8674c5c2015-09-29 04:30:07 +00004718 ArrayRef<const Expr *> PrivateVars,
4719 ArrayRef<const Expr *> FirstprivateVars,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004720 ArrayRef<const Expr *> LastprivateVars,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004721 QualType PrivatesQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004722 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004723 ASTContext &C = CGM.getContext();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004724 FunctionArgList Args;
4725 ImplicitParamDecl TaskPrivatesArg(
4726 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
Alexey Bataev56223232017-06-09 13:40:18 +00004727 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
4728 ImplicitParamDecl::Other);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004729 Args.push_back(&TaskPrivatesArg);
4730 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
4731 unsigned Counter = 1;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004732 for (const Expr *E : PrivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004733 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004734 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4735 C.getPointerType(C.getPointerType(E->getType()))
4736 .withConst()
4737 .withRestrict(),
4738 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004739 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004740 PrivateVarsPos[VD] = Counter;
4741 ++Counter;
4742 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004743 for (const Expr *E : FirstprivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004744 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004745 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4746 C.getPointerType(C.getPointerType(E->getType()))
4747 .withConst()
4748 .withRestrict(),
4749 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004750 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004751 PrivateVarsPos[VD] = Counter;
4752 ++Counter;
4753 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004754 for (const Expr *E : LastprivateVars) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004755 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004756 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4757 C.getPointerType(C.getPointerType(E->getType()))
4758 .withConst()
4759 .withRestrict(),
4760 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004761 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataevf93095a2016-05-05 08:46:22 +00004762 PrivateVarsPos[VD] = Counter;
4763 ++Counter;
4764 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004765 const auto &TaskPrivatesMapFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004766 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004767 llvm::FunctionType *TaskPrivatesMapTy =
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004768 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004769 std::string Name =
4770 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""});
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004771 auto *TaskPrivatesMap = llvm::Function::Create(
Alexey Bataev18fa2322018-05-02 14:20:50 +00004772 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
4773 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004774 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004775 TaskPrivatesMapFnInfo);
Alexey Bataev8c5555c2019-05-21 15:11:58 +00004776 if (CGM.getLangOpts().Optimize) {
4777 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
4778 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
4779 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
4780 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004781 CodeGenFunction CGF(CGM);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004782 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004783 TaskPrivatesMapFnInfo, Args, Loc, Loc);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004784
4785 // *privi = &.privates.privi;
Alexey Bataev31300ed2016-02-04 11:27:03 +00004786 LValue Base = CGF.EmitLoadOfPointerLValue(
4787 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
4788 TaskPrivatesArg.getType()->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004789 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004790 Counter = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004791 for (const FieldDecl *Field : PrivatesQTyRD->fields()) {
4792 LValue FieldLVal = CGF.EmitLValueForField(Base, Field);
4793 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
4794 LValue RefLVal =
4795 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
4796 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue(
Alexey Bataev31300ed2016-02-04 11:27:03 +00004797 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>());
Alexey Bataev2377fe92015-09-10 08:12:02 +00004798 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004799 ++Counter;
4800 }
4801 CGF.FinishFunction();
4802 return TaskPrivatesMap;
4803}
4804
Alexey Bataevf93095a2016-05-05 08:46:22 +00004805/// Emit initialization for private variables in task-based directives.
Alexey Bataev8a831592016-05-10 10:36:51 +00004806static void emitPrivatesInit(CodeGenFunction &CGF,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004807 const OMPExecutableDirective &D,
4808 Address KmpTaskSharedsPtr, LValue TDBase,
4809 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4810 QualType SharedsTy, QualType SharedsPtrTy,
4811 const OMPTaskDataTy &Data,
4812 ArrayRef<PrivateDataTy> Privates, bool ForDup) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004813 ASTContext &C = CGF.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004814 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
4815 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004816 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind())
4817 ? OMPD_taskloop
4818 : OMPD_task;
4819 const CapturedStmt &CS = *D.getCapturedStmt(Kind);
4820 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004821 LValue SrcBase;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004822 bool IsTargetTask =
4823 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) ||
4824 isOpenMPTargetExecutionDirective(D.getDirectiveKind());
4825 // For target-based directives skip 3 firstprivate arrays BasePointersArray,
4826 // PointersArray and SizesArray. The original variables for these arrays are
4827 // not captured and we get their addresses explicitly.
4828 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) ||
Alexey Bataev8451efa2018-01-15 19:06:12 +00004829 (IsTargetTask && KmpTaskSharedsPtr.isValid())) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004830 SrcBase = CGF.MakeAddrLValue(
4831 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4832 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
4833 SharedsTy);
4834 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004835 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004836 for (const PrivateDataTy &Pair : Privates) {
4837 const VarDecl *VD = Pair.second.PrivateCopy;
4838 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004839 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) &&
4840 !CGF.isTrivialInitializer(Init)))) {
Alexey Bataev8a831592016-05-10 10:36:51 +00004841 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004842 if (const VarDecl *Elem = Pair.second.PrivateElemInit) {
4843 const VarDecl *OriginalVD = Pair.second.Original;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004844 // Check if the variable is the target-based BasePointersArray,
4845 // PointersArray or SizesArray.
4846 LValue SharedRefLValue;
Alexey Bataevab41ea62019-03-13 20:46:28 +00004847 QualType Type = PrivateLValue.getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004848 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004849 if (IsTargetTask && !SharedField) {
4850 assert(isa<ImplicitParamDecl>(OriginalVD) &&
4851 isa<CapturedDecl>(OriginalVD->getDeclContext()) &&
4852 cast<CapturedDecl>(OriginalVD->getDeclContext())
4853 ->getNumParams() == 0 &&
4854 isa<TranslationUnitDecl>(
4855 cast<CapturedDecl>(OriginalVD->getDeclContext())
4856 ->getDeclContext()) &&
4857 "Expected artificial target data variable.");
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004858 SharedRefLValue =
4859 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type);
4860 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004861 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField);
4862 SharedRefLValue = CGF.MakeAddrLValue(
4863 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
4864 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl),
4865 SharedRefLValue.getTBAAInfo());
4866 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004867 if (Type->isArrayType()) {
4868 // Initialize firstprivate array.
4869 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) {
4870 // Perform simple memcpy.
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00004871 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004872 } else {
4873 // Initialize firstprivate array using element-by-element
Simon Pilgrim2c518802017-03-30 14:13:19 +00004874 // initialization.
Alexey Bataevf93095a2016-05-05 08:46:22 +00004875 CGF.EmitOMPAggregateAssign(
4876 PrivateLValue.getAddress(), SharedRefLValue.getAddress(), Type,
4877 [&CGF, Elem, Init, &CapturesInfo](Address DestElement,
4878 Address SrcElement) {
4879 // Clean up any temporaries needed by the initialization.
4880 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4881 InitScope.addPrivate(
4882 Elem, [SrcElement]() -> Address { return SrcElement; });
4883 (void)InitScope.Privatize();
4884 // Emit initialization for single element.
4885 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
4886 CGF, &CapturesInfo);
4887 CGF.EmitAnyExprToMem(Init, DestElement,
4888 Init->getType().getQualifiers(),
4889 /*IsInitializer=*/false);
4890 });
4891 }
4892 } else {
4893 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4894 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
4895 return SharedRefLValue.getAddress();
4896 });
4897 (void)InitScope.Privatize();
4898 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
4899 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
4900 /*capturedByInit=*/false);
4901 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004902 } else {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004903 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004904 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004905 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004906 ++FI;
4907 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004908}
4909
4910/// Check if duplication function is required for taskloops.
4911static bool checkInitIsRequired(CodeGenFunction &CGF,
4912 ArrayRef<PrivateDataTy> Privates) {
4913 bool InitRequired = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004914 for (const PrivateDataTy &Pair : Privates) {
4915 const VarDecl *VD = Pair.second.PrivateCopy;
4916 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004917 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) &&
4918 !CGF.isTrivialInitializer(Init));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004919 if (InitRequired)
4920 break;
Alexey Bataevf93095a2016-05-05 08:46:22 +00004921 }
4922 return InitRequired;
4923}
4924
4925
4926/// Emit task_dup function (for initialization of
4927/// private/firstprivate/lastprivate vars and last_iter flag)
4928/// \code
4929/// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int
4930/// lastpriv) {
4931/// // setup lastprivate flag
4932/// task_dst->last = lastpriv;
4933/// // could be constructor calls here...
4934/// }
4935/// \endcode
4936static llvm::Value *
4937emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
4938 const OMPExecutableDirective &D,
4939 QualType KmpTaskTWithPrivatesPtrQTy,
4940 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4941 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy,
4942 QualType SharedsPtrTy, const OMPTaskDataTy &Data,
4943 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004944 ASTContext &C = CGM.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004945 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004946 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4947 KmpTaskTWithPrivatesPtrQTy,
4948 ImplicitParamDecl::Other);
4949 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4950 KmpTaskTWithPrivatesPtrQTy,
4951 ImplicitParamDecl::Other);
4952 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy,
4953 ImplicitParamDecl::Other);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004954 Args.push_back(&DstArg);
4955 Args.push_back(&SrcArg);
4956 Args.push_back(&LastprivArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004957 const auto &TaskDupFnInfo =
Alexey Bataevf93095a2016-05-05 08:46:22 +00004958 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004959 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004960 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""});
4961 auto *TaskDup = llvm::Function::Create(
4962 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004963 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004964 TaskDup->setDoesNotRecurse();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004965 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004966 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc,
4967 Loc);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004968
4969 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4970 CGF.GetAddrOfLocalVar(&DstArg),
4971 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4972 // task_dst->liter = lastpriv;
4973 if (WithLastIter) {
4974 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
4975 LValue Base = CGF.EmitLValueForField(
4976 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4977 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4978 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar(
4979 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc);
4980 CGF.EmitStoreOfScalar(Lastpriv, LILVal);
4981 }
4982
4983 // Emit initial values for private copies (if any).
4984 assert(!Privates.empty());
4985 Address KmpTaskSharedsPtr = Address::invalid();
4986 if (!Data.FirstprivateVars.empty()) {
4987 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4988 CGF.GetAddrOfLocalVar(&SrcArg),
4989 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4990 LValue Base = CGF.EmitLValueForField(
4991 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4992 KmpTaskSharedsPtr = Address(
4993 CGF.EmitLoadOfScalar(CGF.EmitLValueForField(
4994 Base, *std::next(KmpTaskTQTyRD->field_begin(),
4995 KmpTaskTShareds)),
4996 Loc),
4997 CGF.getNaturalTypeAlignment(SharedsTy));
4998 }
Alexey Bataev8a831592016-05-10 10:36:51 +00004999 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
5000 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true);
Alexey Bataevf93095a2016-05-05 08:46:22 +00005001 CGF.FinishFunction();
5002 return TaskDup;
5003}
5004
Alexey Bataev8a831592016-05-10 10:36:51 +00005005/// Checks if destructor function is required to be generated.
5006/// \return true if cleanups are required, false otherwise.
5007static bool
5008checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) {
5009 bool NeedsCleanup = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005010 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
5011 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl());
5012 for (const FieldDecl *FD : PrivateRD->fields()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00005013 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType();
5014 if (NeedsCleanup)
5015 break;
5016 }
5017 return NeedsCleanup;
5018}
5019
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005020CGOpenMPRuntime::TaskResultTy
5021CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
5022 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005023 llvm::Function *TaskFunction, QualType SharedsTy,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005024 Address Shareds, const OMPTaskDataTy &Data) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005025 ASTContext &C = CGM.getContext();
Alexey Bataev7292c292016-04-25 12:22:29 +00005026 llvm::SmallVector<PrivateDataTy, 4> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005027 // Aggregate privates and sort them by the alignment.
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005028 auto I = Data.PrivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005029 for (const Expr *E : Data.PrivateVars) {
5030 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00005031 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00005032 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00005033 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00005034 /*PrivateElemInit=*/nullptr));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005035 ++I;
5036 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005037 I = Data.FirstprivateCopies.begin();
5038 auto IElemInitRef = Data.FirstprivateInits.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005039 for (const Expr *E : Data.FirstprivateVars) {
5040 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00005041 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00005042 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00005043 PrivateHelpersTy(
5044 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00005045 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())));
Richard Trieucc3949d2016-02-18 22:34:54 +00005046 ++I;
5047 ++IElemInitRef;
Alexey Bataev9e034042015-05-05 04:05:12 +00005048 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00005049 I = Data.LastprivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005050 for (const Expr *E : Data.LastprivateVars) {
5051 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00005052 Privates.emplace_back(
Alexey Bataevf93095a2016-05-05 08:46:22 +00005053 C.getDeclAlign(VD),
5054 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00005055 /*PrivateElemInit=*/nullptr));
Alexey Bataevf93095a2016-05-05 08:46:22 +00005056 ++I;
5057 }
Fangrui Song899d1392019-04-24 14:43:05 +00005058 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) {
5059 return L.first > R.first;
5060 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005061 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005062 // Build type kmp_routine_entry_t (if not built yet).
5063 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005064 // Build type kmp_task_t (if not built yet).
Alexey Bataeve213f3e2017-10-11 15:29:40 +00005065 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) {
5066 if (SavedKmpTaskloopTQTy.isNull()) {
5067 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5068 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5069 }
5070 KmpTaskTQTy = SavedKmpTaskloopTQTy;
Alexey Bataev3a03a7f2017-10-11 15:56:38 +00005071 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00005072 assert((D.getDirectiveKind() == OMPD_task ||
5073 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) ||
5074 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) &&
5075 "Expected taskloop, task or target directive");
Alexey Bataeve213f3e2017-10-11 15:29:40 +00005076 if (SavedKmpTaskTQTy.isNull()) {
5077 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5078 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5079 }
5080 KmpTaskTQTy = SavedKmpTaskTQTy;
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005081 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005082 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005083 // Build particular struct kmp_task_t for the given task.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005084 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005085 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005086 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005087 QualType KmpTaskTWithPrivatesPtrQTy =
5088 C.getPointerType(KmpTaskTWithPrivatesQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005089 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
5090 llvm::Type *KmpTaskTWithPrivatesPtrTy =
5091 KmpTaskTWithPrivatesTy->getPointerTo();
5092 llvm::Value *KmpTaskTWithPrivatesTySize =
5093 CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005094 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
5095
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005096 // Emit initial values for private copies (if any).
5097 llvm::Value *TaskPrivatesMap = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005098 llvm::Type *TaskPrivatesMapTy =
James Y Knight9871db02019-02-05 16:42:33 +00005099 std::next(TaskFunction->arg_begin(), 3)->getType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005100 if (!Privates.empty()) {
5101 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataevf93095a2016-05-05 08:46:22 +00005102 TaskPrivatesMap = emitTaskPrivateMappingFunction(
5103 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars,
5104 FI->getType(), Privates);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005105 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5106 TaskPrivatesMap, TaskPrivatesMapTy);
5107 } else {
5108 TaskPrivatesMap = llvm::ConstantPointerNull::get(
5109 cast<llvm::PointerType>(TaskPrivatesMapTy));
5110 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005111 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
5112 // kmp_task_t *tt);
James Y Knight9871db02019-02-05 16:42:33 +00005113 llvm::Function *TaskEntry = emitProxyTaskFunction(
Alexey Bataev7292c292016-04-25 12:22:29 +00005114 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5115 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction,
5116 TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005117
5118 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
5119 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
5120 // kmp_routine_entry_t *task_entry);
5121 // Task flags. Format is taken from
James Y Knight5d71fc52019-01-29 16:37:27 +00005122 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h,
Alexey Bataev62b63b12015-03-10 07:28:44 +00005123 // description of kmp_tasking_flags struct.
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005124 enum {
5125 TiedFlag = 0x1,
5126 FinalFlag = 0x2,
5127 DestructorsFlag = 0x8,
5128 PriorityFlag = 0x20
5129 };
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005130 unsigned Flags = Data.Tied ? TiedFlag : 0;
Alexey Bataev8a831592016-05-10 10:36:51 +00005131 bool NeedsCleanup = false;
5132 if (!Privates.empty()) {
5133 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD);
5134 if (NeedsCleanup)
5135 Flags = Flags | DestructorsFlag;
5136 }
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005137 if (Data.Priority.getInt())
5138 Flags = Flags | PriorityFlag;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005139 llvm::Value *TaskFlags =
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005140 Data.Final.getPointer()
5141 ? CGF.Builder.CreateSelect(Data.Final.getPointer(),
Alexey Bataev62b63b12015-03-10 07:28:44 +00005142 CGF.Builder.getInt32(FinalFlag),
5143 CGF.Builder.getInt32(/*C=*/0))
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005144 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005145 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005146 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00005147 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc),
5148 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
5149 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5150 TaskEntry, KmpRoutineEntryPtrTy)};
5151 llvm::Value *NewTask;
5152 if (D.hasClausesOfKind<OMPNowaitClause>()) {
5153 // Check if we have any device clause associated with the directive.
5154 const Expr *Device = nullptr;
5155 if (auto *C = D.getSingleClause<OMPDeviceClause>())
5156 Device = C->getDevice();
5157 // Emit device ID if any otherwise use default value.
5158 llvm::Value *DeviceID;
5159 if (Device)
5160 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
5161 CGF.Int64Ty, /*isSigned=*/true);
5162 else
5163 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
5164 AllocArgs.push_back(DeviceID);
5165 NewTask = CGF.EmitRuntimeCall(
5166 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs);
5167 } else {
5168 NewTask = CGF.EmitRuntimeCall(
Alexey Bataev62b63b12015-03-10 07:28:44 +00005169 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00005170 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005171 llvm::Value *NewTaskNewTaskTTy =
5172 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5173 NewTask, KmpTaskTWithPrivatesPtrTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005174 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
5175 KmpTaskTWithPrivatesQTy);
5176 LValue TDBase =
5177 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005178 // Fill the data in the resulting kmp_task_t record.
5179 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00005180 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005181 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00005182 KmpTaskSharedsPtr =
5183 Address(CGF.EmitLoadOfScalar(
5184 CGF.EmitLValueForField(
5185 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
5186 KmpTaskTShareds)),
5187 Loc),
5188 CGF.getNaturalTypeAlignment(SharedsTy));
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00005189 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy);
5190 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy);
Richard Smithe78fac52018-04-05 20:52:58 +00005191 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005192 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005193 // Emit initial values for private copies (if any).
Alexey Bataevf93095a2016-05-05 08:46:22 +00005194 TaskResultTy Result;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005195 if (!Privates.empty()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00005196 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD,
5197 SharedsTy, SharedsPtrTy, Data, Privates,
5198 /*ForDup=*/false);
Alexey Bataevf93095a2016-05-05 08:46:22 +00005199 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
5200 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) {
5201 Result.TaskDupFn = emitTaskDupFunction(
5202 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
5203 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates,
5204 /*WithLastIter=*/!Data.LastprivateVars.empty());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005205 }
5206 }
Alexey Bataevad537bb2016-05-30 09:06:50 +00005207 // Fields of union "kmp_cmplrdata_t" for destructors and priority.
5208 enum { Priority = 0, Destructors = 1 };
Alexey Bataev62b63b12015-03-10 07:28:44 +00005209 // Provide pointer to function with destructors for privates.
Alexey Bataevad537bb2016-05-30 09:06:50 +00005210 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005211 const RecordDecl *KmpCmplrdataUD =
5212 (*FI)->getType()->getAsUnionType()->getDecl();
Alexey Bataevad537bb2016-05-30 09:06:50 +00005213 if (NeedsCleanup) {
5214 llvm::Value *DestructorFn = emitDestructorsFunction(
5215 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5216 KmpTaskTWithPrivatesQTy);
5217 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI);
5218 LValue DestructorsLV = CGF.EmitLValueForField(
5219 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
5220 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5221 DestructorFn, KmpRoutineEntryPtrTy),
5222 DestructorsLV);
5223 }
5224 // Set priority.
5225 if (Data.Priority.getInt()) {
5226 LValue Data2LV = CGF.EmitLValueForField(
5227 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
5228 LValue PriorityLV = CGF.EmitLValueForField(
5229 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
5230 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV);
5231 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005232 Result.NewTask = NewTask;
5233 Result.TaskEntry = TaskEntry;
5234 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
5235 Result.TDBase = TDBase;
5236 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
5237 return Result;
Alexey Bataev7292c292016-04-25 12:22:29 +00005238}
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005239
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005240void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
5241 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005242 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005243 QualType SharedsTy, Address Shareds,
5244 const Expr *IfCond,
5245 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005246 if (!CGF.HaveInsertPoint())
5247 return;
5248
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005249 TaskResultTy Result =
5250 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
5251 llvm::Value *NewTask = Result.NewTask;
James Y Knight9871db02019-02-05 16:42:33 +00005252 llvm::Function *TaskEntry = Result.TaskEntry;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005253 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy;
5254 LValue TDBase = Result.TDBase;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005255 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD;
5256 ASTContext &C = CGM.getContext();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005257 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00005258 Address DependenciesArray = Address::invalid();
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005259 unsigned NumDependencies = Data.Dependences.size();
John McCall7f416cc2015-09-08 08:05:57 +00005260 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005261 // Dependence kind for RTL.
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005262 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 };
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005263 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
5264 RecordDecl *KmpDependInfoRD;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005265 QualType FlagsTy =
5266 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005267 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
5268 if (KmpDependInfoTy.isNull()) {
5269 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
5270 KmpDependInfoRD->startDefinition();
5271 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
5272 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
5273 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
5274 KmpDependInfoRD->completeDefinition();
5275 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005276 } else {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005277 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005278 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005279 // Define type kmp_depend_info[<Dependences.size()>];
5280 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00005281 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005282 ArrayType::Normal, /*IndexTypeQuals=*/0);
5283 // kmp_depend_info[<Dependences.size()>] deps;
Alexey Bataev48591dd2016-04-20 04:01:36 +00005284 DependenciesArray =
5285 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005286 for (unsigned I = 0; I < NumDependencies; ++I) {
5287 const Expr *E = Data.Dependences[I].second;
5288 LValue Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005289 llvm::Value *Size;
5290 QualType Ty = E->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005291 if (const auto *ASE =
5292 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005293 LValue UpAddrLVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005294 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005295 llvm::Value *UpAddr =
John McCall7f416cc2015-09-08 08:05:57 +00005296 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005297 llvm::Value *LowIntPtr =
John McCall7f416cc2015-09-08 08:05:57 +00005298 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005299 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
5300 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005301 } else {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005302 Size = CGF.getTypeSize(Ty);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005303 }
5304 LValue Base = CGF.MakeAddrLValue(
James Y Knight751fe282019-02-09 22:22:28 +00005305 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005306 KmpDependInfoTy);
5307 // deps[i].base_addr = &<Dependences[i].second>;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005308 LValue BaseAddrLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005309 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00005310 CGF.EmitStoreOfScalar(
5311 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy),
5312 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005313 // deps[i].len = sizeof(<Dependences[i].second>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005314 LValue LenLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005315 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
5316 CGF.EmitStoreOfScalar(Size, LenLVal);
5317 // deps[i].flags = <Dependences[i].first>;
5318 RTLDependenceKindTy DepKind;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005319 switch (Data.Dependences[I].first) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005320 case OMPC_DEPEND_in:
5321 DepKind = DepIn;
5322 break;
Alexey Bataev92e82f92015-11-23 13:33:42 +00005323 // Out and InOut dependencies must use the same code.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005324 case OMPC_DEPEND_out:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005325 case OMPC_DEPEND_inout:
5326 DepKind = DepInOut;
5327 break;
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005328 case OMPC_DEPEND_mutexinoutset:
5329 DepKind = DepMutexInOutSet;
5330 break;
Alexey Bataeveb482352015-12-18 05:05:56 +00005331 case OMPC_DEPEND_source:
Alexey Bataeva636c7f2015-12-23 10:27:45 +00005332 case OMPC_DEPEND_sink:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005333 case OMPC_DEPEND_unknown:
5334 llvm_unreachable("Unknown task dependence type");
5335 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005336 LValue FlagsLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005337 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
5338 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
5339 FlagsLVal);
5340 }
John McCall7f416cc2015-09-08 08:05:57 +00005341 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knightf5f1b0e2019-02-08 15:34:12 +00005342 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005343 }
5344
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005345 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev62b63b12015-03-10 07:28:44 +00005346 // libcall.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005347 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
5348 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
5349 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
5350 // list is not empty
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005351 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5352 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00005353 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
5354 llvm::Value *DepTaskArgs[7];
5355 if (NumDependencies) {
5356 DepTaskArgs[0] = UpLoc;
5357 DepTaskArgs[1] = ThreadID;
5358 DepTaskArgs[2] = NewTask;
5359 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
5360 DepTaskArgs[4] = DependenciesArray.getPointer();
5361 DepTaskArgs[5] = CGF.Builder.getInt32(0);
5362 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5363 }
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005364 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies,
5365 &TaskArgs,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005366 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005367 if (!Data.Tied) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005368 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005369 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
Alexey Bataev48591dd2016-04-20 04:01:36 +00005370 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
5371 }
John McCall7f416cc2015-09-08 08:05:57 +00005372 if (NumDependencies) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005373 CGF.EmitRuntimeCall(
Alexey Bataev48591dd2016-04-20 04:01:36 +00005374 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs);
John McCall7f416cc2015-09-08 08:05:57 +00005375 } else {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005376 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
John McCall7f416cc2015-09-08 08:05:57 +00005377 TaskArgs);
5378 }
Alexey Bataev48591dd2016-04-20 04:01:36 +00005379 // Check if parent region is untied and build return for untied task;
5380 if (auto *Region =
5381 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
5382 Region->emitUntiedSwitch(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00005383 };
John McCall7f416cc2015-09-08 08:05:57 +00005384
5385 llvm::Value *DepWaitTaskArgs[6];
5386 if (NumDependencies) {
5387 DepWaitTaskArgs[0] = UpLoc;
5388 DepWaitTaskArgs[1] = ThreadID;
5389 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
5390 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
5391 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
5392 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5393 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005394 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
Alexey Bataev3c595a62017-08-14 15:01:03 +00005395 NumDependencies, &DepWaitTaskArgs,
5396 Loc](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005397 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005398 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
5399 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
5400 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
5401 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
5402 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00005403 if (NumDependencies)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005404 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005405 DepWaitTaskArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005406 // Call proxy_task_entry(gtid, new_task);
Alexey Bataev3c595a62017-08-14 15:01:03 +00005407 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
5408 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005409 Action.Enter(CGF);
5410 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
Alexey Bataev3c595a62017-08-14 15:01:03 +00005411 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
Alexey Bataev2c7eee52017-08-04 19:10:54 +00005412 OutlinedFnArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005413 };
5414
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005415 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
5416 // kmp_task_t *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005417 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
5418 // kmp_task_t *new_task);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005419 RegionCodeGenTy RCG(CodeGen);
5420 CommonActionTy Action(
5421 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs,
5422 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs);
5423 RCG.setAction(Action);
5424 RCG(CGF);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005425 };
John McCall7f416cc2015-09-08 08:05:57 +00005426
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005427 if (IfCond) {
Alexey Bataev1d677132015-04-22 13:57:31 +00005428 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005429 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005430 RegionCodeGenTy ThenRCG(ThenCodeGen);
5431 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00005432 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005433}
5434
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005435void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
5436 const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005437 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005438 QualType SharedsTy, Address Shareds,
5439 const Expr *IfCond,
5440 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005441 if (!CGF.HaveInsertPoint())
5442 return;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005443 TaskResultTy Result =
5444 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005445 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev7292c292016-04-25 12:22:29 +00005446 // libcall.
5447 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
5448 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
5449 // sched, kmp_uint64 grainsize, void *task_dup);
5450 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5451 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
5452 llvm::Value *IfVal;
5453 if (IfCond) {
5454 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy,
5455 /*isSigned=*/true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005456 } else {
Alexey Bataev7292c292016-04-25 12:22:29 +00005457 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005458 }
Alexey Bataev7292c292016-04-25 12:22:29 +00005459
5460 LValue LBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005461 Result.TDBase,
5462 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005463 const auto *LBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005464 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl());
5465 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(),
5466 /*IsInitializer=*/true);
5467 LValue UBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005468 Result.TDBase,
5469 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005470 const auto *UBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005471 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl());
5472 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(),
5473 /*IsInitializer=*/true);
5474 LValue StLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005475 Result.TDBase,
5476 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005477 const auto *StVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005478 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl());
5479 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(),
5480 /*IsInitializer=*/true);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005481 // Store reductions address.
5482 LValue RedLVal = CGF.EmitLValueForField(
5483 Result.TDBase,
5484 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005485 if (Data.Reductions) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005486 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005487 } else {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005488 CGF.EmitNullInitialization(RedLVal.getAddress(),
5489 CGF.getContext().VoidPtrTy);
5490 }
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005491 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
Alexey Bataev7292c292016-04-25 12:22:29 +00005492 llvm::Value *TaskArgs[] = {
Alexey Bataev33446032017-07-12 18:09:32 +00005493 UpLoc,
5494 ThreadID,
5495 Result.NewTask,
5496 IfVal,
5497 LBLVal.getPointer(),
5498 UBLVal.getPointer(),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00005499 CGF.EmitLoadOfScalar(StLVal, Loc),
Alexey Bataevac6e4de2018-10-24 19:06:37 +00005500 llvm::ConstantInt::getSigned(
5501 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005502 llvm::ConstantInt::getSigned(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005503 CGF.IntTy, Data.Schedule.getPointer()
5504 ? Data.Schedule.getInt() ? NumTasks : Grainsize
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005505 : NoSchedule),
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005506 Data.Schedule.getPointer()
5507 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty,
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005508 /*isSigned=*/false)
5509 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0),
Alexey Bataev33446032017-07-12 18:09:32 +00005510 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5511 Result.TaskDupFn, CGF.VoidPtrTy)
5512 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)};
Alexey Bataev7292c292016-04-25 12:22:29 +00005513 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs);
5514}
5515
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005516/// Emit reduction operation for each element of array (required for
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005517/// array sections) LHS op = RHS.
5518/// \param Type Type of array.
5519/// \param LHSVar Variable on the left side of the reduction operation
5520/// (references element of array in original variable).
5521/// \param RHSVar Variable on the right side of the reduction operation
5522/// (references element of array in original variable).
5523/// \param RedOpGen Generator of reduction operation with use of LHSVar and
5524/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00005525static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005526 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
5527 const VarDecl *RHSVar,
5528 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
5529 const Expr *, const Expr *)> &RedOpGen,
5530 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
5531 const Expr *UpExpr = nullptr) {
5532 // Perform element-by-element initialization.
5533 QualType ElementTy;
5534 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
5535 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
5536
5537 // Drill down to the base element type on both arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005538 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
5539 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005540
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005541 llvm::Value *RHSBegin = RHSAddr.getPointer();
5542 llvm::Value *LHSBegin = LHSAddr.getPointer();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005543 // Cast from pointer to array type to pointer to single element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005544 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005545 // The basic structure here is a while-do loop.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005546 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
5547 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
5548 llvm::Value *IsEmpty =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005549 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
5550 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
5551
5552 // Enter the loop body, making that address the current address.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005553 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005554 CGF.EmitBlock(BodyBB);
5555
5556 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
5557
5558 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
5559 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
5560 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
5561 Address RHSElementCurrent =
5562 Address(RHSElementPHI,
5563 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5564
5565 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
5566 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
5567 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
5568 Address LHSElementCurrent =
5569 Address(LHSElementPHI,
5570 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5571
5572 // Emit copy.
5573 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005574 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; });
5575 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005576 Scope.Privatize();
5577 RedOpGen(CGF, XExpr, EExpr, UpExpr);
5578 Scope.ForceCleanup();
5579
5580 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005581 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005582 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005583 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005584 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
5585 // Check whether we've reached the end.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005586 llvm::Value *Done =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005587 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
5588 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
5589 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
5590 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
5591
5592 // Done.
5593 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
5594}
5595
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005596/// Emit reduction combiner. If the combiner is a simple expression emit it as
5597/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
5598/// UDR combiner function.
5599static void emitReductionCombiner(CodeGenFunction &CGF,
5600 const Expr *ReductionOp) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005601 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
5602 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
5603 if (const auto *DRE =
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005604 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005605 if (const auto *DRD =
5606 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005607 std::pair<llvm::Function *, llvm::Function *> Reduction =
5608 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
5609 RValue Func = RValue::get(Reduction.first);
5610 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
5611 CGF.EmitIgnoredExpr(ReductionOp);
5612 return;
5613 }
5614 CGF.EmitIgnoredExpr(ReductionOp);
5615}
5616
James Y Knight9871db02019-02-05 16:42:33 +00005617llvm::Function *CGOpenMPRuntime::emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005618 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates,
5619 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
5620 ArrayRef<const Expr *> ReductionOps) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005621 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005622
5623 // void reduction_func(void *LHSArg, void *RHSArg);
5624 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005625 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5626 ImplicitParamDecl::Other);
5627 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5628 ImplicitParamDecl::Other);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005629 Args.push_back(&LHSArg);
5630 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005631 const auto &CGFI =
5632 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00005633 std::string Name = getName({"omp", "reduction", "reduction_func"});
5634 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
5635 llvm::GlobalValue::InternalLinkage, Name,
5636 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00005637 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00005638 Fn->setDoesNotRecurse();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005639 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005640 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005641
5642 // Dst = (void*[n])(LHSArg);
5643 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00005644 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5645 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
5646 ArgsType), CGF.getPointerAlign());
5647 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5648 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
5649 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005650
5651 // ...
5652 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
5653 // ...
5654 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005655 auto IPriv = Privates.begin();
5656 unsigned Idx = 0;
5657 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005658 const auto *RHSVar =
5659 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
5660 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005661 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005662 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005663 const auto *LHSVar =
5664 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
5665 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005666 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005667 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005668 QualType PrivTy = (*IPriv)->getType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00005669 if (PrivTy->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005670 // Get array size and emit VLA type.
5671 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005672 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005673 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005674 const VariableArrayType *VLA =
5675 CGF.getContext().getAsVariableArrayType(PrivTy);
5676 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005677 CodeGenFunction::OpaqueValueMapping OpaqueMap(
Alexey Bataev1189bd02016-01-26 12:20:39 +00005678 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005679 CGF.EmitVariablyModifiedType(PrivTy);
5680 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005681 }
5682 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005683 IPriv = Privates.begin();
5684 auto ILHS = LHSExprs.begin();
5685 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005686 for (const Expr *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005687 if ((*IPriv)->getType()->isArrayType()) {
5688 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005689 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5690 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005691 EmitOMPAggregateReduction(
5692 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5693 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5694 emitReductionCombiner(CGF, E);
5695 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005696 } else {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005697 // Emit reduction for array subscript or single variable.
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005698 emitReductionCombiner(CGF, E);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005699 }
Richard Trieucc3949d2016-02-18 22:34:54 +00005700 ++IPriv;
5701 ++ILHS;
5702 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005703 }
5704 Scope.ForceCleanup();
5705 CGF.FinishFunction();
5706 return Fn;
5707}
5708
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005709void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF,
5710 const Expr *ReductionOp,
5711 const Expr *PrivateRef,
5712 const DeclRefExpr *LHS,
5713 const DeclRefExpr *RHS) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005714 if (PrivateRef->getType()->isArrayType()) {
5715 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005716 const auto *LHSVar = cast<VarDecl>(LHS->getDecl());
5717 const auto *RHSVar = cast<VarDecl>(RHS->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005718 EmitOMPAggregateReduction(
5719 CGF, PrivateRef->getType(), LHSVar, RHSVar,
5720 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5721 emitReductionCombiner(CGF, ReductionOp);
5722 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005723 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005724 // Emit reduction for array subscript or single variable.
5725 emitReductionCombiner(CGF, ReductionOp);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005726 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005727}
5728
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005729void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005730 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005731 ArrayRef<const Expr *> LHSExprs,
5732 ArrayRef<const Expr *> RHSExprs,
5733 ArrayRef<const Expr *> ReductionOps,
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005734 ReductionOptionsTy Options) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00005735 if (!CGF.HaveInsertPoint())
5736 return;
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005737
5738 bool WithNowait = Options.WithNowait;
5739 bool SimpleReduction = Options.SimpleReduction;
5740
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005741 // Next code should be emitted for reduction:
5742 //
5743 // static kmp_critical_name lock = { 0 };
5744 //
5745 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
5746 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
5747 // ...
5748 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
5749 // *(Type<n>-1*)rhs[<n>-1]);
5750 // }
5751 //
5752 // ...
5753 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
5754 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5755 // RedList, reduce_func, &<lock>)) {
5756 // case 1:
5757 // ...
5758 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5759 // ...
5760 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5761 // break;
5762 // case 2:
5763 // ...
5764 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5765 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00005766 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005767 // break;
5768 // default:;
5769 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005770 //
5771 // if SimpleReduction is true, only the next code is generated:
5772 // ...
5773 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5774 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005775
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005776 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005777
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005778 if (SimpleReduction) {
5779 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005780 auto IPriv = Privates.begin();
5781 auto ILHS = LHSExprs.begin();
5782 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005783 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005784 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5785 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005786 ++IPriv;
5787 ++ILHS;
5788 ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005789 }
5790 return;
5791 }
5792
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005793 // 1. Build a list of reduction variables.
5794 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005795 auto Size = RHSExprs.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005796 for (const Expr *E : Privates) {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005797 if (E->getType()->isVariablyModifiedType())
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005798 // Reserve place for array size.
5799 ++Size;
5800 }
5801 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005802 QualType ReductionArrayTy =
5803 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
5804 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00005805 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005806 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005807 auto IPriv = Privates.begin();
5808 unsigned Idx = 0;
5809 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
James Y Knight751fe282019-02-09 22:22:28 +00005810 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
John McCall7f416cc2015-09-08 08:05:57 +00005811 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005812 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00005813 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
5814 Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005815 if ((*IPriv)->getType()->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005816 // Store array size.
5817 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005818 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005819 llvm::Value *Size = CGF.Builder.CreateIntCast(
5820 CGF.getVLASize(
5821 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
Sander de Smalen891af03a2018-02-03 13:55:59 +00005822 .NumElts,
Alexey Bataev1189bd02016-01-26 12:20:39 +00005823 CGF.SizeTy, /*isSigned=*/false);
5824 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
5825 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005826 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005827 }
5828
5829 // 2. Emit reduce_func().
James Y Knight9871db02019-02-05 16:42:33 +00005830 llvm::Function *ReductionFn = emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005831 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
5832 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005833
5834 // 3. Create static kmp_critical_name lock = { 0 };
Alexey Bataev18fa2322018-05-02 14:20:50 +00005835 std::string Name = getName({"reduction"});
5836 llvm::Value *Lock = getCriticalRegionLock(Name);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005837
5838 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5839 // RedList, reduce_func, &<lock>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005840 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
5841 llvm::Value *ThreadId = getThreadID(CGF, Loc);
5842 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
5843 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Samuel Antao4c8035b2016-12-12 18:00:20 +00005844 ReductionList.getPointer(), CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005845 llvm::Value *Args[] = {
5846 IdentTLoc, // ident_t *<loc>
5847 ThreadId, // i32 <gtid>
5848 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
5849 ReductionArrayTySize, // size_type sizeof(RedList)
5850 RL, // void *RedList
5851 ReductionFn, // void (*) (void *, void *) <reduce_func>
5852 Lock // kmp_critical_name *&<lock>
5853 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005854 llvm::Value *Res = CGF.EmitRuntimeCall(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005855 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
5856 : OMPRTL__kmpc_reduce),
5857 Args);
5858
5859 // 5. Build switch(res)
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005860 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
5861 llvm::SwitchInst *SwInst =
5862 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005863
5864 // 6. Build case 1:
5865 // ...
5866 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5867 // ...
5868 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5869 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005870 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005871 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
5872 CGF.EmitBlock(Case1BB);
5873
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005874 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5875 llvm::Value *EndArgs[] = {
5876 IdentTLoc, // ident_t *<loc>
5877 ThreadId, // i32 <gtid>
5878 Lock // kmp_critical_name *&<lock>
5879 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005880 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5881 CodeGenFunction &CGF, PrePostActionTy &Action) {
5882 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005883 auto IPriv = Privates.begin();
5884 auto ILHS = LHSExprs.begin();
5885 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005886 for (const Expr *E : ReductionOps) {
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005887 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5888 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005889 ++IPriv;
5890 ++ILHS;
5891 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005892 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005893 };
5894 RegionCodeGenTy RCG(CodeGen);
5895 CommonActionTy Action(
5896 nullptr, llvm::None,
5897 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
5898 : OMPRTL__kmpc_end_reduce),
5899 EndArgs);
5900 RCG.setAction(Action);
5901 RCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005902
5903 CGF.EmitBranch(DefaultBB);
5904
5905 // 7. Build case 2:
5906 // ...
5907 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5908 // ...
5909 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005910 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005911 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
5912 CGF.EmitBlock(Case2BB);
5913
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005914 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
5915 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005916 auto ILHS = LHSExprs.begin();
5917 auto IRHS = RHSExprs.begin();
5918 auto IPriv = Privates.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005919 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005920 const Expr *XExpr = nullptr;
5921 const Expr *EExpr = nullptr;
5922 const Expr *UpExpr = nullptr;
5923 BinaryOperatorKind BO = BO_Comma;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005924 if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005925 if (BO->getOpcode() == BO_Assign) {
5926 XExpr = BO->getLHS();
5927 UpExpr = BO->getRHS();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005928 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005929 }
5930 // Try to emit update expression as a simple atomic.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005931 const Expr *RHSExpr = UpExpr;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005932 if (RHSExpr) {
5933 // Analyze RHS part of the whole expression.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005934 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005935 RHSExpr->IgnoreParenImpCasts())) {
5936 // If this is a conditional operator, analyze its condition for
5937 // min/max reduction operator.
5938 RHSExpr = ACO->getCond();
Alexey Bataev69a47792015-05-07 03:54:03 +00005939 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005940 if (const auto *BORHS =
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005941 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
5942 EExpr = BORHS->getRHS();
5943 BO = BORHS->getOpcode();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005944 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005945 }
5946 if (XExpr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005947 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005948 auto &&AtomicRedGen = [BO, VD,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005949 Loc](CodeGenFunction &CGF, const Expr *XExpr,
5950 const Expr *EExpr, const Expr *UpExpr) {
5951 LValue X = CGF.EmitLValue(XExpr);
5952 RValue E;
5953 if (EExpr)
5954 E = CGF.EmitAnyExpr(EExpr);
5955 CGF.EmitOMPAtomicSimpleUpdateExpr(
JF Bastien92f4ef12016-04-06 17:26:42 +00005956 X, E, BO, /*IsXLHSInRHSPart=*/true,
5957 llvm::AtomicOrdering::Monotonic, Loc,
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005958 [&CGF, UpExpr, VD, Loc](RValue XRValue) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005959 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5960 PrivateScope.addPrivate(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005961 VD, [&CGF, VD, XRValue, Loc]() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005962 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5963 CGF.emitOMPSimpleStore(
5964 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
5965 VD->getType().getNonReferenceType(), Loc);
5966 return LHSTemp;
5967 });
5968 (void)PrivateScope.Privatize();
5969 return CGF.EmitAnyExpr(UpExpr);
5970 });
5971 };
5972 if ((*IPriv)->getType()->isArrayType()) {
5973 // Emit atomic reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005974 const auto *RHSVar =
5975 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005976 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
5977 AtomicRedGen, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005978 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005979 // Emit atomic reduction for array subscript or single variable.
5980 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005981 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005982 } else {
5983 // Emit as a critical region.
5984 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
Alexey Bataev18fa2322018-05-02 14:20:50 +00005985 const Expr *, const Expr *) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005986 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev18fa2322018-05-02 14:20:50 +00005987 std::string Name = RT.getName({"atomic_reduction"});
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005988 RT.emitCriticalRegion(
Alexey Bataev18fa2322018-05-02 14:20:50 +00005989 CGF, Name,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005990 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
5991 Action.Enter(CGF);
5992 emitReductionCombiner(CGF, E);
5993 },
5994 Loc);
5995 };
5996 if ((*IPriv)->getType()->isArrayType()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005997 const auto *LHSVar =
5998 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5999 const auto *RHSVar =
6000 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006001 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
6002 CritRedGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006003 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006004 CritRedGen(CGF, nullptr, nullptr, nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006005 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006006 }
Richard Trieucc3949d2016-02-18 22:34:54 +00006007 ++ILHS;
6008 ++IRHS;
6009 ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00006010 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006011 };
6012 RegionCodeGenTy AtomicRCG(AtomicCodeGen);
6013 if (!WithNowait) {
6014 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
6015 llvm::Value *EndArgs[] = {
6016 IdentTLoc, // ident_t *<loc>
6017 ThreadId, // i32 <gtid>
6018 Lock // kmp_critical_name *&<lock>
6019 };
6020 CommonActionTy Action(nullptr, llvm::None,
6021 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
6022 EndArgs);
6023 AtomicRCG.setAction(Action);
6024 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006025 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006026 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006027 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00006028
6029 CGF.EmitBranch(DefaultBB);
6030 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
6031}
6032
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006033/// Generates unique name for artificial threadprivate variables.
Alexey Bataev1c44e152018-03-06 18:59:43 +00006034/// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>"
6035static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix,
6036 const Expr *Ref) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006037 SmallString<256> Buffer;
6038 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev1c44e152018-03-06 18:59:43 +00006039 const clang::DeclRefExpr *DE;
6040 const VarDecl *D = ::getBaseDecl(Ref, DE);
6041 if (!D)
6042 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl());
6043 D = D->getCanonicalDecl();
Alexey Bataev18fa2322018-05-02 14:20:50 +00006044 std::string Name = CGM.getOpenMPRuntime().getName(
6045 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)});
6046 Out << Prefix << Name << "_"
Stephen Kellyf2ceec42018-08-09 21:08:08 +00006047 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006048 return Out.str();
6049}
6050
6051/// Emits reduction initializer function:
6052/// \code
6053/// void @.red_init(void* %arg) {
6054/// %0 = bitcast void* %arg to <type>*
6055/// store <type> <init>, <type>* %0
6056/// ret void
6057/// }
6058/// \endcode
6059static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM,
6060 SourceLocation Loc,
6061 ReductionCodeGen &RCG, unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006062 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006063 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006064 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6065 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006066 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006067 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006068 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006069 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006070 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006071 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006072 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006073 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006074 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006075 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006076 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006077 Address PrivateAddr = CGF.EmitLoadOfPointer(
6078 CGF.GetAddrOfLocalVar(&Param),
6079 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6080 llvm::Value *Size = nullptr;
6081 // If the size of the reduction item is non-constant, load it from global
6082 // threadprivate variable.
6083 if (RCG.getSizes(N).second) {
6084 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6085 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006086 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006087 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6088 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006089 }
6090 RCG.emitAggregateType(CGF, N, Size);
6091 LValue SharedLVal;
6092 // If initializer uses initializer from declare reduction construct, emit a
6093 // pointer to the address of the original reduction item (reuired by reduction
6094 // initializer)
6095 if (RCG.usesReductionInitializer(N)) {
6096 Address SharedAddr =
6097 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6098 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006099 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataev21dab122018-03-09 15:20:30 +00006100 SharedAddr = CGF.EmitLoadOfPointer(
6101 SharedAddr,
6102 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006103 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy);
6104 } else {
6105 SharedLVal = CGF.MakeNaturalAlignAddrLValue(
6106 llvm::ConstantPointerNull::get(CGM.VoidPtrTy),
6107 CGM.getContext().VoidPtrTy);
6108 }
6109 // Emit the initializer:
6110 // %0 = bitcast void* %arg to <type>*
6111 // store <type> <init>, <type>* %0
6112 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal,
6113 [](CodeGenFunction &) { return false; });
6114 CGF.FinishFunction();
6115 return Fn;
6116}
6117
6118/// Emits reduction combiner function:
6119/// \code
6120/// void @.red_comb(void* %arg0, void* %arg1) {
6121/// %lhs = bitcast void* %arg0 to <type>*
6122/// %rhs = bitcast void* %arg1 to <type>*
6123/// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs)
6124/// store <type> %2, <type>* %lhs
6125/// ret void
6126/// }
6127/// \endcode
6128static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM,
6129 SourceLocation Loc,
6130 ReductionCodeGen &RCG, unsigned N,
6131 const Expr *ReductionOp,
6132 const Expr *LHS, const Expr *RHS,
6133 const Expr *PrivateRef) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006134 ASTContext &C = CGM.getContext();
6135 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl());
6136 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006137 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006138 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
6139 C.VoidPtrTy, ImplicitParamDecl::Other);
6140 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6141 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006142 Args.emplace_back(&ParamInOut);
6143 Args.emplace_back(&ParamIn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006144 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006145 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006146 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006147 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006148 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006149 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006150 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006151 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006152 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006153 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006154 llvm::Value *Size = nullptr;
6155 // If the size of the reduction item is non-constant, load it from global
6156 // threadprivate variable.
6157 if (RCG.getSizes(N).second) {
6158 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6159 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006160 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006161 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6162 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006163 }
6164 RCG.emitAggregateType(CGF, N, Size);
6165 // Remap lhs and rhs variables to the addresses of the function arguments.
6166 // %lhs = bitcast void* %arg0 to <type>*
6167 // %rhs = bitcast void* %arg1 to <type>*
6168 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006169 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006170 // Pull out the pointer to the variable.
6171 Address PtrAddr = CGF.EmitLoadOfPointer(
6172 CGF.GetAddrOfLocalVar(&ParamInOut),
6173 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6174 return CGF.Builder.CreateElementBitCast(
6175 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType()));
6176 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006177 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006178 // Pull out the pointer to the variable.
6179 Address PtrAddr = CGF.EmitLoadOfPointer(
6180 CGF.GetAddrOfLocalVar(&ParamIn),
6181 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6182 return CGF.Builder.CreateElementBitCast(
6183 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType()));
6184 });
6185 PrivateScope.Privatize();
6186 // Emit the combiner body:
6187 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs)
6188 // store <type> %2, <type>* %lhs
6189 CGM.getOpenMPRuntime().emitSingleReductionCombiner(
6190 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS),
6191 cast<DeclRefExpr>(RHS));
6192 CGF.FinishFunction();
6193 return Fn;
6194}
6195
6196/// Emits reduction finalizer function:
6197/// \code
6198/// void @.red_fini(void* %arg) {
6199/// %0 = bitcast void* %arg to <type>*
6200/// <destroy>(<type>* %0)
6201/// ret void
6202/// }
6203/// \endcode
6204static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM,
6205 SourceLocation Loc,
6206 ReductionCodeGen &RCG, unsigned N) {
6207 if (!RCG.needCleanups(N))
6208 return nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006209 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006210 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006211 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6212 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006213 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006214 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006215 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006216 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006217 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006218 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006219 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006220 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006221 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006222 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006223 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006224 Address PrivateAddr = CGF.EmitLoadOfPointer(
6225 CGF.GetAddrOfLocalVar(&Param),
6226 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6227 llvm::Value *Size = nullptr;
6228 // If the size of the reduction item is non-constant, load it from global
6229 // threadprivate variable.
6230 if (RCG.getSizes(N).second) {
6231 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6232 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006233 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006234 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6235 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006236 }
6237 RCG.emitAggregateType(CGF, N, Size);
6238 // Emit the finalizer body:
6239 // <destroy>(<type>* %0)
6240 RCG.emitCleanups(CGF, N, PrivateAddr);
6241 CGF.FinishFunction();
6242 return Fn;
6243}
6244
6245llvm::Value *CGOpenMPRuntime::emitTaskReductionInit(
6246 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
6247 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
6248 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty())
6249 return nullptr;
6250
6251 // Build typedef struct:
6252 // kmp_task_red_input {
6253 // void *reduce_shar; // shared reduction item
6254 // size_t reduce_size; // size of data item
6255 // void *reduce_init; // data initialization routine
6256 // void *reduce_fini; // data finalization routine
6257 // void *reduce_comb; // data combiner routine
6258 // kmp_task_red_flags_t flags; // flags for additional info from compiler
6259 // } kmp_task_red_input_t;
6260 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006261 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t");
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006262 RD->startDefinition();
6263 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6264 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType());
6265 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6266 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6267 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6268 const FieldDecl *FlagsFD = addFieldToRecordDecl(
6269 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false));
6270 RD->completeDefinition();
6271 QualType RDType = C.getRecordType(RD);
6272 unsigned Size = Data.ReductionVars.size();
6273 llvm::APInt ArraySize(/*numBits=*/64, Size);
6274 QualType ArrayRDType = C.getConstantArrayType(
6275 RDType, ArraySize, ArrayType::Normal, /*IndexTypeQuals=*/0);
6276 // kmp_task_red_input_t .rd_input.[Size];
6277 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input.");
6278 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies,
6279 Data.ReductionOps);
6280 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) {
6281 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt];
6282 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0),
6283 llvm::ConstantInt::get(CGM.SizeTy, Cnt)};
6284 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP(
6285 TaskRedInput.getPointer(), Idxs,
6286 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc,
6287 ".rd_input.gep.");
6288 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType);
6289 // ElemLVal.reduce_shar = &Shareds[Cnt];
6290 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD);
6291 RCG.emitSharedLValue(CGF, Cnt);
6292 llvm::Value *CastedShared =
6293 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer());
6294 CGF.EmitStoreOfScalar(CastedShared, SharedLVal);
6295 RCG.emitAggregateType(CGF, Cnt);
6296 llvm::Value *SizeValInChars;
6297 llvm::Value *SizeVal;
6298 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt);
6299 // We use delayed creation/initialization for VLAs, array sections and
6300 // custom reduction initializations. It is required because runtime does not
6301 // provide the way to pass the sizes of VLAs/array sections to
6302 // initializer/combiner/finalizer functions and does not pass the pointer to
6303 // original reduction item to the initializer. Instead threadprivate global
6304 // variables are used to store these values and use them in the functions.
6305 bool DelayedCreation = !!SizeVal;
6306 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy,
6307 /*isSigned=*/false);
6308 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD);
6309 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal);
6310 // ElemLVal.reduce_init = init;
6311 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD);
6312 llvm::Value *InitAddr =
6313 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt));
6314 CGF.EmitStoreOfScalar(InitAddr, InitLVal);
6315 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt);
6316 // ElemLVal.reduce_fini = fini;
6317 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD);
6318 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt);
6319 llvm::Value *FiniAddr = Fini
6320 ? CGF.EmitCastToVoidPtr(Fini)
6321 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy);
6322 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal);
6323 // ElemLVal.reduce_comb = comb;
6324 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD);
6325 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction(
6326 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt],
6327 RHSExprs[Cnt], Data.ReductionCopies[Cnt]));
6328 CGF.EmitStoreOfScalar(CombAddr, CombLVal);
6329 // ElemLVal.flags = 0;
6330 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD);
6331 if (DelayedCreation) {
6332 CGF.EmitStoreOfScalar(
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006333 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006334 FlagsLVal);
6335 } else
6336 CGF.EmitNullInitialization(FlagsLVal.getAddress(), FlagsLVal.getType());
6337 }
6338 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void
6339 // *data);
6340 llvm::Value *Args[] = {
6341 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6342 /*isSigned=*/true),
6343 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true),
6344 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(),
6345 CGM.VoidPtrTy)};
6346 return CGF.EmitRuntimeCall(
6347 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args);
6348}
6349
6350void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
6351 SourceLocation Loc,
6352 ReductionCodeGen &RCG,
6353 unsigned N) {
6354 auto Sizes = RCG.getSizes(N);
6355 // Emit threadprivate global variable if the type is non-constant
6356 // (Sizes.second = nullptr).
6357 if (Sizes.second) {
6358 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy,
6359 /*isSigned=*/false);
6360 Address SizeAddr = getAddrOfArtificialThreadPrivate(
6361 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006362 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006363 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false);
6364 }
6365 // Store address of the original reduction item if custom initializer is used.
6366 if (RCG.usesReductionInitializer(N)) {
6367 Address SharedAddr = getAddrOfArtificialThreadPrivate(
6368 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006369 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006370 CGF.Builder.CreateStore(
6371 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6372 RCG.getSharedLValue(N).getPointer(), CGM.VoidPtrTy),
6373 SharedAddr, /*IsVolatile=*/false);
6374 }
6375}
6376
6377Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF,
6378 SourceLocation Loc,
6379 llvm::Value *ReductionsPtr,
6380 LValue SharedLVal) {
6381 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
6382 // *d);
6383 llvm::Value *Args[] = {
6384 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6385 /*isSigned=*/true),
6386 ReductionsPtr,
6387 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(SharedLVal.getPointer(),
6388 CGM.VoidPtrTy)};
6389 return Address(
6390 CGF.EmitRuntimeCall(
6391 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args),
6392 SharedLVal.getAlignment());
6393}
6394
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006395void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
6396 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006397 if (!CGF.HaveInsertPoint())
6398 return;
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006399 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
6400 // global_tid);
6401 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
6402 // Ignore return result until untied tasks are supported.
6403 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00006404 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
6405 Region->emitUntiedSwitch(CGF);
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006406}
6407
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006408void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006409 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00006410 const RegionCodeGenTy &CodeGen,
6411 bool HasCancel) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006412 if (!CGF.HaveInsertPoint())
6413 return;
Alexey Bataev25e5b442015-09-15 12:52:43 +00006414 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006415 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00006416}
6417
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006418namespace {
6419enum RTCancelKind {
6420 CancelNoreq = 0,
6421 CancelParallel = 1,
6422 CancelLoop = 2,
6423 CancelSections = 3,
6424 CancelTaskgroup = 4
6425};
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00006426} // anonymous namespace
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006427
6428static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
6429 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00006430 if (CancelRegion == OMPD_parallel)
6431 CancelKind = CancelParallel;
6432 else if (CancelRegion == OMPD_for)
6433 CancelKind = CancelLoop;
6434 else if (CancelRegion == OMPD_sections)
6435 CancelKind = CancelSections;
6436 else {
6437 assert(CancelRegion == OMPD_taskgroup);
6438 CancelKind = CancelTaskgroup;
6439 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006440 return CancelKind;
6441}
6442
6443void CGOpenMPRuntime::emitCancellationPointCall(
6444 CodeGenFunction &CGF, SourceLocation Loc,
6445 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006446 if (!CGF.HaveInsertPoint())
6447 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006448 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
6449 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006450 if (auto *OMPRegionInfo =
6451 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Jonas Hahnfeldb07931f2017-02-17 18:32:58 +00006452 // For 'cancellation point taskgroup', the task region info may not have a
6453 // cancel. This may instead happen in another adjacent task.
6454 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006455 llvm::Value *Args[] = {
6456 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
6457 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006458 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006459 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006460 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
6461 // if (__kmpc_cancellationpoint()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006462 // exit from construct;
6463 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006464 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6465 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6466 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006467 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6468 CGF.EmitBlock(ExitBB);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006469 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006470 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev25e5b442015-09-15 12:52:43 +00006471 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006472 CGF.EmitBranchThroughCleanup(CancelDest);
6473 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6474 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006475 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006476}
6477
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006478void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00006479 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006480 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006481 if (!CGF.HaveInsertPoint())
6482 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006483 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
6484 // kmp_int32 cncl_kind);
6485 if (auto *OMPRegionInfo =
6486 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006487 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF,
6488 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006489 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev87933c72015-09-18 08:07:34 +00006490 llvm::Value *Args[] = {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006491 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
Alexey Bataev87933c72015-09-18 08:07:34 +00006492 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
6493 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006494 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006495 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
Alexey Bataev87933c72015-09-18 08:07:34 +00006496 // if (__kmpc_cancel()) {
Alexey Bataev87933c72015-09-18 08:07:34 +00006497 // exit from construct;
6498 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006499 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6500 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6501 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev87933c72015-09-18 08:07:34 +00006502 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6503 CGF.EmitBlock(ExitBB);
Alexey Bataev87933c72015-09-18 08:07:34 +00006504 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006505 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev87933c72015-09-18 08:07:34 +00006506 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6507 CGF.EmitBranchThroughCleanup(CancelDest);
6508 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6509 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006510 if (IfCond) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006511 emitOMPIfClause(CGF, IfCond, ThenGen,
6512 [](CodeGenFunction &, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006513 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006514 RegionCodeGenTy ThenRCG(ThenGen);
6515 ThenRCG(CGF);
6516 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006517 }
6518}
Samuel Antaobed3c462015-10-02 16:14:20 +00006519
Samuel Antaoee8fb302016-01-06 13:42:12 +00006520void CGOpenMPRuntime::emitTargetOutlinedFunction(
6521 const OMPExecutableDirective &D, StringRef ParentName,
6522 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006523 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00006524 assert(!ParentName.empty() && "Invalid target region parent name!");
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00006525 HasEmittedTargetRegion = true;
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006526 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
6527 IsOffloadEntry, CodeGen);
6528}
6529
6530void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
6531 const OMPExecutableDirective &D, StringRef ParentName,
6532 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6533 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antao2de62b02016-02-13 23:35:10 +00006534 // Create a unique name for the entry function using the source location
6535 // information of the current target region. The name will be something like:
Samuel Antaoee8fb302016-01-06 13:42:12 +00006536 //
Samuel Antao2de62b02016-02-13 23:35:10 +00006537 // __omp_offloading_DD_FFFF_PP_lBB
Samuel Antaoee8fb302016-01-06 13:42:12 +00006538 //
6539 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
Samuel Antao2de62b02016-02-13 23:35:10 +00006540 // mangled name of the function that encloses the target region and BB is the
6541 // line number of the target region.
Samuel Antaoee8fb302016-01-06 13:42:12 +00006542
6543 unsigned DeviceID;
6544 unsigned FileID;
6545 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00006546 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00006547 Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006548 SmallString<64> EntryFnName;
6549 {
6550 llvm::raw_svector_ostream OS(EntryFnName);
Samuel Antao2de62b02016-02-13 23:35:10 +00006551 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
6552 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00006553 }
6554
Alexey Bataev475a7442018-01-12 19:39:11 +00006555 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006556
Samuel Antaobed3c462015-10-02 16:14:20 +00006557 CodeGenFunction CGF(CGM, true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006558 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
Samuel Antaobed3c462015-10-02 16:14:20 +00006559 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006560
Samuel Antao6d004262016-06-16 18:39:34 +00006561 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006562
6563 // If this target outline function is not an offload entry, we don't need to
6564 // register it.
6565 if (!IsOffloadEntry)
6566 return;
6567
6568 // The target region ID is used by the runtime library to identify the current
6569 // target region, so it only has to be unique and not necessarily point to
6570 // anything. It could be the pointer to the outlined function that implements
6571 // the target region, but we aren't using that so that the compiler doesn't
6572 // need to keep that, and could therefore inline the host function if proven
6573 // worthwhile during optimization. In the other hand, if emitting code for the
6574 // device, the ID has to be the function address so that it can retrieved from
6575 // the offloading entry and launched by the runtime library. We also mark the
6576 // outlined function to have external linkage in case we are emitting code for
6577 // the device, because these functions will be entry points to the device.
6578
6579 if (CGM.getLangOpts().OpenMPIsDevice) {
6580 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
Alexey Bataev9a700172018-05-08 14:16:57 +00006581 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Rafael Espindolacbca4872018-01-11 22:15:12 +00006582 OutlinedFn->setDSOLocal(false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006583 } else {
Alexey Bataevc15ea702018-05-09 18:02:37 +00006584 std::string Name = getName({EntryFnName, "region_id"});
Samuel Antaoee8fb302016-01-06 13:42:12 +00006585 OutlinedFnID = new llvm::GlobalVariable(
6586 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
Alexey Bataev9a700172018-05-08 14:16:57 +00006587 llvm::GlobalValue::WeakAnyLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006588 llvm::Constant::getNullValue(CGM.Int8Ty), Name);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006589 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00006590
6591 // Register the information for the entry associated with this target region.
6592 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
Samuel Antaof83efdb2017-01-05 16:02:49 +00006593 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID,
Alexey Bataev03f270c2018-03-30 18:31:07 +00006594 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion);
Samuel Antaobed3c462015-10-02 16:14:20 +00006595}
6596
Alexey Bataev5c427362019-04-10 19:11:33 +00006597/// Checks if the expression is constant or does not have non-trivial function
6598/// calls.
6599static bool isTrivial(ASTContext &Ctx, const Expr * E) {
6600 // We can skip constant expressions.
6601 // We can skip expressions with trivial calls or simple expressions.
6602 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) ||
6603 !E->hasNonTrivialCall(Ctx)) &&
6604 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true);
6605}
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006606
Alexey Bataev5c427362019-04-10 19:11:33 +00006607const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx,
6608 const Stmt *Body) {
6609 const Stmt *Child = Body->IgnoreContainers();
6610 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) {
6611 Child = nullptr;
6612 for (const Stmt *S : C->body()) {
6613 if (const auto *E = dyn_cast<Expr>(S)) {
6614 if (isTrivial(Ctx, E))
6615 continue;
6616 }
6617 // Some of the statements can be ignored.
6618 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) ||
6619 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S))
6620 continue;
6621 // Analyze declarations.
6622 if (const auto *DS = dyn_cast<DeclStmt>(S)) {
6623 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) {
6624 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6625 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6626 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6627 isa<UsingDirectiveDecl>(D) ||
6628 isa<OMPDeclareReductionDecl>(D) ||
6629 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6630 return true;
6631 const auto *VD = dyn_cast<VarDecl>(D);
6632 if (!VD)
6633 return false;
6634 return VD->isConstexpr() ||
6635 ((VD->getType().isTrivialType(Ctx) ||
6636 VD->getType()->isReferenceType()) &&
6637 (!VD->hasInit() || isTrivial(Ctx, VD->getInit())));
6638 }))
6639 continue;
6640 }
6641 // Found multiple children - cannot get the one child only.
6642 if (Child)
6643 return nullptr;
6644 Child = S;
6645 }
6646 if (Child)
6647 Child = Child->IgnoreContainers();
6648 }
6649 return Child;
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006650}
6651
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006652/// Emit the number of teams for a target directive. Inspect the num_teams
6653/// clause associated with a teams construct combined or closely nested
6654/// with the target directive.
6655///
6656/// Emit a team of size one for directives such as 'target parallel' that
6657/// have no associated teams construct.
6658///
6659/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006660static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006661emitNumTeamsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006662 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006663 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6664 "Clauses associated with the teams directive expected to be emitted "
6665 "only for the host!");
6666 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6667 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6668 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006669 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006670 switch (DirectiveKind) {
6671 case OMPD_target: {
6672 const auto *CS = D.getInnermostCapturedStmt();
6673 const auto *Body =
6674 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
6675 const Stmt *ChildStmt =
6676 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body);
6677 if (const auto *NestedDir =
6678 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6679 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) {
6680 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) {
6681 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6682 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6683 const Expr *NumTeams =
6684 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6685 llvm::Value *NumTeamsVal =
6686 CGF.EmitScalarExpr(NumTeams,
6687 /*IgnoreResultAssign*/ true);
6688 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006689 /*isSigned=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00006690 }
6691 return Bld.getInt32(0);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006692 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006693 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) ||
6694 isOpenMPSimdDirective(NestedDir->getDirectiveKind()))
6695 return Bld.getInt32(1);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006696 return Bld.getInt32(0);
6697 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006698 return nullptr;
Samuel Antaob68e2db2016-03-03 16:20:23 +00006699 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006700 case OMPD_target_teams:
6701 case OMPD_target_teams_distribute:
6702 case OMPD_target_teams_distribute_simd:
6703 case OMPD_target_teams_distribute_parallel_for:
6704 case OMPD_target_teams_distribute_parallel_for_simd: {
6705 if (D.hasClausesOfKind<OMPNumTeamsClause>()) {
6706 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF);
6707 const Expr *NumTeams =
6708 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6709 llvm::Value *NumTeamsVal =
6710 CGF.EmitScalarExpr(NumTeams,
6711 /*IgnoreResultAssign*/ true);
6712 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006713 /*isSigned=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00006714 }
6715 return Bld.getInt32(0);
6716 }
6717 case OMPD_target_parallel:
6718 case OMPD_target_parallel_for:
6719 case OMPD_target_parallel_for_simd:
6720 case OMPD_target_simd:
6721 return Bld.getInt32(1);
6722 case OMPD_parallel:
6723 case OMPD_for:
6724 case OMPD_parallel_for:
6725 case OMPD_parallel_sections:
6726 case OMPD_for_simd:
6727 case OMPD_parallel_for_simd:
6728 case OMPD_cancel:
6729 case OMPD_cancellation_point:
6730 case OMPD_ordered:
6731 case OMPD_threadprivate:
6732 case OMPD_allocate:
6733 case OMPD_task:
6734 case OMPD_simd:
6735 case OMPD_sections:
6736 case OMPD_section:
6737 case OMPD_single:
6738 case OMPD_master:
6739 case OMPD_critical:
6740 case OMPD_taskyield:
6741 case OMPD_barrier:
6742 case OMPD_taskwait:
6743 case OMPD_taskgroup:
6744 case OMPD_atomic:
6745 case OMPD_flush:
6746 case OMPD_teams:
6747 case OMPD_target_data:
6748 case OMPD_target_exit_data:
6749 case OMPD_target_enter_data:
6750 case OMPD_distribute:
6751 case OMPD_distribute_simd:
6752 case OMPD_distribute_parallel_for:
6753 case OMPD_distribute_parallel_for_simd:
6754 case OMPD_teams_distribute:
6755 case OMPD_teams_distribute_simd:
6756 case OMPD_teams_distribute_parallel_for:
6757 case OMPD_teams_distribute_parallel_for_simd:
6758 case OMPD_target_update:
6759 case OMPD_declare_simd:
6760 case OMPD_declare_target:
6761 case OMPD_end_declare_target:
6762 case OMPD_declare_reduction:
6763 case OMPD_declare_mapper:
6764 case OMPD_taskloop:
6765 case OMPD_taskloop_simd:
6766 case OMPD_requires:
6767 case OMPD_unknown:
6768 break;
6769 }
6770 llvm_unreachable("Unexpected directive kind.");
6771}
Samuel Antaob68e2db2016-03-03 16:20:23 +00006772
Alexey Bataev5c427362019-04-10 19:11:33 +00006773static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS,
6774 llvm::Value *DefaultThreadLimitVal) {
6775 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6776 CGF.getContext(), CS->getCapturedStmt());
6777 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6778 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) {
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006779 llvm::Value *NumThreads = nullptr;
6780 llvm::Value *CondVal = nullptr;
6781 // Handle if clause. If if clause present, the number of threads is
6782 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6783 if (Dir->hasClausesOfKind<OMPIfClause>()) {
6784 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6785 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6786 const OMPIfClause *IfClause = nullptr;
6787 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) {
6788 if (C->getNameModifier() == OMPD_unknown ||
6789 C->getNameModifier() == OMPD_parallel) {
6790 IfClause = C;
6791 break;
6792 }
6793 }
6794 if (IfClause) {
6795 const Expr *Cond = IfClause->getCondition();
6796 bool Result;
6797 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6798 if (!Result)
6799 return CGF.Builder.getInt32(1);
6800 } else {
6801 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange());
6802 if (const auto *PreInit =
6803 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) {
6804 for (const auto *I : PreInit->decls()) {
6805 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6806 CGF.EmitVarDecl(cast<VarDecl>(*I));
6807 } else {
6808 CodeGenFunction::AutoVarEmission Emission =
6809 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6810 CGF.EmitAutoVarCleanups(Emission);
6811 }
6812 }
6813 }
6814 CondVal = CGF.EvaluateExprAsBool(Cond);
6815 }
6816 }
6817 }
6818 // Check the value of num_threads clause iff if clause was not specified
6819 // or is not evaluated to false.
Alexey Bataev5c427362019-04-10 19:11:33 +00006820 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) {
6821 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6822 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6823 const auto *NumThreadsClause =
6824 Dir->getSingleClause<OMPNumThreadsClause>();
6825 CodeGenFunction::LexicalScope Scope(
6826 CGF, NumThreadsClause->getNumThreads()->getSourceRange());
6827 if (const auto *PreInit =
6828 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6829 for (const auto *I : PreInit->decls()) {
6830 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6831 CGF.EmitVarDecl(cast<VarDecl>(*I));
6832 } else {
6833 CodeGenFunction::AutoVarEmission Emission =
6834 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6835 CGF.EmitAutoVarCleanups(Emission);
6836 }
6837 }
6838 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006839 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads());
Alexey Bataev5c427362019-04-10 19:11:33 +00006840 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006841 /*isSigned=*/false);
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006842 if (DefaultThreadLimitVal)
6843 NumThreads = CGF.Builder.CreateSelect(
6844 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads),
6845 DefaultThreadLimitVal, NumThreads);
6846 } else {
6847 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal
6848 : CGF.Builder.getInt32(0);
Alexey Bataev5c427362019-04-10 19:11:33 +00006849 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006850 // Process condition of the if clause.
6851 if (CondVal) {
6852 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads,
6853 CGF.Builder.getInt32(1));
6854 }
6855 return NumThreads;
Alexey Bataev5c427362019-04-10 19:11:33 +00006856 }
6857 if (isOpenMPSimdDirective(Dir->getDirectiveKind()))
6858 return CGF.Builder.getInt32(1);
6859 return DefaultThreadLimitVal;
6860 }
6861 return DefaultThreadLimitVal ? DefaultThreadLimitVal
6862 : CGF.Builder.getInt32(0);
Samuel Antaob68e2db2016-03-03 16:20:23 +00006863}
6864
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006865/// Emit the number of threads for a target directive. Inspect the
6866/// thread_limit clause associated with a teams construct combined or closely
6867/// nested with the target directive.
6868///
6869/// Emit the num_threads clause for directives such as 'target parallel' that
6870/// have no associated teams construct.
6871///
6872/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006873static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006874emitNumThreadsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006875 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006876 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6877 "Clauses associated with the teams directive expected to be emitted "
6878 "only for the host!");
6879 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6880 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6881 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006882 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006883 llvm::Value *ThreadLimitVal = nullptr;
6884 llvm::Value *NumThreadsVal = nullptr;
6885 switch (DirectiveKind) {
6886 case OMPD_target: {
6887 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6888 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6889 return NumThreads;
6890 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6891 CGF.getContext(), CS->getCapturedStmt());
6892 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6893 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) {
6894 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6895 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6896 const auto *ThreadLimitClause =
6897 Dir->getSingleClause<OMPThreadLimitClause>();
6898 CodeGenFunction::LexicalScope Scope(
6899 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange());
6900 if (const auto *PreInit =
6901 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6902 for (const auto *I : PreInit->decls()) {
6903 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6904 CGF.EmitVarDecl(cast<VarDecl>(*I));
6905 } else {
6906 CodeGenFunction::AutoVarEmission Emission =
6907 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6908 CGF.EmitAutoVarCleanups(Emission);
6909 }
6910 }
6911 }
6912 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6913 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6914 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006915 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006916 }
6917 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) &&
6918 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) {
6919 CS = Dir->getInnermostCapturedStmt();
6920 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6921 CGF.getContext(), CS->getCapturedStmt());
6922 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6923 }
6924 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) &&
6925 !isOpenMPSimdDirective(Dir->getDirectiveKind())) {
6926 CS = Dir->getInnermostCapturedStmt();
6927 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6928 return NumThreads;
6929 }
6930 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind()))
6931 return Bld.getInt32(1);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006932 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006933 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6934 }
6935 case OMPD_target_teams: {
6936 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6937 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6938 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6939 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6940 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6941 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006942 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006943 }
6944 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6945 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6946 return NumThreads;
6947 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6948 CGF.getContext(), CS->getCapturedStmt());
6949 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6950 if (Dir->getDirectiveKind() == OMPD_distribute) {
6951 CS = Dir->getInnermostCapturedStmt();
6952 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6953 return NumThreads;
6954 }
6955 }
6956 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6957 }
6958 case OMPD_target_teams_distribute:
6959 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6960 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6961 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6962 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6963 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6964 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006965 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006966 }
6967 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal);
6968 case OMPD_target_parallel:
6969 case OMPD_target_parallel_for:
6970 case OMPD_target_parallel_for_simd:
6971 case OMPD_target_teams_distribute_parallel_for:
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006972 case OMPD_target_teams_distribute_parallel_for_simd: {
6973 llvm::Value *CondVal = nullptr;
6974 // Handle if clause. If if clause present, the number of threads is
6975 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6976 if (D.hasClausesOfKind<OMPIfClause>()) {
6977 const OMPIfClause *IfClause = nullptr;
6978 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) {
6979 if (C->getNameModifier() == OMPD_unknown ||
6980 C->getNameModifier() == OMPD_parallel) {
6981 IfClause = C;
6982 break;
6983 }
6984 }
6985 if (IfClause) {
6986 const Expr *Cond = IfClause->getCondition();
6987 bool Result;
6988 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6989 if (!Result)
6990 return Bld.getInt32(1);
6991 } else {
6992 CodeGenFunction::RunCleanupsScope Scope(CGF);
6993 CondVal = CGF.EvaluateExprAsBool(Cond);
6994 }
6995 }
6996 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006997 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6998 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6999 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
7000 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
7001 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
7002 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00007003 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00007004 }
7005 if (D.hasClausesOfKind<OMPNumThreadsClause>()) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00007006 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
Alexey Bataev5c427362019-04-10 19:11:33 +00007007 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>();
7008 llvm::Value *NumThreads = CGF.EmitScalarExpr(
7009 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true);
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00007010 NumThreadsVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00007011 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00007012 ThreadLimitVal = ThreadLimitVal
Alexey Bataev5c427362019-04-10 19:11:33 +00007013 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal,
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00007014 ThreadLimitVal),
7015 NumThreadsVal, ThreadLimitVal)
7016 : NumThreadsVal;
Alexey Bataev50a1c782017-12-01 21:31:08 +00007017 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00007018 if (!ThreadLimitVal)
7019 ThreadLimitVal = Bld.getInt32(0);
7020 if (CondVal)
7021 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1));
7022 return ThreadLimitVal;
7023 }
Alexey Bataev5c427362019-04-10 19:11:33 +00007024 case OMPD_target_teams_distribute_simd:
7025 case OMPD_target_simd:
7026 return Bld.getInt32(1);
7027 case OMPD_parallel:
7028 case OMPD_for:
7029 case OMPD_parallel_for:
7030 case OMPD_parallel_sections:
7031 case OMPD_for_simd:
7032 case OMPD_parallel_for_simd:
7033 case OMPD_cancel:
7034 case OMPD_cancellation_point:
7035 case OMPD_ordered:
7036 case OMPD_threadprivate:
7037 case OMPD_allocate:
7038 case OMPD_task:
7039 case OMPD_simd:
7040 case OMPD_sections:
7041 case OMPD_section:
7042 case OMPD_single:
7043 case OMPD_master:
7044 case OMPD_critical:
7045 case OMPD_taskyield:
7046 case OMPD_barrier:
7047 case OMPD_taskwait:
7048 case OMPD_taskgroup:
7049 case OMPD_atomic:
7050 case OMPD_flush:
7051 case OMPD_teams:
7052 case OMPD_target_data:
7053 case OMPD_target_exit_data:
7054 case OMPD_target_enter_data:
7055 case OMPD_distribute:
7056 case OMPD_distribute_simd:
7057 case OMPD_distribute_parallel_for:
7058 case OMPD_distribute_parallel_for_simd:
7059 case OMPD_teams_distribute:
7060 case OMPD_teams_distribute_simd:
7061 case OMPD_teams_distribute_parallel_for:
7062 case OMPD_teams_distribute_parallel_for_simd:
7063 case OMPD_target_update:
7064 case OMPD_declare_simd:
7065 case OMPD_declare_target:
7066 case OMPD_end_declare_target:
7067 case OMPD_declare_reduction:
7068 case OMPD_declare_mapper:
7069 case OMPD_taskloop:
7070 case OMPD_taskloop_simd:
7071 case OMPD_requires:
7072 case OMPD_unknown:
7073 break;
Samuel Antaob68e2db2016-03-03 16:20:23 +00007074 }
Alexey Bataev5c427362019-04-10 19:11:33 +00007075 llvm_unreachable("Unsupported directive kind.");
Samuel Antaob68e2db2016-03-03 16:20:23 +00007076}
7077
Samuel Antao86ace552016-04-27 22:40:57 +00007078namespace {
Alexey Bataevb3638132018-07-19 16:34:13 +00007079LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
7080
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007081// Utility to handle information from clauses associated with a given
Samuel Antao86ace552016-04-27 22:40:57 +00007082// construct that use mappable expressions (e.g. 'map' clause, 'to' clause).
7083// It provides a convenient interface to obtain the information and generate
7084// code for that information.
7085class MappableExprsHandler {
7086public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007087 /// Values for bit flags used to specify the mapping type for
Samuel Antao86ace552016-04-27 22:40:57 +00007088 /// offloading.
Alexey Bataevb3638132018-07-19 16:34:13 +00007089 enum OpenMPOffloadMappingFlags : uint64_t {
7090 /// No flags
7091 OMP_MAP_NONE = 0x0,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007092 /// Allocate memory on the device and move data from host to device.
Samuel Antao86ace552016-04-27 22:40:57 +00007093 OMP_MAP_TO = 0x01,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007094 /// Allocate memory on the device and move data from device to host.
Samuel Antao86ace552016-04-27 22:40:57 +00007095 OMP_MAP_FROM = 0x02,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007096 /// Always perform the requested mapping action on the element, even
Samuel Antao86ace552016-04-27 22:40:57 +00007097 /// if it was already mapped before.
7098 OMP_MAP_ALWAYS = 0x04,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007099 /// Delete the element from the device environment, ignoring the
Samuel Antao86ace552016-04-27 22:40:57 +00007100 /// current reference count associated with the element.
Samuel Antao6782e942016-05-26 16:48:10 +00007101 OMP_MAP_DELETE = 0x08,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007102 /// The element being mapped is a pointer-pointee pair; both the
George Rokos065755d2017-11-07 18:27:04 +00007103 /// pointer and the pointee should be mapped.
7104 OMP_MAP_PTR_AND_OBJ = 0x10,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007105 /// This flags signals that the base address of an entry should be
George Rokos065755d2017-11-07 18:27:04 +00007106 /// passed to the target kernel as an argument.
7107 OMP_MAP_TARGET_PARAM = 0x20,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007108 /// Signal that the runtime library has to return the device pointer
George Rokos065755d2017-11-07 18:27:04 +00007109 /// in the current position for the data being mapped. Used when we have the
7110 /// use_device_ptr clause.
7111 OMP_MAP_RETURN_PARAM = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007112 /// This flag signals that the reference being passed is a pointer to
Samuel Antaod486f842016-05-26 16:53:38 +00007113 /// private data.
George Rokos065755d2017-11-07 18:27:04 +00007114 OMP_MAP_PRIVATE = 0x80,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007115 /// Pass the element to the device by value.
George Rokos065755d2017-11-07 18:27:04 +00007116 OMP_MAP_LITERAL = 0x100,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007117 /// Implicit map
7118 OMP_MAP_IMPLICIT = 0x200,
Alexey Bataevb3638132018-07-19 16:34:13 +00007119 /// The 16 MSBs of the flags indicate whether the entry is member of some
7120 /// struct/class.
7121 OMP_MAP_MEMBER_OF = 0xffff000000000000,
7122 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF),
Samuel Antao86ace552016-04-27 22:40:57 +00007123 };
7124
Michael Krused47b9432019-08-05 18:43:21 +00007125 /// Get the offset of the OMP_MAP_MEMBER_OF field.
7126 static unsigned getFlagMemberOffset() {
7127 unsigned Offset = 0;
7128 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1);
7129 Remain = Remain >> 1)
7130 Offset++;
7131 return Offset;
7132 }
7133
Samuel Antaocc10b852016-07-28 14:23:26 +00007134 /// Class that associates information with a base pointer to be passed to the
7135 /// runtime library.
7136 class BasePointerInfo {
7137 /// The base pointer.
7138 llvm::Value *Ptr = nullptr;
7139 /// The base declaration that refers to this device pointer, or null if
7140 /// there is none.
7141 const ValueDecl *DevPtrDecl = nullptr;
7142
7143 public:
7144 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr)
7145 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {}
7146 llvm::Value *operator*() const { return Ptr; }
7147 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; }
7148 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; }
7149 };
7150
Alexey Bataevb3638132018-07-19 16:34:13 +00007151 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>;
7152 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>;
7153 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>;
7154
7155 /// Map between a struct and the its lowest & highest elements which have been
7156 /// mapped.
7157 /// [ValueDecl *] --> {LE(FieldIndex, Pointer),
7158 /// HE(FieldIndex, Pointer)}
7159 struct StructRangeInfoTy {
7160 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = {
7161 0, Address::invalid()};
7162 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = {
7163 0, Address::invalid()};
7164 Address Base = Address::invalid();
7165 };
Samuel Antao86ace552016-04-27 22:40:57 +00007166
7167private:
Alexey Bataevb3638132018-07-19 16:34:13 +00007168 /// Kind that defines how a device pointer has to be returned.
7169 struct MapInfo {
7170 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
7171 OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
Kelvin Lief579432018-12-18 22:18:41 +00007172 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataevb3638132018-07-19 16:34:13 +00007173 bool ReturnDevicePointer = false;
7174 bool IsImplicit = false;
7175
7176 MapInfo() = default;
7177 MapInfo(
7178 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Kelvin Lief579432018-12-18 22:18:41 +00007179 OpenMPMapClauseKind MapType,
7180 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007181 bool ReturnDevicePointer, bool IsImplicit)
Kelvin Lief579432018-12-18 22:18:41 +00007182 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
Alexey Bataevb3638132018-07-19 16:34:13 +00007183 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {}
7184 };
7185
7186 /// If use_device_ptr is used on a pointer which is a struct member and there
7187 /// is no map information about it, then emission of that entry is deferred
7188 /// until the whole struct has been processed.
7189 struct DeferredDevicePtrEntryTy {
7190 const Expr *IE = nullptr;
7191 const ValueDecl *VD = nullptr;
7192
7193 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD)
7194 : IE(IE), VD(VD) {}
7195 };
7196
Michael Krused47b9432019-08-05 18:43:21 +00007197 /// The target directive from where the mappable clauses were extracted. It
7198 /// is either a executable directive or a user-defined mapper directive.
7199 llvm::PointerUnion<const OMPExecutableDirective *,
7200 const OMPDeclareMapperDecl *>
7201 CurDir;
Samuel Antao86ace552016-04-27 22:40:57 +00007202
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007203 /// Function the directive is being generated for.
Samuel Antao86ace552016-04-27 22:40:57 +00007204 CodeGenFunction &CGF;
7205
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007206 /// Set of all first private variables in the current directive.
Alexey Bataevf288cf92019-06-27 18:53:07 +00007207 /// bool data is set to true if the variable is implicitly marked as
7208 /// firstprivate, false otherwise.
7209 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls;
Samuel Antaod486f842016-05-26 16:53:38 +00007210
Samuel Antao6890b092016-07-28 14:25:09 +00007211 /// Map between device pointer declarations and their expression components.
7212 /// The key value for declarations in 'this' is null.
7213 llvm::DenseMap<
7214 const ValueDecl *,
7215 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7216 DevPointersMap;
7217
Samuel Antao86ace552016-04-27 22:40:57 +00007218 llvm::Value *getExprTypeSize(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007219 QualType ExprTy = E->getType().getCanonicalType();
Samuel Antao86ace552016-04-27 22:40:57 +00007220
7221 // Reference types are ignored for mapping purposes.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007222 if (const auto *RefTy = ExprTy->getAs<ReferenceType>())
Samuel Antao86ace552016-04-27 22:40:57 +00007223 ExprTy = RefTy->getPointeeType().getCanonicalType();
7224
7225 // Given that an array section is considered a built-in type, we need to
7226 // do the calculation based on the length of the section instead of relying
7227 // on CGF.getTypeSize(E->getType()).
7228 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) {
7229 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType(
7230 OAE->getBase()->IgnoreParenImpCasts())
7231 .getCanonicalType();
7232
7233 // If there is no length associated with the expression, that means we
7234 // are using the whole length of the base.
7235 if (!OAE->getLength() && OAE->getColonLoc().isValid())
7236 return CGF.getTypeSize(BaseTy);
7237
7238 llvm::Value *ElemSize;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007239 if (const auto *PTy = BaseTy->getAs<PointerType>()) {
Samuel Antao86ace552016-04-27 22:40:57 +00007240 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007241 } else {
7242 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr());
Samuel Antao86ace552016-04-27 22:40:57 +00007243 assert(ATy && "Expecting array type if not a pointer type.");
7244 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType());
7245 }
7246
7247 // If we don't have a length at this point, that is because we have an
7248 // array section with a single element.
7249 if (!OAE->getLength())
7250 return ElemSize;
7251
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007252 llvm::Value *LengthVal = CGF.EmitScalarExpr(OAE->getLength());
Samuel Antao86ace552016-04-27 22:40:57 +00007253 LengthVal =
7254 CGF.Builder.CreateIntCast(LengthVal, CGF.SizeTy, /*isSigned=*/false);
7255 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize);
7256 }
7257 return CGF.getTypeSize(ExprTy);
7258 }
7259
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007260 /// Return the corresponding bits for a given map clause modifier. Add
Samuel Antao86ace552016-04-27 22:40:57 +00007261 /// a flag marking the map as a pointer if requested. Add a flag marking the
Samuel Antao6782e942016-05-26 16:48:10 +00007262 /// map as the first one of a series of maps that relate to the same map
7263 /// expression.
Kelvin Lief579432018-12-18 22:18:41 +00007264 OpenMPOffloadMappingFlags getMapTypeBits(
7265 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
7266 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const {
Alexey Bataevb3638132018-07-19 16:34:13 +00007267 OpenMPOffloadMappingFlags Bits =
7268 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE;
Samuel Antao86ace552016-04-27 22:40:57 +00007269 switch (MapType) {
7270 case OMPC_MAP_alloc:
Samuel Antao6782e942016-05-26 16:48:10 +00007271 case OMPC_MAP_release:
7272 // alloc and release is the default behavior in the runtime library, i.e.
7273 // if we don't pass any bits alloc/release that is what the runtime is
7274 // going to do. Therefore, we don't need to signal anything for these two
7275 // type modifiers.
Samuel Antao86ace552016-04-27 22:40:57 +00007276 break;
7277 case OMPC_MAP_to:
Alexey Bataevb3638132018-07-19 16:34:13 +00007278 Bits |= OMP_MAP_TO;
Samuel Antao86ace552016-04-27 22:40:57 +00007279 break;
7280 case OMPC_MAP_from:
Alexey Bataevb3638132018-07-19 16:34:13 +00007281 Bits |= OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007282 break;
7283 case OMPC_MAP_tofrom:
Alexey Bataevb3638132018-07-19 16:34:13 +00007284 Bits |= OMP_MAP_TO | OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007285 break;
7286 case OMPC_MAP_delete:
Alexey Bataevb3638132018-07-19 16:34:13 +00007287 Bits |= OMP_MAP_DELETE;
Samuel Antao86ace552016-04-27 22:40:57 +00007288 break;
Alexey Bataevb3638132018-07-19 16:34:13 +00007289 case OMPC_MAP_unknown:
Samuel Antao86ace552016-04-27 22:40:57 +00007290 llvm_unreachable("Unexpected map type!");
Samuel Antao86ace552016-04-27 22:40:57 +00007291 }
7292 if (AddPtrFlag)
George Rokos065755d2017-11-07 18:27:04 +00007293 Bits |= OMP_MAP_PTR_AND_OBJ;
7294 if (AddIsTargetParamFlag)
7295 Bits |= OMP_MAP_TARGET_PARAM;
Kelvin Lief579432018-12-18 22:18:41 +00007296 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always)
7297 != MapModifiers.end())
Samuel Antao86ace552016-04-27 22:40:57 +00007298 Bits |= OMP_MAP_ALWAYS;
7299 return Bits;
7300 }
7301
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007302 /// Return true if the provided expression is a final array section. A
Samuel Antao86ace552016-04-27 22:40:57 +00007303 /// final array section, is one whose length can't be proved to be one.
7304 bool isFinalArraySectionExpression(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007305 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
Samuel Antao86ace552016-04-27 22:40:57 +00007306
7307 // It is not an array section and therefore not a unity-size one.
7308 if (!OASE)
7309 return false;
7310
7311 // An array section with no colon always refer to a single element.
7312 if (OASE->getColonLoc().isInvalid())
7313 return false;
7314
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007315 const Expr *Length = OASE->getLength();
Samuel Antao86ace552016-04-27 22:40:57 +00007316
7317 // If we don't have a length we have to check if the array has size 1
7318 // for this dimension. Also, we should always expect a length if the
7319 // base type is pointer.
7320 if (!Length) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007321 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType(
7322 OASE->getBase()->IgnoreParenImpCasts())
7323 .getCanonicalType();
7324 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
Samuel Antao86ace552016-04-27 22:40:57 +00007325 return ATy->getSize().getSExtValue() != 1;
7326 // If we don't have a constant dimension length, we have to consider
7327 // the current section as having any size, so it is not necessarily
7328 // unitary. If it happen to be unity size, that's user fault.
7329 return true;
7330 }
7331
7332 // Check if the length evaluates to 1.
Fangrui Song407659a2018-11-30 23:41:18 +00007333 Expr::EvalResult Result;
7334 if (!Length->EvaluateAsInt(Result, CGF.getContext()))
Samuel Antao86ace552016-04-27 22:40:57 +00007335 return true; // Can have more that size 1.
7336
Fangrui Song407659a2018-11-30 23:41:18 +00007337 llvm::APSInt ConstLength = Result.Val.getInt();
Samuel Antao86ace552016-04-27 22:40:57 +00007338 return ConstLength.getSExtValue() != 1;
7339 }
7340
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007341 /// Generate the base pointers, section pointers, sizes and map type
Samuel Antao86ace552016-04-27 22:40:57 +00007342 /// bits for the provided map type, map modifier, and expression components.
7343 /// \a IsFirstComponent should be set to true if the provided set of
7344 /// components is the first associated with a capture.
7345 void generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00007346 OpenMPMapClauseKind MapType,
7347 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Samuel Antao86ace552016-04-27 22:40:57 +00007348 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Samuel Antaocc10b852016-07-28 14:23:26 +00007349 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007350 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
Alexey Bataevb3638132018-07-19 16:34:13 +00007351 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007352 bool IsImplicit,
7353 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7354 OverlappedElements = llvm::None) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007355 // The following summarizes what has to be generated for each map and the
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00007356 // types below. The generated information is expressed in this order:
Samuel Antao86ace552016-04-27 22:40:57 +00007357 // base pointer, section pointer, size, flags
7358 // (to add to the ones that come from the map type and modifier).
7359 //
7360 // double d;
7361 // int i[100];
7362 // float *p;
7363 //
7364 // struct S1 {
7365 // int i;
7366 // float f[50];
7367 // }
7368 // struct S2 {
7369 // int i;
7370 // float f[50];
7371 // S1 s;
7372 // double *p;
7373 // struct S2 *ps;
7374 // }
7375 // S2 s;
7376 // S2 *ps;
7377 //
7378 // map(d)
Alexey Bataevb3638132018-07-19 16:34:13 +00007379 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007380 //
7381 // map(i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007382 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007383 //
7384 // map(i[1:23])
Alexey Bataevb3638132018-07-19 16:34:13 +00007385 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007386 //
7387 // map(p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007388 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007389 //
7390 // map(p[1:24])
Alexey Bataevb3638132018-07-19 16:34:13 +00007391 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007392 //
7393 // map(s)
Alexey Bataevb3638132018-07-19 16:34:13 +00007394 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007395 //
7396 // map(s.i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007397 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007398 //
7399 // map(s.s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007400 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007401 //
7402 // map(s.p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007403 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007404 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007405 // map(to: s.p[:22])
7406 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*)
7407 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**)
7408 // &(s.p), &(s.p[0]), 22*sizeof(double),
7409 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***)
7410 // (*) alloc space for struct members, only this is a target parameter
7411 // (**) map the pointer (nothing to be mapped in this example) (the compiler
7412 // optimizes this entry out, same in the examples below)
7413 // (***) map the pointee (map: to)
Samuel Antao86ace552016-04-27 22:40:57 +00007414 //
7415 // map(s.ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007416 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007417 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007418 // map(from: s.ps->s.i)
7419 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7420 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7421 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007422 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007423 // map(to: s.ps->ps)
7424 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7425 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7426 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007427 //
7428 // map(s.ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007429 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7430 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7431 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7432 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007433 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007434 // map(to: s.ps->ps->s.f[:22])
7435 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7436 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7437 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7438 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007439 //
7440 // map(ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007441 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007442 //
7443 // map(ps->i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007444 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007445 //
7446 // map(ps->s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007447 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007448 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007449 // map(from: ps->p)
7450 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007451 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007452 // map(to: ps->p[:22])
7453 // ps, &(ps->p), sizeof(double*), TARGET_PARAM
7454 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1)
7455 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007456 //
7457 // map(ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007458 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007459 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007460 // map(from: ps->ps->s.i)
7461 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7462 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7463 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007464 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007465 // map(from: ps->ps->ps)
7466 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7467 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7468 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007469 //
7470 // map(ps->ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007471 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7472 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7473 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7474 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007475 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007476 // map(to: ps->ps->ps->s.f[:22])
7477 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7478 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7479 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7480 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
7481 //
7482 // map(to: s.f[:22]) map(from: s.p[:33])
7483 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) +
7484 // sizeof(double*) (**), TARGET_PARAM
7485 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO
7486 // &s, &(s.p), sizeof(double*), MEMBER_OF(1)
7487 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7488 // (*) allocate contiguous space needed to fit all mapped members even if
7489 // we allocate space for members not mapped (in this example,
7490 // s.f[22..49] and s.s are not mapped, yet we must allocate space for
7491 // them as well because they fall between &s.f[0] and &s.p)
7492 //
7493 // map(from: s.f[:22]) map(to: ps->p[:33])
7494 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM
7495 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7496 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*)
7497 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO
7498 // (*) the struct this entry pertains to is the 2nd element in the list of
7499 // arguments, hence MEMBER_OF(2)
7500 //
7501 // map(from: s.f[:22], s.s) map(to: ps->p[:33])
7502 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM
7503 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM
7504 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM
7505 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7506 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*)
7507 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO
7508 // (*) the struct this entry pertains to is the 4th element in the list
7509 // of arguments, hence MEMBER_OF(4)
Samuel Antao86ace552016-04-27 22:40:57 +00007510
7511 // Track if the map information being generated is the first for a capture.
7512 bool IsCaptureFirstInfo = IsFirstComponentList;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007513 // When the variable is on a declare target link or in a to clause with
7514 // unified memory, a reference is needed to hold the host/device address
7515 // of the variable.
7516 bool RequiresReference = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007517
7518 // Scan the components from the base to the complete expression.
7519 auto CI = Components.rbegin();
7520 auto CE = Components.rend();
7521 auto I = CI;
7522
7523 // Track if the map information being generated is the first for a list of
7524 // components.
7525 bool IsExpressionFirstInfo = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00007526 Address BP = Address::invalid();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007527 const Expr *AssocExpr = I->getAssociatedExpression();
7528 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7529 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
Samuel Antao86ace552016-04-27 22:40:57 +00007530
Patrick Lystere13b1e32019-01-02 19:28:48 +00007531 if (isa<MemberExpr>(AssocExpr)) {
Samuel Antao86ace552016-04-27 22:40:57 +00007532 // The base is the 'this' pointer. The content of the pointer is going
7533 // to be the base of the field being mapped.
Alexey Bataevb3638132018-07-19 16:34:13 +00007534 BP = CGF.LoadCXXThisAddress();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007535 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7536 (OASE &&
7537 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
7538 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
Samuel Antao86ace552016-04-27 22:40:57 +00007539 } else {
7540 // The base is the reference to the variable.
7541 // BP = &Var.
Patrick Lystere13b1e32019-01-02 19:28:48 +00007542 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
Alexey Bataev92327c52018-03-26 16:40:55 +00007543 if (const auto *VD =
7544 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7545 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007546 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7547 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7548 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
7549 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) {
7550 RequiresReference = true;
7551 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataev2c1dffe2018-04-16 20:34:41 +00007552 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007553 }
Alexey Bataev92327c52018-03-26 16:40:55 +00007554 }
Samuel Antao86ace552016-04-27 22:40:57 +00007555
7556 // If the variable is a pointer and is being dereferenced (i.e. is not
Nico Webera6916892016-06-10 18:53:04 +00007557 // the last component), the base has to be the pointer itself, not its
Samuel Antao403ffd42016-07-27 22:49:49 +00007558 // reference. References are ignored for mapping purposes.
7559 QualType Ty =
7560 I->getAssociatedDeclaration()->getType().getNonReferenceType();
7561 if (Ty->isAnyPointerType() && std::next(I) != CE) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007562 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
Samuel Antao86ace552016-04-27 22:40:57 +00007563
7564 // We do not need to generate individual map information for the
7565 // pointer, it can be associated with the combined storage.
7566 ++I;
7567 }
7568 }
7569
Alexey Bataevb3638132018-07-19 16:34:13 +00007570 // Track whether a component of the list should be marked as MEMBER_OF some
7571 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry
7572 // in a component list should be marked as MEMBER_OF, all subsequent entries
7573 // do not belong to the base struct. E.g.
7574 // struct S2 s;
7575 // s.ps->ps->ps->f[:]
7576 // (1) (2) (3) (4)
7577 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a
7578 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3)
7579 // is the pointee of ps(2) which is not member of struct s, so it should not
7580 // be marked as such (it is still PTR_AND_OBJ).
7581 // The variable is initialized to false so that PTR_AND_OBJ entries which
7582 // are not struct members are not considered (e.g. array of pointers to
7583 // data).
7584 bool ShouldBeMemberOf = false;
7585
7586 // Variable keeping track of whether or not we have encountered a component
7587 // in the component list which is a member expression. Useful when we have a
7588 // pointer or a final array section, in which case it is the previous
7589 // component in the list which tells us whether we have a member expression.
7590 // E.g. X.f[:]
7591 // While processing the final array section "[:]" it is "f" which tells us
7592 // whether we are dealing with a member of a declared struct.
7593 const MemberExpr *EncounteredME = nullptr;
7594
Samuel Antao86ace552016-04-27 22:40:57 +00007595 for (; I != CE; ++I) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007596 // If the current component is member of a struct (parent struct) mark it.
7597 if (!EncounteredME) {
7598 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7599 // If we encounter a PTR_AND_OBJ entry from now on it should be marked
7600 // as MEMBER_OF the parent struct.
7601 if (EncounteredME)
7602 ShouldBeMemberOf = true;
7603 }
7604
Samuel Antao86ace552016-04-27 22:40:57 +00007605 auto Next = std::next(I);
7606
7607 // We need to generate the addresses and sizes if this is the last
7608 // component, if the component is a pointer or if it is an array section
7609 // whose length can't be proved to be one. If this is a pointer, it
7610 // becomes the base address for the following components.
7611
7612 // A final array section, is one whose length can't be proved to be one.
7613 bool IsFinalArraySection =
7614 isFinalArraySectionExpression(I->getAssociatedExpression());
7615
7616 // Get information on whether the element is a pointer. Have to do a
7617 // special treatment for array sections given that they are built-in
7618 // types.
7619 const auto *OASE =
7620 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression());
7621 bool IsPointer =
Alexey Bataevb3638132018-07-19 16:34:13 +00007622 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE)
7623 .getCanonicalType()
7624 ->isAnyPointerType()) ||
Samuel Antao86ace552016-04-27 22:40:57 +00007625 I->getAssociatedExpression()->getType()->isAnyPointerType();
7626
7627 if (Next == CE || IsPointer || IsFinalArraySection) {
Samuel Antao86ace552016-04-27 22:40:57 +00007628 // If this is not the last component, we expect the pointer to be
7629 // associated with an array expression or member expression.
7630 assert((Next == CE ||
7631 isa<MemberExpr>(Next->getAssociatedExpression()) ||
7632 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||
7633 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) &&
7634 "Unexpected expression");
7635
Alexey Bataevb3638132018-07-19 16:34:13 +00007636 Address LB =
7637 CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getAddress();
Samuel Antao86ace552016-04-27 22:40:57 +00007638
Alexey Bataevb3638132018-07-19 16:34:13 +00007639 // If this component is a pointer inside the base struct then we don't
7640 // need to create any entry for it - it will be combined with the object
7641 // it is pointing to into a single PTR_AND_OBJ entry.
7642 bool IsMemberPointer =
7643 IsPointer && EncounteredME &&
7644 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) ==
7645 EncounteredME);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007646 if (!OverlappedElements.empty()) {
7647 // Handle base element with the info for overlapped elements.
7648 assert(!PartialStruct.Base.isValid() && "The base element is set.");
7649 assert(Next == CE &&
7650 "Expected last element for the overlapped elements.");
7651 assert(!IsPointer &&
7652 "Unexpected base element with the pointer type.");
7653 // Mark the whole struct as the struct that requires allocation on the
7654 // device.
7655 PartialStruct.LowestElem = {0, LB};
7656 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(
7657 I->getAssociatedExpression()->getType());
7658 Address HB = CGF.Builder.CreateConstGEP(
7659 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB,
7660 CGF.VoidPtrTy),
James Y Knight751fe282019-02-09 22:22:28 +00007661 TypeSize.getQuantity() - 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007662 PartialStruct.HighestElem = {
7663 std::numeric_limits<decltype(
7664 PartialStruct.HighestElem.first)>::max(),
7665 HB};
7666 PartialStruct.Base = BP;
7667 // Emit data for non-overlapped data.
7668 OpenMPOffloadMappingFlags Flags =
7669 OMP_MAP_MEMBER_OF |
Kelvin Lief579432018-12-18 22:18:41 +00007670 getMapTypeBits(MapType, MapModifiers, IsImplicit,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007671 /*AddPtrFlag=*/false,
7672 /*AddIsTargetParamFlag=*/false);
7673 LB = BP;
7674 llvm::Value *Size = nullptr;
7675 // Do bitcopy of all non-overlapped structure elements.
7676 for (OMPClauseMappableExprCommon::MappableExprComponentListRef
7677 Component : OverlappedElements) {
7678 Address ComponentLB = Address::invalid();
7679 for (const OMPClauseMappableExprCommon::MappableComponent &MC :
7680 Component) {
7681 if (MC.getAssociatedDeclaration()) {
7682 ComponentLB =
7683 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
7684 .getAddress();
7685 Size = CGF.Builder.CreatePtrDiff(
7686 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()),
7687 CGF.EmitCastToVoidPtr(LB.getPointer()));
7688 break;
7689 }
7690 }
7691 BasePointers.push_back(BP.getPointer());
7692 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007693 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty,
7694 /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007695 Types.push_back(Flags);
James Y Knight751fe282019-02-09 22:22:28 +00007696 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007697 }
7698 BasePointers.push_back(BP.getPointer());
7699 Pointers.push_back(LB.getPointer());
7700 Size = CGF.Builder.CreatePtrDiff(
7701 CGF.EmitCastToVoidPtr(
James Y Knight751fe282019-02-09 22:22:28 +00007702 CGF.Builder.CreateConstGEP(HB, 1).getPointer()),
Alexey Bataeve82445f2018-09-20 13:54:02 +00007703 CGF.EmitCastToVoidPtr(LB.getPointer()));
Alexey Bataeva90fc662019-06-25 16:00:43 +00007704 Sizes.push_back(
7705 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007706 Types.push_back(Flags);
7707 break;
7708 }
7709 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
Alexey Bataevb3638132018-07-19 16:34:13 +00007710 if (!IsMemberPointer) {
7711 BasePointers.push_back(BP.getPointer());
7712 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007713 Sizes.push_back(
7714 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Samuel Antao03a3cec2016-07-27 22:52:16 +00007715
Alexey Bataevb3638132018-07-19 16:34:13 +00007716 // We need to add a pointer flag for each map that comes from the
7717 // same expression except for the first one. We also need to signal
7718 // this map is the first one that relates with the current capture
7719 // (there is a set of entries for each capture).
7720 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
Kelvin Lief579432018-12-18 22:18:41 +00007721 MapType, MapModifiers, IsImplicit,
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007722 !IsExpressionFirstInfo || RequiresReference,
7723 IsCaptureFirstInfo && !RequiresReference);
Alexey Bataevb3638132018-07-19 16:34:13 +00007724
7725 if (!IsExpressionFirstInfo) {
7726 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
7727 // then we reset the TO/FROM/ALWAYS/DELETE flags.
7728 if (IsPointer)
7729 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS |
7730 OMP_MAP_DELETE);
7731
7732 if (ShouldBeMemberOf) {
7733 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag
7734 // should be later updated with the correct value of MEMBER_OF.
7735 Flags |= OMP_MAP_MEMBER_OF;
7736 // From now on, all subsequent PTR_AND_OBJ entries should not be
7737 // marked as MEMBER_OF.
7738 ShouldBeMemberOf = false;
7739 }
7740 }
7741
7742 Types.push_back(Flags);
Samuel Antao03a3cec2016-07-27 22:52:16 +00007743 }
7744
Alexey Bataevb3638132018-07-19 16:34:13 +00007745 // If we have encountered a member expression so far, keep track of the
7746 // mapped member. If the parent is "*this", then the value declaration
7747 // is nullptr.
7748 if (EncounteredME) {
7749 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl());
7750 unsigned FieldIndex = FD->getFieldIndex();
Samuel Antao03a3cec2016-07-27 22:52:16 +00007751
Alexey Bataevb3638132018-07-19 16:34:13 +00007752 // Update info about the lowest and highest elements for this struct
7753 if (!PartialStruct.Base.isValid()) {
7754 PartialStruct.LowestElem = {FieldIndex, LB};
7755 PartialStruct.HighestElem = {FieldIndex, LB};
7756 PartialStruct.Base = BP;
7757 } else if (FieldIndex < PartialStruct.LowestElem.first) {
7758 PartialStruct.LowestElem = {FieldIndex, LB};
7759 } else if (FieldIndex > PartialStruct.HighestElem.first) {
7760 PartialStruct.HighestElem = {FieldIndex, LB};
7761 }
7762 }
Samuel Antao86ace552016-04-27 22:40:57 +00007763
7764 // If we have a final array section, we are done with this expression.
7765 if (IsFinalArraySection)
7766 break;
7767
7768 // The pointer becomes the base for the next element.
7769 if (Next != CE)
7770 BP = LB;
7771
7772 IsExpressionFirstInfo = false;
7773 IsCaptureFirstInfo = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007774 }
7775 }
7776 }
7777
Alexey Bataevb3638132018-07-19 16:34:13 +00007778 /// Return the adjusted map modifiers if the declaration a capture refers to
7779 /// appears in a first-private clause. This is expected to be used only with
7780 /// directives that start with 'target'.
7781 MappableExprsHandler::OpenMPOffloadMappingFlags
7782 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const {
7783 assert(Cap.capturesVariable() && "Expected capture by reference only!");
7784
7785 // A first private variable captured by reference will use only the
7786 // 'private ptr' and 'map to' flag. Return the right flags if the captured
7787 // declaration is known as first-private in this handler.
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007788 if (FirstPrivateDecls.count(Cap.getCapturedVar())) {
7789 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) &&
7790 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef)
7791 return MappableExprsHandler::OMP_MAP_ALWAYS |
7792 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataevc2b831f2019-04-02 16:03:40 +00007793 if (Cap.getCapturedVar()->getType()->isAnyPointerType())
7794 return MappableExprsHandler::OMP_MAP_TO |
7795 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ;
Alexey Bataevb3638132018-07-19 16:34:13 +00007796 return MappableExprsHandler::OMP_MAP_PRIVATE |
7797 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007798 }
Alexey Bataevb3638132018-07-19 16:34:13 +00007799 return MappableExprsHandler::OMP_MAP_TO |
7800 MappableExprsHandler::OMP_MAP_FROM;
7801 }
7802
7803 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) {
Michael Krused47b9432019-08-05 18:43:21 +00007804 // Rotate by getFlagMemberOffset() bits.
Alexey Bataevb3638132018-07-19 16:34:13 +00007805 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1)
Michael Krused47b9432019-08-05 18:43:21 +00007806 << getFlagMemberOffset());
Alexey Bataevb3638132018-07-19 16:34:13 +00007807 }
7808
7809 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags,
7810 OpenMPOffloadMappingFlags MemberOfFlag) {
7811 // If the entry is PTR_AND_OBJ but has not been marked with the special
7812 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be
7813 // marked as MEMBER_OF.
7814 if ((Flags & OMP_MAP_PTR_AND_OBJ) &&
7815 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF))
7816 return;
7817
7818 // Reset the placeholder value to prepare the flag for the assignment of the
7819 // proper MEMBER_OF value.
7820 Flags &= ~OMP_MAP_MEMBER_OF;
7821 Flags |= MemberOfFlag;
7822 }
7823
Alexey Bataeve82445f2018-09-20 13:54:02 +00007824 void getPlainLayout(const CXXRecordDecl *RD,
7825 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
7826 bool AsBase) const {
7827 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD);
7828
7829 llvm::StructType *St =
7830 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType();
7831
7832 unsigned NumElements = St->getNumElements();
7833 llvm::SmallVector<
7834 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
7835 RecordLayout(NumElements);
7836
7837 // Fill bases.
7838 for (const auto &I : RD->bases()) {
7839 if (I.isVirtual())
7840 continue;
7841 const auto *Base = I.getType()->getAsCXXRecordDecl();
7842 // Ignore empty bases.
7843 if (Base->isEmpty() || CGF.getContext()
7844 .getASTRecordLayout(Base)
7845 .getNonVirtualSize()
7846 .isZero())
7847 continue;
7848
7849 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
7850 RecordLayout[FieldIndex] = Base;
7851 }
7852 // Fill in virtual bases.
7853 for (const auto &I : RD->vbases()) {
7854 const auto *Base = I.getType()->getAsCXXRecordDecl();
7855 // Ignore empty bases.
7856 if (Base->isEmpty())
7857 continue;
7858 unsigned FieldIndex = RL.getVirtualBaseIndex(Base);
7859 if (RecordLayout[FieldIndex])
7860 continue;
7861 RecordLayout[FieldIndex] = Base;
7862 }
7863 // Fill in all the fields.
7864 assert(!RD->isUnion() && "Unexpected union.");
7865 for (const auto *Field : RD->fields()) {
7866 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
7867 // will fill in later.)
Richard Smith78b239e2019-06-20 20:44:45 +00007868 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) {
Alexey Bataeve82445f2018-09-20 13:54:02 +00007869 unsigned FieldIndex = RL.getLLVMFieldNo(Field);
7870 RecordLayout[FieldIndex] = Field;
7871 }
7872 }
7873 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
7874 &Data : RecordLayout) {
7875 if (Data.isNull())
7876 continue;
7877 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>())
7878 getPlainLayout(Base, Layout, /*AsBase=*/true);
7879 else
7880 Layout.push_back(Data.get<const FieldDecl *>());
7881 }
7882 }
7883
Alexey Bataevb3638132018-07-19 16:34:13 +00007884public:
7885 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
Michael Krused47b9432019-08-05 18:43:21 +00007886 : CurDir(&Dir), CGF(CGF) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007887 // Extract firstprivate clause information.
7888 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>())
7889 for (const auto *D : C->varlists())
Alexey Bataevf288cf92019-06-27 18:53:07 +00007890 FirstPrivateDecls.try_emplace(
7891 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit());
Alexey Bataevb3638132018-07-19 16:34:13 +00007892 // Extract device pointer clause information.
7893 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
7894 for (auto L : C->component_lists())
7895 DevPointersMap[L.first].push_back(L.second);
7896 }
7897
Michael Krused47b9432019-08-05 18:43:21 +00007898 /// Constructor for the declare mapper directive.
7899 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF)
7900 : CurDir(&Dir), CGF(CGF) {}
7901
Alexey Bataevb3638132018-07-19 16:34:13 +00007902 /// Generate code for the combined entry if we have a partially mapped struct
7903 /// and take care of the mapping flags of the arguments corresponding to
7904 /// individual struct members.
7905 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers,
7906 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7907 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes,
7908 const StructRangeInfoTy &PartialStruct) const {
7909 // Base is the base of the struct
7910 BasePointers.push_back(PartialStruct.Base.getPointer());
7911 // Pointer is the address of the lowest element
7912 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer();
7913 Pointers.push_back(LB);
7914 // Size is (addr of {highest+1} element) - (addr of lowest element)
7915 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer();
7916 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1);
7917 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy);
7918 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy);
7919 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00007920 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00007921 /*isSigned=*/false);
Alexey Bataevb3638132018-07-19 16:34:13 +00007922 Sizes.push_back(Size);
7923 // Map type is always TARGET_PARAM
7924 Types.push_back(OMP_MAP_TARGET_PARAM);
7925 // Remove TARGET_PARAM flag from the first element
7926 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM;
7927
7928 // All other current entries will be MEMBER_OF the combined entry
7929 // (except for PTR_AND_OBJ entries which do not have a placeholder value
7930 // 0xFFFF in the MEMBER_OF field).
7931 OpenMPOffloadMappingFlags MemberOfFlag =
7932 getMemberOfFlag(BasePointers.size() - 1);
7933 for (auto &M : CurTypes)
7934 setCorrectMemberOfFlag(M, MemberOfFlag);
7935 }
7936
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007937 /// Generate all the base pointers, section pointers, sizes and map
Samuel Antaocc10b852016-07-28 14:23:26 +00007938 /// types for the extracted mappable expressions. Also, for each item that
7939 /// relates with a device pointer, a pair of the relevant declaration and
7940 /// index where it occurs is appended to the device pointers info array.
7941 void generateAllInfo(MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007942 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7943 MapFlagsArrayTy &Types) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007944 // We have to process the component lists that relate with the same
7945 // declaration in a single chunk so that we can generate the map flags
7946 // correctly. Therefore, we organize all lists in a map.
Alexey Bataev5d1c3f62017-06-27 15:46:42 +00007947 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
Samuel Antao8d2d7302016-05-26 18:30:22 +00007948
7949 // Helper function to fill the information map for the different supported
7950 // clauses.
Samuel Antaocc10b852016-07-28 14:23:26 +00007951 auto &&InfoGen = [&Info](
7952 const ValueDecl *D,
7953 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
Kelvin Lief579432018-12-18 22:18:41 +00007954 OpenMPMapClauseKind MapType,
7955 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007956 bool ReturnDevicePointer, bool IsImplicit) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007957 const ValueDecl *VD =
7958 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
Kelvin Lief579432018-12-18 22:18:41 +00007959 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007960 IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00007961 };
Samuel Antao8d2d7302016-05-26 18:30:22 +00007962
Michael Krused47b9432019-08-05 18:43:21 +00007963 assert(CurDir.is<const OMPExecutableDirective *>() &&
7964 "Expect a executable directive");
7965 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
7966 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007967 for (const auto &L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007968 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(),
Alexey Bataevb3638132018-07-19 16:34:13 +00007969 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007970 }
Michael Krused47b9432019-08-05 18:43:21 +00007971 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007972 for (const auto &L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007973 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007974 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007975 }
Michael Krused47b9432019-08-05 18:43:21 +00007976 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007977 for (const auto &L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007978 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007979 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007980 }
Samuel Antao86ace552016-04-27 22:40:57 +00007981
Samuel Antaocc10b852016-07-28 14:23:26 +00007982 // Look at the use_device_ptr clause information and mark the existing map
7983 // entries as such. If there is no map information for an entry in the
7984 // use_device_ptr list, we create one with map type 'alloc' and zero size
Alexey Bataevb3638132018-07-19 16:34:13 +00007985 // section. It is the user fault if that was not mapped before. If there is
7986 // no map information and the pointer is a struct member, then we defer the
7987 // emission of that entry until the whole struct has been processed.
7988 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>>
7989 DeferredInfo;
7990
Alexey Bataevb3638132018-07-19 16:34:13 +00007991 for (const auto *C :
Michael Krused47b9432019-08-05 18:43:21 +00007992 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007993 for (const auto &L : C->component_lists()) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007994 assert(!L.second.empty() && "Not expecting empty list of components!");
7995 const ValueDecl *VD = L.second.back().getAssociatedDeclaration();
7996 VD = cast<ValueDecl>(VD->getCanonicalDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007997 const Expr *IE = L.second.back().getAssociatedExpression();
Samuel Antaocc10b852016-07-28 14:23:26 +00007998 // If the first component is a member expression, we have to look into
7999 // 'this', which maps to null in the map of map information. Otherwise
8000 // look directly for the information.
8001 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
8002
8003 // We potentially have map information for this declaration already.
8004 // Look for the first set of components that refer to it.
8005 if (It != Info.end()) {
8006 auto CI = std::find_if(
8007 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) {
8008 return MI.Components.back().getAssociatedDeclaration() == VD;
8009 });
8010 // If we found a map entry, signal that the pointer has to be returned
8011 // and move on to the next declaration.
8012 if (CI != It->second.end()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00008013 CI->ReturnDevicePointer = true;
Samuel Antaocc10b852016-07-28 14:23:26 +00008014 continue;
8015 }
8016 }
8017
8018 // We didn't find any match in our map information - generate a zero
Alexey Bataevb3638132018-07-19 16:34:13 +00008019 // size array section - if the pointer is a struct member we defer this
8020 // action until the whole struct has been processed.
Alexey Bataevb3638132018-07-19 16:34:13 +00008021 if (isa<MemberExpr>(IE)) {
8022 // Insert the pointer into Info to be processed by
8023 // generateInfoForComponentList. Because it is a member pointer
8024 // without a pointee, no entry will be generated for it, therefore
8025 // we need to generate one after the whole struct has been processed.
8026 // Nonetheless, generateInfoForComponentList must be called to take
8027 // the pointer into account for the calculation of the range of the
8028 // partial struct.
Kelvin Lief579432018-12-18 22:18:41 +00008029 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00008030 /*ReturnDevicePointer=*/false, C->isImplicit());
8031 DeferredInfo[nullptr].emplace_back(IE, VD);
8032 } else {
Michael Krused47b9432019-08-05 18:43:21 +00008033 llvm::Value *Ptr =
8034 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc());
Alexey Bataevb3638132018-07-19 16:34:13 +00008035 BasePointers.emplace_back(Ptr, VD);
8036 Pointers.push_back(Ptr);
Michael Krused47b9432019-08-05 18:43:21 +00008037 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00008038 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM);
8039 }
Samuel Antaocc10b852016-07-28 14:23:26 +00008040 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008041 }
Samuel Antaocc10b852016-07-28 14:23:26 +00008042
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008043 for (const auto &M : Info) {
Samuel Antao86ace552016-04-27 22:40:57 +00008044 // We need to know when we generate information for the first component
8045 // associated with a capture, because the mapping flags depend on it.
8046 bool IsFirstComponentList = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00008047
8048 // Temporary versions of arrays
8049 MapBaseValuesArrayTy CurBasePointers;
8050 MapValuesArrayTy CurPointers;
8051 MapValuesArrayTy CurSizes;
8052 MapFlagsArrayTy CurTypes;
8053 StructRangeInfoTy PartialStruct;
8054
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008055 for (const MapInfo &L : M.second) {
Samuel Antao86ace552016-04-27 22:40:57 +00008056 assert(!L.Components.empty() &&
8057 "Not expecting declaration with no component lists.");
Samuel Antaocc10b852016-07-28 14:23:26 +00008058
8059 // Remember the current base pointer index.
Alexey Bataevb3638132018-07-19 16:34:13 +00008060 unsigned CurrentBasePointersIdx = CurBasePointers.size();
Michael Krused47b9432019-08-05 18:43:21 +00008061 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8062 CurBasePointers, CurPointers, CurSizes,
8063 CurTypes, PartialStruct,
8064 IsFirstComponentList, L.IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00008065
8066 // If this entry relates with a device pointer, set the relevant
8067 // declaration and add the 'return pointer' flag.
Alexey Bataevb3638132018-07-19 16:34:13 +00008068 if (L.ReturnDevicePointer) {
8069 assert(CurBasePointers.size() > CurrentBasePointersIdx &&
Samuel Antaocc10b852016-07-28 14:23:26 +00008070 "Unexpected number of mapped base pointers.");
8071
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008072 const ValueDecl *RelevantVD =
8073 L.Components.back().getAssociatedDeclaration();
Samuel Antaocc10b852016-07-28 14:23:26 +00008074 assert(RelevantVD &&
8075 "No relevant declaration related with device pointer??");
8076
Alexey Bataevb3638132018-07-19 16:34:13 +00008077 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD);
8078 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008079 }
Samuel Antao86ace552016-04-27 22:40:57 +00008080 IsFirstComponentList = false;
8081 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008082
8083 // Append any pending zero-length pointers which are struct members and
8084 // used with use_device_ptr.
8085 auto CI = DeferredInfo.find(M.first);
8086 if (CI != DeferredInfo.end()) {
8087 for (const DeferredDevicePtrEntryTy &L : CI->second) {
8088 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer();
8089 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar(
8090 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc());
8091 CurBasePointers.emplace_back(BasePtr, L.VD);
8092 CurPointers.push_back(Ptr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008093 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00008094 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder
8095 // value MEMBER_OF=FFFF so that the entry is later updated with the
8096 // correct value of MEMBER_OF.
8097 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM |
8098 OMP_MAP_MEMBER_OF);
8099 }
8100 }
8101
8102 // If there is an entry in PartialStruct it means we have a struct with
8103 // individual members mapped. Emit an extra combined entry.
8104 if (PartialStruct.Base.isValid())
8105 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8106 PartialStruct);
8107
8108 // We need to append the results of this capture to what we already have.
8109 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8110 Pointers.append(CurPointers.begin(), CurPointers.end());
8111 Sizes.append(CurSizes.begin(), CurSizes.end());
8112 Types.append(CurTypes.begin(), CurTypes.end());
Samuel Antao86ace552016-04-27 22:40:57 +00008113 }
8114 }
8115
Michael Krused47b9432019-08-05 18:43:21 +00008116 /// Generate all the base pointers, section pointers, sizes and map types for
8117 /// the extracted map clauses of user-defined mapper.
8118 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers,
8119 MapValuesArrayTy &Pointers,
8120 MapValuesArrayTy &Sizes,
8121 MapFlagsArrayTy &Types) const {
8122 assert(CurDir.is<const OMPDeclareMapperDecl *>() &&
8123 "Expect a declare mapper directive");
8124 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>();
8125 // We have to process the component lists that relate with the same
8126 // declaration in a single chunk so that we can generate the map flags
8127 // correctly. Therefore, we organize all lists in a map.
8128 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
8129
8130 // Helper function to fill the information map for the different supported
8131 // clauses.
8132 auto &&InfoGen = [&Info](
8133 const ValueDecl *D,
8134 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
8135 OpenMPMapClauseKind MapType,
8136 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8137 bool ReturnDevicePointer, bool IsImplicit) {
8138 const ValueDecl *VD =
8139 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
8140 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
8141 IsImplicit);
8142 };
8143
8144 for (const auto *C : CurMapperDir->clauselists()) {
8145 const auto *MC = cast<OMPMapClause>(C);
8146 for (const auto &L : MC->component_lists()) {
8147 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(),
8148 /*ReturnDevicePointer=*/false, MC->isImplicit());
8149 }
8150 }
8151
8152 for (const auto &M : Info) {
8153 // We need to know when we generate information for the first component
8154 // associated with a capture, because the mapping flags depend on it.
8155 bool IsFirstComponentList = true;
8156
8157 // Temporary versions of arrays
8158 MapBaseValuesArrayTy CurBasePointers;
8159 MapValuesArrayTy CurPointers;
8160 MapValuesArrayTy CurSizes;
8161 MapFlagsArrayTy CurTypes;
8162 StructRangeInfoTy PartialStruct;
8163
8164 for (const MapInfo &L : M.second) {
8165 assert(!L.Components.empty() &&
8166 "Not expecting declaration with no component lists.");
8167 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8168 CurBasePointers, CurPointers, CurSizes,
8169 CurTypes, PartialStruct,
8170 IsFirstComponentList, L.IsImplicit);
8171 IsFirstComponentList = false;
8172 }
8173
8174 // If there is an entry in PartialStruct it means we have a struct with
8175 // individual members mapped. Emit an extra combined entry.
8176 if (PartialStruct.Base.isValid())
8177 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8178 PartialStruct);
8179
8180 // We need to append the results of this capture to what we already have.
8181 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8182 Pointers.append(CurPointers.begin(), CurPointers.end());
8183 Sizes.append(CurSizes.begin(), CurSizes.end());
8184 Types.append(CurTypes.begin(), CurTypes.end());
8185 }
8186 }
8187
Alexey Bataev60705422018-10-30 15:50:12 +00008188 /// Emit capture info for lambdas for variables captured by reference.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008189 void generateInfoForLambdaCaptures(
8190 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers,
8191 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
8192 MapFlagsArrayTy &Types,
8193 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008194 const auto *RD = VD->getType()
8195 .getCanonicalType()
8196 .getNonReferenceType()
8197 ->getAsCXXRecordDecl();
8198 if (!RD || !RD->isLambda())
8199 return;
8200 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD));
8201 LValue VDLVal = CGF.MakeAddrLValue(
8202 VDAddr, VD->getType().getCanonicalType().getNonReferenceType());
8203 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
8204 FieldDecl *ThisCapture = nullptr;
8205 RD->getCaptureFields(Captures, ThisCapture);
8206 if (ThisCapture) {
8207 LValue ThisLVal =
8208 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture);
Alexey Bataev969dbc02018-11-08 15:47:39 +00008209 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture);
8210 LambdaPointers.try_emplace(ThisLVal.getPointer(), VDLVal.getPointer());
8211 BasePointers.push_back(ThisLVal.getPointer());
8212 Pointers.push_back(ThisLValVal.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00008213 Sizes.push_back(
8214 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8215 CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008216 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008217 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8218 }
8219 for (const LambdaCapture &LC : RD->captures()) {
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008220 if (!LC.capturesVariable())
Alexey Bataev60705422018-10-30 15:50:12 +00008221 continue;
8222 const VarDecl *VD = LC.getCapturedVar();
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008223 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType())
8224 continue;
Alexey Bataev60705422018-10-30 15:50:12 +00008225 auto It = Captures.find(VD);
8226 assert(It != Captures.end() && "Found lambda capture without field.");
8227 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second);
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008228 if (LC.getCaptureKind() == LCK_ByRef) {
8229 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second);
8230 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer());
8231 BasePointers.push_back(VarLVal.getPointer());
8232 Pointers.push_back(VarLValVal.getPointer());
8233 Sizes.push_back(CGF.Builder.CreateIntCast(
8234 CGF.getTypeSize(
8235 VD->getType().getCanonicalType().getNonReferenceType()),
8236 CGF.Int64Ty, /*isSigned=*/true));
8237 } else {
8238 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation());
8239 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer());
8240 BasePointers.push_back(VarLVal.getPointer());
8241 Pointers.push_back(VarRVal.getScalarVal());
8242 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0));
8243 }
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008244 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008245 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8246 }
8247 }
8248
8249 /// Set correct indices for lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008250 void adjustMemberOfForLambdaCaptures(
8251 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
8252 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
8253 MapFlagsArrayTy &Types) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008254 for (unsigned I = 0, E = Types.size(); I < E; ++I) {
8255 // Set correct member_of idx for all implicit lambda captures.
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008256 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008257 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT))
8258 continue;
Alexey Bataev969dbc02018-11-08 15:47:39 +00008259 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]);
8260 assert(BasePtr && "Unable to find base lambda address.");
Alexey Bataev60705422018-10-30 15:50:12 +00008261 int TgtIdx = -1;
8262 for (unsigned J = I; J > 0; --J) {
8263 unsigned Idx = J - 1;
8264 if (Pointers[Idx] != BasePtr)
8265 continue;
8266 TgtIdx = Idx;
8267 break;
8268 }
8269 assert(TgtIdx != -1 && "Unable to find parent lambda.");
8270 // All other current entries will be MEMBER_OF the combined entry
8271 // (except for PTR_AND_OBJ entries which do not have a placeholder value
8272 // 0xFFFF in the MEMBER_OF field).
8273 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx);
8274 setCorrectMemberOfFlag(Types[I], MemberOfFlag);
8275 }
8276 }
8277
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008278 /// Generate the base pointers, section pointers, sizes and map types
Samuel Antao86ace552016-04-27 22:40:57 +00008279 /// associated to a given capture.
8280 void generateInfoForCapture(const CapturedStmt::Capture *Cap,
Samuel Antao6890b092016-07-28 14:25:09 +00008281 llvm::Value *Arg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008282 MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00008283 MapValuesArrayTy &Pointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008284 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
8285 StructRangeInfoTy &PartialStruct) const {
Samuel Antao86ace552016-04-27 22:40:57 +00008286 assert(!Cap->capturesVariableArrayType() &&
8287 "Not expecting to generate map info for a variable array type!");
8288
Samuel Antao6890b092016-07-28 14:25:09 +00008289 // We need to know when we generating information for the first component
Alexey Bataevb3638132018-07-19 16:34:13 +00008290 const ValueDecl *VD = Cap->capturesThis()
8291 ? nullptr
8292 : Cap->getCapturedVar()->getCanonicalDecl();
Samuel Antao86ace552016-04-27 22:40:57 +00008293
Samuel Antao6890b092016-07-28 14:25:09 +00008294 // If this declaration appears in a is_device_ptr clause we just have to
8295 // pass the pointer by value. If it is a reference to a declaration, we just
Alexey Bataevb3638132018-07-19 16:34:13 +00008296 // pass its value.
8297 if (DevPointersMap.count(VD)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008298 BasePointers.emplace_back(Arg, VD);
Samuel Antao6890b092016-07-28 14:25:09 +00008299 Pointers.push_back(Arg);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008300 Sizes.push_back(
8301 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8302 CGF.Int64Ty, /*isSigned=*/true));
George Rokos065755d2017-11-07 18:27:04 +00008303 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM);
Samuel Antao6890b092016-07-28 14:25:09 +00008304 return;
8305 }
8306
Alexey Bataeve82445f2018-09-20 13:54:02 +00008307 using MapData =
8308 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
Kelvin Lief579432018-12-18 22:18:41 +00008309 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008310 SmallVector<MapData, 4> DeclComponentLists;
Michael Krused47b9432019-08-05 18:43:21 +00008311 assert(CurDir.is<const OMPExecutableDirective *>() &&
8312 "Expect a executable directive");
8313 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
8314 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008315 for (const auto &L : C->decl_component_lists(VD)) {
Samuel Antao86ace552016-04-27 22:40:57 +00008316 assert(L.first == VD &&
8317 "We got information for the wrong declaration??");
8318 assert(!L.second.empty() &&
8319 "Not expecting declaration with no component lists.");
Alexey Bataeve82445f2018-09-20 13:54:02 +00008320 DeclComponentLists.emplace_back(L.second, C->getMapType(),
Kelvin Lief579432018-12-18 22:18:41 +00008321 C->getMapTypeModifiers(),
Alexey Bataeve82445f2018-09-20 13:54:02 +00008322 C->isImplicit());
Samuel Antao86ace552016-04-27 22:40:57 +00008323 }
Alexey Bataeve82445f2018-09-20 13:54:02 +00008324 }
8325
8326 // Find overlapping elements (including the offset from the base element).
8327 llvm::SmallDenseMap<
8328 const MapData *,
8329 llvm::SmallVector<
8330 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>,
8331 4>
8332 OverlappedData;
8333 size_t Count = 0;
8334 for (const MapData &L : DeclComponentLists) {
8335 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8336 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008337 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008338 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008339 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008340 ++Count;
8341 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) {
8342 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1;
Kelvin Lief579432018-12-18 22:18:41 +00008343 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008344 auto CI = Components.rbegin();
8345 auto CE = Components.rend();
8346 auto SI = Components1.rbegin();
8347 auto SE = Components1.rend();
8348 for (; CI != CE && SI != SE; ++CI, ++SI) {
8349 if (CI->getAssociatedExpression()->getStmtClass() !=
8350 SI->getAssociatedExpression()->getStmtClass())
8351 break;
8352 // Are we dealing with different variables/fields?
8353 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
8354 break;
8355 }
8356 // Found overlapping if, at least for one component, reached the head of
8357 // the components list.
8358 if (CI == CE || SI == SE) {
8359 assert((CI != CE || SI != SE) &&
8360 "Unexpected full match of the mapping components.");
8361 const MapData &BaseData = CI == CE ? L : L1;
8362 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData =
8363 SI == SE ? Components : Components1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008364 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData);
8365 OverlappedElements.getSecond().push_back(SubData);
8366 }
8367 }
8368 }
8369 // Sort the overlapped elements for each item.
8370 llvm::SmallVector<const FieldDecl *, 4> Layout;
8371 if (!OverlappedData.empty()) {
8372 if (const auto *CRD =
8373 VD->getType().getCanonicalType()->getAsCXXRecordDecl())
8374 getPlainLayout(CRD, Layout, /*AsBase=*/false);
8375 else {
8376 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl();
8377 Layout.append(RD->field_begin(), RD->field_end());
8378 }
8379 }
8380 for (auto &Pair : OverlappedData) {
8381 llvm::sort(
8382 Pair.getSecond(),
8383 [&Layout](
8384 OMPClauseMappableExprCommon::MappableExprComponentListRef First,
8385 OMPClauseMappableExprCommon::MappableExprComponentListRef
8386 Second) {
8387 auto CI = First.rbegin();
8388 auto CE = First.rend();
8389 auto SI = Second.rbegin();
8390 auto SE = Second.rend();
8391 for (; CI != CE && SI != SE; ++CI, ++SI) {
8392 if (CI->getAssociatedExpression()->getStmtClass() !=
8393 SI->getAssociatedExpression()->getStmtClass())
8394 break;
8395 // Are we dealing with different variables/fields?
8396 if (CI->getAssociatedDeclaration() !=
8397 SI->getAssociatedDeclaration())
8398 break;
8399 }
Richard Trieu5061e832018-09-21 21:20:33 +00008400
8401 // Lists contain the same elements.
8402 if (CI == CE && SI == SE)
8403 return false;
8404
8405 // List with less elements is less than list with more elements.
8406 if (CI == CE || SI == SE)
8407 return CI == CE;
8408
Alexey Bataeve82445f2018-09-20 13:54:02 +00008409 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
8410 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
8411 if (FD1->getParent() == FD2->getParent())
8412 return FD1->getFieldIndex() < FD2->getFieldIndex();
8413 const auto It =
8414 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) {
8415 return FD == FD1 || FD == FD2;
8416 });
8417 return *It == FD1;
8418 });
8419 }
8420
8421 // Associated with a capture, because the mapping flags depend on it.
8422 // Go through all of the elements with the overlapped elements.
8423 for (const auto &Pair : OverlappedData) {
8424 const MapData &L = *Pair.getFirst();
8425 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8426 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008427 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008428 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008429 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008430 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
8431 OverlappedComponents = Pair.getSecond();
8432 bool IsFirstComponentList = true;
Kelvin Lief579432018-12-18 22:18:41 +00008433 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008434 BasePointers, Pointers, Sizes, Types,
8435 PartialStruct, IsFirstComponentList,
8436 IsImplicit, OverlappedComponents);
8437 }
8438 // Go through other elements without overlapped elements.
8439 bool IsFirstComponentList = OverlappedData.empty();
8440 for (const MapData &L : DeclComponentLists) {
8441 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8442 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008443 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008444 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008445 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008446 auto It = OverlappedData.find(&L);
8447 if (It == OverlappedData.end())
Kelvin Lief579432018-12-18 22:18:41 +00008448 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008449 BasePointers, Pointers, Sizes, Types,
8450 PartialStruct, IsFirstComponentList,
8451 IsImplicit);
8452 IsFirstComponentList = false;
8453 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008454 }
Samuel Antao86ace552016-04-27 22:40:57 +00008455
Alexey Bataevb3638132018-07-19 16:34:13 +00008456 /// Generate the base pointers, section pointers, sizes and map types
8457 /// associated with the declare target link variables.
8458 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers,
8459 MapValuesArrayTy &Pointers,
8460 MapValuesArrayTy &Sizes,
8461 MapFlagsArrayTy &Types) const {
Michael Krused47b9432019-08-05 18:43:21 +00008462 assert(CurDir.is<const OMPExecutableDirective *>() &&
8463 "Expect a executable directive");
8464 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
Alexey Bataevb3638132018-07-19 16:34:13 +00008465 // Map other list items in the map clause which are not captured variables
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00008466 // but "declare target link" global variables.
Michael Krused47b9432019-08-05 18:43:21 +00008467 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00008468 for (const auto &L : C->component_lists()) {
8469 if (!L.first)
8470 continue;
8471 const auto *VD = dyn_cast<VarDecl>(L.first);
8472 if (!VD)
8473 continue;
8474 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00008475 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00008476 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
8477 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)
Alexey Bataevb3638132018-07-19 16:34:13 +00008478 continue;
8479 StructRangeInfoTy PartialStruct;
8480 generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00008481 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008482 Pointers, Sizes, Types, PartialStruct,
8483 /*IsFirstComponentList=*/true, C->isImplicit());
8484 assert(!PartialStruct.Base.isValid() &&
8485 "No partial structs for declare target link expected.");
8486 }
8487 }
Samuel Antao86ace552016-04-27 22:40:57 +00008488 }
Samuel Antaod486f842016-05-26 16:53:38 +00008489
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008490 /// Generate the default map information for a given capture \a CI,
Samuel Antaod486f842016-05-26 16:53:38 +00008491 /// record field declaration \a RI and captured value \a CV.
Samuel Antaocc10b852016-07-28 14:23:26 +00008492 void generateDefaultMapInfo(const CapturedStmt::Capture &CI,
8493 const FieldDecl &RI, llvm::Value *CV,
8494 MapBaseValuesArrayTy &CurBasePointers,
8495 MapValuesArrayTy &CurPointers,
8496 MapValuesArrayTy &CurSizes,
Alexey Bataevb3638132018-07-19 16:34:13 +00008497 MapFlagsArrayTy &CurMapTypes) const {
Alexey Bataevf288cf92019-06-27 18:53:07 +00008498 bool IsImplicit = true;
Samuel Antaod486f842016-05-26 16:53:38 +00008499 // Do the default mapping.
8500 if (CI.capturesThis()) {
8501 CurBasePointers.push_back(CV);
8502 CurPointers.push_back(CV);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008503 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr());
Alexey Bataeva90fc662019-06-25 16:00:43 +00008504 CurSizes.push_back(
8505 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()),
8506 CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008507 // Default map type.
Samuel Antaocc10b852016-07-28 14:23:26 +00008508 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM);
Samuel Antaod486f842016-05-26 16:53:38 +00008509 } else if (CI.capturesVariableByCopy()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008510 CurBasePointers.push_back(CV);
8511 CurPointers.push_back(CV);
Samuel Antaod486f842016-05-26 16:53:38 +00008512 if (!RI.getType()->isAnyPointerType()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008513 // We have to signal to the runtime captures passed by value that are
8514 // not pointers.
George Rokos065755d2017-11-07 18:27:04 +00008515 CurMapTypes.push_back(OMP_MAP_LITERAL);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008516 CurSizes.push_back(CGF.Builder.CreateIntCast(
8517 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008518 } else {
8519 // Pointers are implicitly mapped with a zero size and no flags
8520 // (other than first map that is added for all implicit maps).
Alexey Bataevb3638132018-07-19 16:34:13 +00008521 CurMapTypes.push_back(OMP_MAP_NONE);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008522 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
Samuel Antaod486f842016-05-26 16:53:38 +00008523 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008524 const VarDecl *VD = CI.getCapturedVar();
8525 auto I = FirstPrivateDecls.find(VD);
8526 if (I != FirstPrivateDecls.end())
8527 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008528 } else {
8529 assert(CI.capturesVariable() && "Expected captured reference.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008530 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr());
Samuel Antaod486f842016-05-26 16:53:38 +00008531 QualType ElementType = PtrTy->getPointeeType();
Alexey Bataeva90fc662019-06-25 16:00:43 +00008532 CurSizes.push_back(CGF.Builder.CreateIntCast(
8533 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008534 // The default map type for a scalar/complex type is 'to' because by
8535 // default the value doesn't have to be retrieved. For an aggregate
8536 // type, the default is 'tofrom'.
Alexey Bataevb3638132018-07-19 16:34:13 +00008537 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI));
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008538 const VarDecl *VD = CI.getCapturedVar();
Alexey Bataevf288cf92019-06-27 18:53:07 +00008539 auto I = FirstPrivateDecls.find(VD);
8540 if (I != FirstPrivateDecls.end() &&
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008541 VD->getType().isConstant(CGF.getContext())) {
8542 llvm::Constant *Addr =
8543 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD);
8544 // Copy the value of the original variable to the new global copy.
8545 CGF.Builder.CreateMemCpy(
8546 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(),
8547 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)),
Rui Ueyama49a3ad22019-07-16 04:46:31 +00008548 CurSizes.back(), /*IsVolatile=*/false);
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008549 // Use new global variable as the base pointers.
8550 CurBasePointers.push_back(Addr);
8551 CurPointers.push_back(Addr);
8552 } else {
8553 CurBasePointers.push_back(CV);
Alexey Bataevf288cf92019-06-27 18:53:07 +00008554 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) {
Alexey Bataevc2b831f2019-04-02 16:03:40 +00008555 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue(
8556 CV, ElementType, CGF.getContext().getDeclAlign(VD),
8557 AlignmentSource::Decl));
8558 CurPointers.push_back(PtrAddr.getPointer());
8559 } else {
8560 CurPointers.push_back(CV);
8561 }
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008562 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008563 if (I != FirstPrivateDecls.end())
8564 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008565 }
George Rokos065755d2017-11-07 18:27:04 +00008566 // Every default map produces a single argument which is a target parameter.
8567 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM;
Alexey Bataevb3638132018-07-19 16:34:13 +00008568
8569 // Add flag stating this is an implicit map.
Alexey Bataevf288cf92019-06-27 18:53:07 +00008570 if (IsImplicit)
8571 CurMapTypes.back() |= OMP_MAP_IMPLICIT;
Samuel Antaod486f842016-05-26 16:53:38 +00008572 }
Samuel Antao86ace552016-04-27 22:40:57 +00008573};
Samuel Antaodf158d52016-04-27 22:58:19 +00008574} // anonymous namespace
8575
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008576/// Emit the arrays used to pass the captures and map information to the
Samuel Antaodf158d52016-04-27 22:58:19 +00008577/// offloading runtime library. If there is no map or capture information,
8578/// return nullptr by reference.
8579static void
Samuel Antaocc10b852016-07-28 14:23:26 +00008580emitOffloadingArrays(CodeGenFunction &CGF,
8581 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers,
Samuel Antaodf158d52016-04-27 22:58:19 +00008582 MappableExprsHandler::MapValuesArrayTy &Pointers,
8583 MappableExprsHandler::MapValuesArrayTy &Sizes,
Samuel Antaocc10b852016-07-28 14:23:26 +00008584 MappableExprsHandler::MapFlagsArrayTy &MapTypes,
8585 CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008586 CodeGenModule &CGM = CGF.CGM;
8587 ASTContext &Ctx = CGF.getContext();
Samuel Antaodf158d52016-04-27 22:58:19 +00008588
Samuel Antaocc10b852016-07-28 14:23:26 +00008589 // Reset the array information.
8590 Info.clearArrayInfo();
8591 Info.NumberOfPtrs = BasePointers.size();
Samuel Antaodf158d52016-04-27 22:58:19 +00008592
Samuel Antaocc10b852016-07-28 14:23:26 +00008593 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008594 // Detect if we have any capture size requiring runtime evaluation of the
8595 // size so that a constant array could be eventually used.
8596 bool hasRuntimeEvaluationCaptureSize = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008597 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008598 if (!isa<llvm::Constant>(S)) {
8599 hasRuntimeEvaluationCaptureSize = true;
8600 break;
8601 }
8602
Samuel Antaocc10b852016-07-28 14:23:26 +00008603 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true);
Samuel Antaodf158d52016-04-27 22:58:19 +00008604 QualType PointerArrayType =
8605 Ctx.getConstantArrayType(Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal,
8606 /*IndexTypeQuals=*/0);
8607
Samuel Antaocc10b852016-07-28 14:23:26 +00008608 Info.BasePointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008609 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
Samuel Antaocc10b852016-07-28 14:23:26 +00008610 Info.PointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008611 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
8612
8613 // If we don't have any VLA types or other types that require runtime
8614 // evaluation, we can use a constant array for the map sizes, otherwise we
8615 // need to fill up the arrays as we do for the pointers.
Alexey Bataeva90fc662019-06-25 16:00:43 +00008616 QualType Int64Ty =
8617 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Samuel Antaodf158d52016-04-27 22:58:19 +00008618 if (hasRuntimeEvaluationCaptureSize) {
Alexey Bataeva90fc662019-06-25 16:00:43 +00008619 QualType SizeArrayType =
8620 Ctx.getConstantArrayType(Int64Ty, PointerNumAP, ArrayType::Normal,
8621 /*IndexTypeQuals=*/0);
Samuel Antaocc10b852016-07-28 14:23:26 +00008622 Info.SizesArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008623 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
8624 } else {
8625 // We expect all the sizes to be constant, so we collect them to create
8626 // a constant array.
8627 SmallVector<llvm::Constant *, 16> ConstSizes;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008628 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008629 ConstSizes.push_back(cast<llvm::Constant>(S));
8630
8631 auto *SizesArrayInit = llvm::ConstantArray::get(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008632 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008633 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008634 auto *SizesArrayGbl = new llvm::GlobalVariable(
8635 CGM.getModule(), SizesArrayInit->getType(),
8636 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008637 SizesArrayInit, Name);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008638 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008639 Info.SizesArray = SizesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008640 }
8641
8642 // The map types are always constant so we don't need to generate code to
8643 // fill arrays. Instead, we create an array constant.
Alexey Bataevb3638132018-07-19 16:34:13 +00008644 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0);
8645 llvm::copy(MapTypes, Mapping.begin());
Samuel Antaodf158d52016-04-27 22:58:19 +00008646 llvm::Constant *MapTypesArrayInit =
Alexey Bataevb3638132018-07-19 16:34:13 +00008647 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008648 std::string MaptypesName =
8649 CGM.getOpenMPRuntime().getName({"offload_maptypes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008650 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
8651 CGM.getModule(), MapTypesArrayInit->getType(),
8652 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008653 MapTypesArrayInit, MaptypesName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008654 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008655 Info.MapTypesArray = MapTypesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008656
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008657 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) {
8658 llvm::Value *BPVal = *BasePointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008659 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008660 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008661 Info.BasePointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008662 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8663 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008664 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8665 CGF.Builder.CreateStore(BPVal, BPAddr);
8666
Samuel Antaocc10b852016-07-28 14:23:26 +00008667 if (Info.requiresDevicePointerInfo())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008668 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl())
Alexey Bataev43a919f2018-04-13 17:48:43 +00008669 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr);
Samuel Antaocc10b852016-07-28 14:23:26 +00008670
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008671 llvm::Value *PVal = Pointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008672 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008673 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008674 Info.PointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008675 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8676 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008677 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8678 CGF.Builder.CreateStore(PVal, PAddr);
8679
8680 if (hasRuntimeEvaluationCaptureSize) {
8681 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008682 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008683 Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008684 /*Idx0=*/0,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008685 /*Idx1=*/I);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008686 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty));
Samuel Antaodf158d52016-04-27 22:58:19 +00008687 CGF.Builder.CreateStore(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008688 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true),
Samuel Antaodf158d52016-04-27 22:58:19 +00008689 SAddr);
8690 }
8691 }
8692 }
8693}
Michael Krused47b9432019-08-05 18:43:21 +00008694
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008695/// Emit the arguments to be passed to the runtime library based on the
Samuel Antaodf158d52016-04-27 22:58:19 +00008696/// arrays of pointers, sizes and map types.
8697static void emitOffloadingArraysArgument(
8698 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg,
8699 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008700 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008701 CodeGenModule &CGM = CGF.CGM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008702 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008703 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008704 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8705 Info.BasePointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008706 /*Idx0=*/0, /*Idx1=*/0);
8707 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008708 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8709 Info.PointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008710 /*Idx0=*/0,
8711 /*Idx1=*/0);
8712 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008713 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008714 /*Idx0=*/0, /*Idx1=*/0);
8715 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
George Rokos63bc9d62017-11-21 18:25:12 +00008716 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008717 Info.MapTypesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008718 /*Idx0=*/0,
8719 /*Idx1=*/0);
8720 } else {
8721 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
8722 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008723 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008724 MapTypesArrayArg =
George Rokos63bc9d62017-11-21 18:25:12 +00008725 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008726 }
Samuel Antao86ace552016-04-27 22:40:57 +00008727}
8728
Alexey Bataev7bb33532019-01-07 21:30:43 +00008729/// Check for inner distribute directive.
8730static const OMPExecutableDirective *
8731getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
8732 const auto *CS = D.getInnermostCapturedStmt();
8733 const auto *Body =
8734 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00008735 const Stmt *ChildStmt =
8736 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
Alexey Bataev7bb33532019-01-07 21:30:43 +00008737
Alexey Bataev5c427362019-04-10 19:11:33 +00008738 if (const auto *NestedDir =
8739 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008740 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind();
8741 switch (D.getDirectiveKind()) {
8742 case OMPD_target:
8743 if (isOpenMPDistributeDirective(DKind))
8744 return NestedDir;
8745 if (DKind == OMPD_teams) {
8746 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
8747 /*IgnoreCaptured=*/true);
8748 if (!Body)
8749 return nullptr;
Alexey Bataev5c427362019-04-10 19:11:33 +00008750 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
8751 if (const auto *NND =
8752 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008753 DKind = NND->getDirectiveKind();
8754 if (isOpenMPDistributeDirective(DKind))
8755 return NND;
8756 }
8757 }
8758 return nullptr;
8759 case OMPD_target_teams:
8760 if (isOpenMPDistributeDirective(DKind))
8761 return NestedDir;
8762 return nullptr;
8763 case OMPD_target_parallel:
8764 case OMPD_target_simd:
8765 case OMPD_target_parallel_for:
8766 case OMPD_target_parallel_for_simd:
8767 return nullptr;
8768 case OMPD_target_teams_distribute:
8769 case OMPD_target_teams_distribute_simd:
8770 case OMPD_target_teams_distribute_parallel_for:
8771 case OMPD_target_teams_distribute_parallel_for_simd:
8772 case OMPD_parallel:
8773 case OMPD_for:
8774 case OMPD_parallel_for:
8775 case OMPD_parallel_sections:
8776 case OMPD_for_simd:
8777 case OMPD_parallel_for_simd:
8778 case OMPD_cancel:
8779 case OMPD_cancellation_point:
8780 case OMPD_ordered:
8781 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00008782 case OMPD_allocate:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008783 case OMPD_task:
8784 case OMPD_simd:
8785 case OMPD_sections:
8786 case OMPD_section:
8787 case OMPD_single:
8788 case OMPD_master:
8789 case OMPD_critical:
8790 case OMPD_taskyield:
8791 case OMPD_barrier:
8792 case OMPD_taskwait:
8793 case OMPD_taskgroup:
8794 case OMPD_atomic:
8795 case OMPD_flush:
8796 case OMPD_teams:
8797 case OMPD_target_data:
8798 case OMPD_target_exit_data:
8799 case OMPD_target_enter_data:
8800 case OMPD_distribute:
8801 case OMPD_distribute_simd:
8802 case OMPD_distribute_parallel_for:
8803 case OMPD_distribute_parallel_for_simd:
8804 case OMPD_teams_distribute:
8805 case OMPD_teams_distribute_simd:
8806 case OMPD_teams_distribute_parallel_for:
8807 case OMPD_teams_distribute_parallel_for_simd:
8808 case OMPD_target_update:
8809 case OMPD_declare_simd:
8810 case OMPD_declare_target:
8811 case OMPD_end_declare_target:
8812 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00008813 case OMPD_declare_mapper:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008814 case OMPD_taskloop:
8815 case OMPD_taskloop_simd:
8816 case OMPD_requires:
8817 case OMPD_unknown:
8818 llvm_unreachable("Unexpected directive.");
8819 }
8820 }
8821
8822 return nullptr;
8823}
8824
Michael Krused47b9432019-08-05 18:43:21 +00008825/// Emit the user-defined mapper function. The code generation follows the
8826/// pattern in the example below.
8827/// \code
8828/// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle,
8829/// void *base, void *begin,
8830/// int64_t size, int64_t type) {
8831/// // Allocate space for an array section first.
8832/// if (size > 1 && !maptype.IsDelete)
8833/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
8834/// size*sizeof(Ty), clearToFrom(type));
8835/// // Map members.
8836/// for (unsigned i = 0; i < size; i++) {
8837/// // For each component specified by this mapper:
8838/// for (auto c : all_components) {
8839/// if (c.hasMapper())
8840/// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size,
8841/// c.arg_type);
8842/// else
8843/// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base,
8844/// c.arg_begin, c.arg_size, c.arg_type);
8845/// }
8846/// }
8847/// // Delete the array section.
8848/// if (size > 1 && maptype.IsDelete)
8849/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
8850/// size*sizeof(Ty), clearToFrom(type));
8851/// }
8852/// \endcode
8853void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D,
8854 CodeGenFunction *CGF) {
8855 if (UDMMap.count(D) > 0)
8856 return;
8857 ASTContext &C = CGM.getContext();
8858 QualType Ty = D->getType();
8859 QualType PtrTy = C.getPointerType(Ty).withRestrict();
8860 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
8861 auto *MapperVarDecl =
8862 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl());
8863 SourceLocation Loc = D->getLocation();
8864 CharUnits ElementSize = C.getTypeSizeInChars(Ty);
8865
8866 // Prepare mapper function arguments and attributes.
8867 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
8868 C.VoidPtrTy, ImplicitParamDecl::Other);
8869 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
8870 ImplicitParamDecl::Other);
8871 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
8872 C.VoidPtrTy, ImplicitParamDecl::Other);
8873 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
8874 ImplicitParamDecl::Other);
8875 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
8876 ImplicitParamDecl::Other);
8877 FunctionArgList Args;
8878 Args.push_back(&HandleArg);
8879 Args.push_back(&BaseArg);
8880 Args.push_back(&BeginArg);
8881 Args.push_back(&SizeArg);
8882 Args.push_back(&TypeArg);
8883 const CGFunctionInfo &FnInfo =
8884 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
8885 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
8886 SmallString<64> TyStr;
8887 llvm::raw_svector_ostream Out(TyStr);
8888 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out);
8889 std::string Name = getName({"omp_mapper", TyStr, D->getName()});
8890 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
8891 Name, &CGM.getModule());
8892 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
8893 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
8894 // Start the mapper function code generation.
8895 CodeGenFunction MapperCGF(CGM);
8896 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
8897 // Compute the starting and end addreses of array elements.
8898 llvm::Value *Size = MapperCGF.EmitLoadOfScalar(
8899 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false,
8900 C.getPointerType(Int64Ty), Loc);
8901 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast(
8902 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(),
8903 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy)));
8904 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size);
8905 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar(
8906 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false,
8907 C.getPointerType(Int64Ty), Loc);
8908 // Prepare common arguments for array initiation and deletion.
8909 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar(
8910 MapperCGF.GetAddrOfLocalVar(&HandleArg),
8911 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8912 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar(
8913 MapperCGF.GetAddrOfLocalVar(&BaseArg),
8914 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8915 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar(
8916 MapperCGF.GetAddrOfLocalVar(&BeginArg),
8917 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8918
8919 // Emit array initiation if this is an array section and \p MapType indicates
8920 // that memory allocation is required.
8921 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head");
8922 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
8923 ElementSize, HeadBB, /*IsInit=*/true);
8924
8925 // Emit a for loop to iterate through SizeArg of elements and map all of them.
8926
8927 // Emit the loop header block.
8928 MapperCGF.EmitBlock(HeadBB);
8929 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body");
8930 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done");
8931 // Evaluate whether the initial condition is satisfied.
8932 llvm::Value *IsEmpty =
8933 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty");
8934 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
8935 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock();
8936
8937 // Emit the loop body block.
8938 MapperCGF.EmitBlock(BodyBB);
8939 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI(
8940 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent");
8941 PtrPHI->addIncoming(PtrBegin, EntryBB);
8942 Address PtrCurrent =
8943 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg)
8944 .getAlignment()
8945 .alignmentOfArrayElement(ElementSize));
8946 // Privatize the declared variable of mapper to be the current array element.
8947 CodeGenFunction::OMPPrivateScope Scope(MapperCGF);
8948 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() {
8949 return MapperCGF
8950 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>())
8951 .getAddress();
8952 });
8953 (void)Scope.Privatize();
8954
8955 // Get map clause information. Fill up the arrays with all mapped variables.
8956 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
8957 MappableExprsHandler::MapValuesArrayTy Pointers;
8958 MappableExprsHandler::MapValuesArrayTy Sizes;
8959 MappableExprsHandler::MapFlagsArrayTy MapTypes;
8960 MappableExprsHandler MEHandler(*D, MapperCGF);
8961 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes);
8962
8963 // Call the runtime API __tgt_mapper_num_components to get the number of
8964 // pre-existing components.
8965 llvm::Value *OffloadingArgs[] = {Handle};
8966 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall(
8967 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs);
8968 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl(
8969 PreviousSize,
8970 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset()));
8971
8972 // Fill up the runtime mapper handle for all components.
8973 for (unsigned I = 0; I < BasePointers.size(); ++I) {
8974 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast(
8975 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
8976 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast(
8977 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
8978 llvm::Value *CurSizeArg = Sizes[I];
8979
8980 // Extract the MEMBER_OF field from the map type.
8981 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member");
8982 MapperCGF.EmitBlock(MemberBB);
8983 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]);
8984 llvm::Value *Member = MapperCGF.Builder.CreateAnd(
8985 OriMapType,
8986 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF));
8987 llvm::BasicBlock *MemberCombineBB =
8988 MapperCGF.createBasicBlock("omp.member.combine");
8989 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type");
8990 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member);
8991 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB);
8992 // Add the number of pre-existing components to the MEMBER_OF field if it
8993 // is valid.
8994 MapperCGF.EmitBlock(MemberCombineBB);
8995 llvm::Value *CombinedMember =
8996 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
8997 // Do nothing if it is not a member of previous components.
8998 MapperCGF.EmitBlock(TypeBB);
8999 llvm::PHINode *MemberMapType =
9000 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype");
9001 MemberMapType->addIncoming(OriMapType, MemberBB);
9002 MemberMapType->addIncoming(CombinedMember, MemberCombineBB);
9003
9004 // Combine the map type inherited from user-defined mapper with that
9005 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM
9006 // bits of the \a MapType, which is the input argument of the mapper
9007 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM
9008 // bits of MemberMapType.
9009 // [OpenMP 5.0], 1.2.6. map-type decay.
9010 // | alloc | to | from | tofrom | release | delete
9011 // ----------------------------------------------------------
9012 // alloc | alloc | alloc | alloc | alloc | release | delete
9013 // to | alloc | to | alloc | to | release | delete
9014 // from | alloc | alloc | from | from | release | delete
9015 // tofrom | alloc | to | from | tofrom | release | delete
9016 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd(
9017 MapType,
9018 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO |
9019 MappableExprsHandler::OMP_MAP_FROM));
9020 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc");
9021 llvm::BasicBlock *AllocElseBB =
9022 MapperCGF.createBasicBlock("omp.type.alloc.else");
9023 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to");
9024 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else");
9025 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from");
9026 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end");
9027 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom);
9028 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
9029 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM.
9030 MapperCGF.EmitBlock(AllocBB);
9031 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd(
9032 MemberMapType,
9033 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9034 MappableExprsHandler::OMP_MAP_FROM)));
9035 MapperCGF.Builder.CreateBr(EndBB);
9036 MapperCGF.EmitBlock(AllocElseBB);
9037 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ(
9038 LeftToFrom,
9039 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO));
9040 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
9041 // In case of to, clear OMP_MAP_FROM.
9042 MapperCGF.EmitBlock(ToBB);
9043 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd(
9044 MemberMapType,
9045 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM));
9046 MapperCGF.Builder.CreateBr(EndBB);
9047 MapperCGF.EmitBlock(ToElseBB);
9048 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ(
9049 LeftToFrom,
9050 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM));
9051 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB);
9052 // In case of from, clear OMP_MAP_TO.
9053 MapperCGF.EmitBlock(FromBB);
9054 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd(
9055 MemberMapType,
9056 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO));
9057 // In case of tofrom, do nothing.
9058 MapperCGF.EmitBlock(EndBB);
9059 llvm::PHINode *CurMapType =
9060 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype");
9061 CurMapType->addIncoming(AllocMapType, AllocBB);
9062 CurMapType->addIncoming(ToMapType, ToBB);
9063 CurMapType->addIncoming(FromMapType, FromBB);
9064 CurMapType->addIncoming(MemberMapType, ToElseBB);
9065
9066 // TODO: call the corresponding mapper function if a user-defined mapper is
9067 // associated with this map clause.
9068 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9069 // data structure.
9070 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg,
9071 CurSizeArg, CurMapType};
9072 MapperCGF.EmitRuntimeCall(
9073 createRuntimeFunction(OMPRTL__tgt_push_mapper_component),
9074 OffloadingArgs);
9075 }
9076
9077 // Update the pointer to point to the next element that needs to be mapped,
9078 // and check whether we have mapped all elements.
9079 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32(
9080 PtrPHI, /*Idx0=*/1, "omp.arraymap.next");
9081 PtrPHI->addIncoming(PtrNext, BodyBB);
9082 llvm::Value *IsDone =
9083 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone");
9084 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit");
9085 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
9086
9087 MapperCGF.EmitBlock(ExitBB);
9088 // Emit array deletion if this is an array section and \p MapType indicates
9089 // that deletion is required.
9090 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
9091 ElementSize, DoneBB, /*IsInit=*/false);
9092
9093 // Emit the function exit block.
9094 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true);
9095 MapperCGF.FinishFunction();
9096 UDMMap.try_emplace(D, Fn);
9097 if (CGF) {
9098 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn);
9099 Decls.second.push_back(D);
9100 }
9101}
9102
9103/// Emit the array initialization or deletion portion for user-defined mapper
9104/// code generation. First, it evaluates whether an array section is mapped and
9105/// whether the \a MapType instructs to delete this section. If \a IsInit is
9106/// true, and \a MapType indicates to not delete this array, array
9107/// initialization code is generated. If \a IsInit is false, and \a MapType
9108/// indicates to not this array, array deletion code is generated.
9109void CGOpenMPRuntime::emitUDMapperArrayInitOrDel(
9110 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base,
9111 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType,
9112 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) {
9113 StringRef Prefix = IsInit ? ".init" : ".del";
9114
9115 // Evaluate if this is an array section.
9116 llvm::BasicBlock *IsDeleteBB =
9117 MapperCGF.createBasicBlock("omp.array" + Prefix + ".evaldelete");
9118 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.array" + Prefix);
9119 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE(
9120 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray");
9121 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB);
9122
9123 // Evaluate if we are going to delete this section.
9124 MapperCGF.EmitBlock(IsDeleteBB);
9125 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd(
9126 MapType,
9127 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE));
9128 llvm::Value *DeleteCond;
9129 if (IsInit) {
9130 DeleteCond = MapperCGF.Builder.CreateIsNull(
9131 DeleteBit, "omp.array" + Prefix + ".delete");
9132 } else {
9133 DeleteCond = MapperCGF.Builder.CreateIsNotNull(
9134 DeleteBit, "omp.array" + Prefix + ".delete");
9135 }
9136 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB);
9137
9138 MapperCGF.EmitBlock(BodyBB);
9139 // Get the array size by multiplying element size and element number (i.e., \p
9140 // Size).
9141 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul(
9142 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
9143 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves
9144 // memory allocation/deletion purpose only.
9145 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd(
9146 MapType,
9147 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9148 MappableExprsHandler::OMP_MAP_FROM)));
9149 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9150 // data structure.
9151 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg};
9152 MapperCGF.EmitRuntimeCall(
9153 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs);
9154}
9155
Alexey Bataev7bb33532019-01-07 21:30:43 +00009156void CGOpenMPRuntime::emitTargetNumIterationsCall(
9157 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *Device,
9158 const llvm::function_ref<llvm::Value *(
9159 CodeGenFunction &CGF, const OMPLoopDirective &D)> &SizeEmitter) {
9160 OpenMPDirectiveKind Kind = D.getDirectiveKind();
9161 const OMPExecutableDirective *TD = &D;
9162 // Get nested teams distribute kind directive, if any.
9163 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind))
9164 TD = getNestedDistributeDirective(CGM.getContext(), D);
9165 if (!TD)
9166 return;
9167 const auto *LD = cast<OMPLoopDirective>(TD);
9168 auto &&CodeGen = [LD, &Device, &SizeEmitter, this](CodeGenFunction &CGF,
9169 PrePostActionTy &) {
9170 llvm::Value *NumIterations = SizeEmitter(CGF, *LD);
9171
9172 // Emit device ID if any.
9173 llvm::Value *DeviceID;
9174 if (Device)
9175 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
9176 CGF.Int64Ty, /*isSigned=*/true);
9177 else
9178 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9179
9180 llvm::Value *Args[] = {DeviceID, NumIterations};
9181 CGF.EmitRuntimeCall(
9182 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args);
9183 };
9184 emitInlinedDirective(CGF, OMPD_unknown, CodeGen);
9185}
9186
Samuel Antaobed3c462015-10-02 16:14:20 +00009187void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
9188 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00009189 llvm::Function *OutlinedFn,
Samuel Antaoee8fb302016-01-06 13:42:12 +00009190 llvm::Value *OutlinedFnID,
Alexey Bataev8451efa2018-01-15 19:06:12 +00009191 const Expr *IfCond, const Expr *Device) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00009192 if (!CGF.HaveInsertPoint())
9193 return;
Samuel Antaobed3c462015-10-02 16:14:20 +00009194
Samuel Antaoee8fb302016-01-06 13:42:12 +00009195 assert(OutlinedFn && "Invalid outlined function!");
9196
Alexey Bataev8451efa2018-01-15 19:06:12 +00009197 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>();
9198 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
Alexey Bataev475a7442018-01-12 19:39:11 +00009199 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009200 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF,
9201 PrePostActionTy &) {
9202 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9203 };
9204 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen);
Samuel Antao86ace552016-04-27 22:40:57 +00009205
Alexey Bataev8451efa2018-01-15 19:06:12 +00009206 CodeGenFunction::OMPTargetDataInfo InputInfo;
9207 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobed3c462015-10-02 16:14:20 +00009208 // Fill up the pointer arrays and transfer execution to the device.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009209 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo,
9210 &MapTypesArray, &CS, RequiresOuterTask,
9211 &CapturedVars](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobed3c462015-10-02 16:14:20 +00009212 // On top of the arrays that were filled up, the target offloading call
9213 // takes as arguments the device id as well as the host pointer. The host
9214 // pointer is used by the runtime library to identify the current target
9215 // region, so it only has to be unique and not necessarily point to
9216 // anything. It could be the pointer to the outlined function that
9217 // implements the target region, but we aren't using that so that the
9218 // compiler doesn't need to keep that, and could therefore inline the host
9219 // function if proven worthwhile during optimization.
9220
Samuel Antaoee8fb302016-01-06 13:42:12 +00009221 // From this point on, we need to have an ID of the target region defined.
9222 assert(OutlinedFnID && "Invalid outlined function ID!");
Samuel Antaobed3c462015-10-02 16:14:20 +00009223
9224 // Emit device ID if any.
9225 llvm::Value *DeviceID;
George Rokos63bc9d62017-11-21 18:25:12 +00009226 if (Device) {
Samuel Antaobed3c462015-10-02 16:14:20 +00009227 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009228 CGF.Int64Ty, /*isSigned=*/true);
9229 } else {
9230 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9231 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009232
Samuel Antaodf158d52016-04-27 22:58:19 +00009233 // Emit the number of elements in the offloading arrays.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009234 llvm::Value *PointerNum =
9235 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaodf158d52016-04-27 22:58:19 +00009236
Samuel Antaob68e2db2016-03-03 16:20:23 +00009237 // Return value of the runtime offloading call.
9238 llvm::Value *Return;
9239
Alexey Bataev5c427362019-04-10 19:11:33 +00009240 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D);
9241 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009242
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009243 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00009244 // The target region is an outlined function launched by the runtime
9245 // via calls __tgt_target() or __tgt_target_teams().
9246 //
9247 // __tgt_target() launches a target region with one team and one thread,
9248 // executing a serial region. This master thread may in turn launch
9249 // more threads within its team upon encountering a parallel region,
9250 // however, no additional teams can be launched on the device.
9251 //
9252 // __tgt_target_teams() launches a target region with one or more teams,
9253 // each with one or more threads. This call is required for target
9254 // constructs such as:
9255 // 'target teams'
9256 // 'target' / 'teams'
9257 // 'target teams distribute parallel for'
9258 // 'target parallel'
9259 // and so on.
9260 //
9261 // Note that on the host and CPU targets, the runtime implementation of
9262 // these calls simply call the outlined function without forking threads.
9263 // The outlined functions themselves have runtime calls to
9264 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by
9265 // the compiler in emitTeamsCall() and emitParallelCall().
9266 //
9267 // In contrast, on the NVPTX target, the implementation of
9268 // __tgt_target_teams() launches a GPU kernel with the requested number
9269 // of teams and threads so no additional calls to the runtime are required.
Samuel Antaob68e2db2016-03-03 16:20:23 +00009270 if (NumTeams) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00009271 // If we have NumTeams defined this means that we have an enclosed teams
9272 // region. Therefore we also expect to have NumThreads defined. These two
9273 // values should be defined in the presence of a teams directive,
9274 // regardless of having any clauses associated. If the user is using teams
9275 // but no clauses, these two values will be the default that should be
9276 // passed to the runtime library - a 32-bit integer with the value zero.
9277 assert(NumThreads && "Thread limit expression should be available along "
9278 "with number of teams.");
Alexey Bataev8451efa2018-01-15 19:06:12 +00009279 llvm::Value *OffloadingArgs[] = {DeviceID,
9280 OutlinedFnID,
9281 PointerNum,
9282 InputInfo.BasePointersArray.getPointer(),
9283 InputInfo.PointersArray.getPointer(),
9284 InputInfo.SizesArray.getPointer(),
9285 MapTypesArray,
9286 NumTeams,
9287 NumThreads};
Samuel Antaob68e2db2016-03-03 16:20:23 +00009288 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00009289 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait
9290 : OMPRTL__tgt_target_teams),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009291 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009292 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009293 llvm::Value *OffloadingArgs[] = {DeviceID,
9294 OutlinedFnID,
9295 PointerNum,
9296 InputInfo.BasePointersArray.getPointer(),
9297 InputInfo.PointersArray.getPointer(),
9298 InputInfo.SizesArray.getPointer(),
9299 MapTypesArray};
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009300 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00009301 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait
9302 : OMPRTL__tgt_target),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009303 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009304 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009305
Alexey Bataev2a007e02017-10-02 14:20:58 +00009306 // Check the error code and execute the host version if required.
9307 llvm::BasicBlock *OffloadFailedBlock =
9308 CGF.createBasicBlock("omp_offload.failed");
9309 llvm::BasicBlock *OffloadContBlock =
9310 CGF.createBasicBlock("omp_offload.cont");
9311 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return);
9312 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
9313
9314 CGF.EmitBlock(OffloadFailedBlock);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009315 if (RequiresOuterTask) {
9316 CapturedVars.clear();
9317 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9318 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009319 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev2a007e02017-10-02 14:20:58 +00009320 CGF.EmitBranch(OffloadContBlock);
9321
9322 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00009323 };
9324
Samuel Antaoee8fb302016-01-06 13:42:12 +00009325 // Notify that the host version must be executed.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009326 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars,
9327 RequiresOuterTask](CodeGenFunction &CGF,
9328 PrePostActionTy &) {
9329 if (RequiresOuterTask) {
9330 CapturedVars.clear();
9331 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9332 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009333 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009334 };
9335
9336 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray,
9337 &CapturedVars, RequiresOuterTask,
9338 &CS](CodeGenFunction &CGF, PrePostActionTy &) {
9339 // Fill up the arrays with all the captured variables.
9340 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
9341 MappableExprsHandler::MapValuesArrayTy Pointers;
9342 MappableExprsHandler::MapValuesArrayTy Sizes;
9343 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9344
Alexey Bataev8451efa2018-01-15 19:06:12 +00009345 // Get mappable expression information.
9346 MappableExprsHandler MEHandler(D, CGF);
Alexey Bataev969dbc02018-11-08 15:47:39 +00009347 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
Alexey Bataev8451efa2018-01-15 19:06:12 +00009348
9349 auto RI = CS.getCapturedRecordDecl()->field_begin();
9350 auto CV = CapturedVars.begin();
9351 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
9352 CE = CS.capture_end();
9353 CI != CE; ++CI, ++RI, ++CV) {
Alexey Bataevb3638132018-07-19 16:34:13 +00009354 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers;
9355 MappableExprsHandler::MapValuesArrayTy CurPointers;
9356 MappableExprsHandler::MapValuesArrayTy CurSizes;
9357 MappableExprsHandler::MapFlagsArrayTy CurMapTypes;
9358 MappableExprsHandler::StructRangeInfoTy PartialStruct;
Alexey Bataev8451efa2018-01-15 19:06:12 +00009359
9360 // VLA sizes are passed to the outlined region by copy and do not have map
9361 // information associated.
9362 if (CI->capturesVariableArrayType()) {
9363 CurBasePointers.push_back(*CV);
9364 CurPointers.push_back(*CV);
Alexey Bataeva90fc662019-06-25 16:00:43 +00009365 CurSizes.push_back(CGF.Builder.CreateIntCast(
9366 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev8451efa2018-01-15 19:06:12 +00009367 // Copy to the device as an argument. No need to retrieve it.
9368 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL |
Alexey Bataevf288cf92019-06-27 18:53:07 +00009369 MappableExprsHandler::OMP_MAP_TARGET_PARAM |
9370 MappableExprsHandler::OMP_MAP_IMPLICIT);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009371 } else {
9372 // If we have any information in the map clause, we use it, otherwise we
9373 // just do a default mapping.
9374 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00009375 CurSizes, CurMapTypes, PartialStruct);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009376 if (CurBasePointers.empty())
9377 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers,
9378 CurPointers, CurSizes, CurMapTypes);
Alexey Bataev60705422018-10-30 15:50:12 +00009379 // Generate correct mapping for variables captured by reference in
9380 // lambdas.
9381 if (CI->capturesVariable())
Alexey Bataev969dbc02018-11-08 15:47:39 +00009382 MEHandler.generateInfoForLambdaCaptures(
9383 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes,
9384 CurMapTypes, LambdaPointers);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009385 }
9386 // We expect to have at least an element of information for this capture.
9387 assert(!CurBasePointers.empty() &&
9388 "Non-existing map pointer for capture!");
9389 assert(CurBasePointers.size() == CurPointers.size() &&
9390 CurBasePointers.size() == CurSizes.size() &&
9391 CurBasePointers.size() == CurMapTypes.size() &&
9392 "Inconsistent map information sizes!");
9393
Alexey Bataevb3638132018-07-19 16:34:13 +00009394 // If there is an entry in PartialStruct it means we have a struct with
9395 // individual members mapped. Emit an extra combined entry.
9396 if (PartialStruct.Base.isValid())
9397 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes,
9398 CurMapTypes, PartialStruct);
9399
Alexey Bataev8451efa2018-01-15 19:06:12 +00009400 // We need to append the results of this capture to what we already have.
9401 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
9402 Pointers.append(CurPointers.begin(), CurPointers.end());
9403 Sizes.append(CurSizes.begin(), CurSizes.end());
9404 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end());
9405 }
Alexey Bataev60705422018-10-30 15:50:12 +00009406 // Adjust MEMBER_OF flags for the lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00009407 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers,
9408 Pointers, MapTypes);
Alexey Bataev92327c52018-03-26 16:40:55 +00009409 // Map other list items in the map clause which are not captured variables
9410 // but "declare target link" global variables.
Alexey Bataevb3638132018-07-19 16:34:13 +00009411 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes,
9412 MapTypes);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009413
9414 TargetDataInfo Info;
9415 // Fill up the arrays and create the arguments.
9416 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
9417 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
9418 Info.PointersArray, Info.SizesArray,
9419 Info.MapTypesArray, Info);
9420 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
9421 InputInfo.BasePointersArray =
9422 Address(Info.BasePointersArray, CGM.getPointerAlign());
9423 InputInfo.PointersArray =
9424 Address(Info.PointersArray, CGM.getPointerAlign());
9425 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign());
9426 MapTypesArray = Info.MapTypesArray;
9427 if (RequiresOuterTask)
9428 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
9429 else
9430 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
9431 };
9432
9433 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask](
9434 CodeGenFunction &CGF, PrePostActionTy &) {
9435 if (RequiresOuterTask) {
9436 CodeGenFunction::OMPTargetDataInfo InputInfo;
9437 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo);
9438 } else {
9439 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen);
9440 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009441 };
9442
9443 // If we have a target function ID it means that we need to support
9444 // offloading, otherwise, just execute on the host. We need to execute on host
9445 // regardless of the conditional in the if clause if, e.g., the user do not
9446 // specify target triples.
9447 if (OutlinedFnID) {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009448 if (IfCond) {
9449 emitOMPIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
9450 } else {
9451 RegionCodeGenTy ThenRCG(TargetThenGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00009452 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00009453 }
9454 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009455 RegionCodeGenTy ElseRCG(TargetElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00009456 ElseRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00009457 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009458}
Samuel Antaoee8fb302016-01-06 13:42:12 +00009459
9460void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
9461 StringRef ParentName) {
9462 if (!S)
9463 return;
9464
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009465 // Codegen OMP target directives that offload compute to the device.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009466 bool RequiresDeviceCodegen =
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009467 isa<OMPExecutableDirective>(S) &&
9468 isOpenMPTargetExecutionDirective(
9469 cast<OMPExecutableDirective>(S)->getDirectiveKind());
Samuel Antaoee8fb302016-01-06 13:42:12 +00009470
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009471 if (RequiresDeviceCodegen) {
9472 const auto &E = *cast<OMPExecutableDirective>(S);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009473 unsigned DeviceID;
9474 unsigned FileID;
9475 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009476 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID,
Samuel Antao2de62b02016-02-13 23:35:10 +00009477 FileID, Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009478
9479 // Is this a target region that should not be emitted as an entry point? If
9480 // so just signal we are done with this target region.
Samuel Antao2de62b02016-02-13 23:35:10 +00009481 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
9482 ParentName, Line))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009483 return;
9484
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009485 switch (E.getDirectiveKind()) {
9486 case OMPD_target:
9487 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName,
9488 cast<OMPTargetDirective>(E));
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009489 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009490 case OMPD_target_parallel:
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009491 CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009492 CGM, ParentName, cast<OMPTargetParallelDirective>(E));
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009493 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009494 case OMPD_target_teams:
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009495 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009496 CGM, ParentName, cast<OMPTargetTeamsDirective>(E));
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009497 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009498 case OMPD_target_teams_distribute:
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009499 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009500 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E));
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009501 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009502 case OMPD_target_teams_distribute_simd:
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009503 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009504 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E));
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009505 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009506 case OMPD_target_parallel_for:
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009507 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009508 CGM, ParentName, cast<OMPTargetParallelForDirective>(E));
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009509 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009510 case OMPD_target_parallel_for_simd:
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009511 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009512 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E));
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009513 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009514 case OMPD_target_simd:
Alexey Bataevf8365372017-11-17 17:57:25 +00009515 CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009516 CGM, ParentName, cast<OMPTargetSimdDirective>(E));
Alexey Bataevf8365372017-11-17 17:57:25 +00009517 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009518 case OMPD_target_teams_distribute_parallel_for:
Carlo Bertolli52978c32018-01-03 21:12:44 +00009519 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
9520 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009521 cast<OMPTargetTeamsDistributeParallelForDirective>(E));
Carlo Bertolli52978c32018-01-03 21:12:44 +00009522 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009523 case OMPD_target_teams_distribute_parallel_for_simd:
Alexey Bataev647dd842018-01-15 20:59:40 +00009524 CodeGenFunction::
9525 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
9526 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009527 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E));
Alexey Bataev647dd842018-01-15 20:59:40 +00009528 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009529 case OMPD_parallel:
9530 case OMPD_for:
9531 case OMPD_parallel_for:
9532 case OMPD_parallel_sections:
9533 case OMPD_for_simd:
9534 case OMPD_parallel_for_simd:
9535 case OMPD_cancel:
9536 case OMPD_cancellation_point:
9537 case OMPD_ordered:
9538 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00009539 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009540 case OMPD_task:
9541 case OMPD_simd:
9542 case OMPD_sections:
9543 case OMPD_section:
9544 case OMPD_single:
9545 case OMPD_master:
9546 case OMPD_critical:
9547 case OMPD_taskyield:
9548 case OMPD_barrier:
9549 case OMPD_taskwait:
9550 case OMPD_taskgroup:
9551 case OMPD_atomic:
9552 case OMPD_flush:
9553 case OMPD_teams:
9554 case OMPD_target_data:
9555 case OMPD_target_exit_data:
9556 case OMPD_target_enter_data:
9557 case OMPD_distribute:
9558 case OMPD_distribute_simd:
9559 case OMPD_distribute_parallel_for:
9560 case OMPD_distribute_parallel_for_simd:
9561 case OMPD_teams_distribute:
9562 case OMPD_teams_distribute_simd:
9563 case OMPD_teams_distribute_parallel_for:
9564 case OMPD_teams_distribute_parallel_for_simd:
9565 case OMPD_target_update:
9566 case OMPD_declare_simd:
9567 case OMPD_declare_target:
9568 case OMPD_end_declare_target:
9569 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00009570 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009571 case OMPD_taskloop:
9572 case OMPD_taskloop_simd:
Kelvin Li1408f912018-09-26 04:28:39 +00009573 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009574 case OMPD_unknown:
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009575 llvm_unreachable("Unknown target directive for OpenMP device codegen.");
9576 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009577 return;
9578 }
9579
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009580 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
Alexey Bataev475a7442018-01-12 19:39:11 +00009581 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009582 return;
9583
9584 scanForTargetRegionsFunctions(
Alexey Bataev475a7442018-01-12 19:39:11 +00009585 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009586 return;
9587 }
9588
9589 // If this is a lambda function, look into its body.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009590 if (const auto *L = dyn_cast<LambdaExpr>(S))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009591 S = L->getBody();
9592
9593 // Keep looking for target regions recursively.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009594 for (const Stmt *II : S->children())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009595 scanForTargetRegionsFunctions(II, ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009596}
9597
9598bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009599 // If emitting code for the host, we do not process FD here. Instead we do
9600 // the normal code generation.
9601 if (!CGM.getLangOpts().OpenMPIsDevice)
9602 return false;
9603
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009604 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009605 StringRef Name = CGM.getMangledName(GD);
9606 // Try to detect target regions in the function.
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009607 if (const auto *FD = dyn_cast<FunctionDecl>(VD))
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009608 scanForTargetRegionsFunctions(FD->getBody(), Name);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009609
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009610 // Do not to emit function if it is not marked as declare target.
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009611 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009612 AlreadyEmittedTargetFunctions.count(Name) == 0;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009613}
9614
9615bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
9616 if (!CGM.getLangOpts().OpenMPIsDevice)
9617 return false;
9618
9619 // Check if there are Ctors/Dtors in this declaration and look for target
9620 // regions in it. We use the complete variant to produce the kernel name
9621 // mangling.
9622 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009623 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
9624 for (const CXXConstructorDecl *Ctor : RD->ctors()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009625 StringRef ParentName =
9626 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
9627 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
9628 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009629 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009630 StringRef ParentName =
9631 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
9632 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
9633 }
9634 }
9635
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009636 // Do not to emit variable if it is not marked as declare target.
Alexey Bataev92327c52018-03-26 16:40:55 +00009637 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009638 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
9639 cast<VarDecl>(GD.getDecl()));
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009640 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
9641 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9642 HasRequiresUnifiedSharedMemory)) {
Alexey Bataevd01b7492018-08-15 19:45:12 +00009643 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009644 return true;
9645 }
9646 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009647}
9648
Alexey Bataev1af5bd52019-03-05 17:47:18 +00009649llvm::Constant *
9650CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF,
9651 const VarDecl *VD) {
9652 assert(VD->getType().isConstant(CGM.getContext()) &&
9653 "Expected constant variable.");
9654 StringRef VarName;
9655 llvm::Constant *Addr;
9656 llvm::GlobalValue::LinkageTypes Linkage;
9657 QualType Ty = VD->getType();
9658 SmallString<128> Buffer;
9659 {
9660 unsigned DeviceID;
9661 unsigned FileID;
9662 unsigned Line;
9663 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID,
9664 FileID, Line);
9665 llvm::raw_svector_ostream OS(Buffer);
9666 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID)
9667 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
9668 VarName = OS.str();
9669 }
9670 Linkage = llvm::GlobalValue::InternalLinkage;
9671 Addr =
9672 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName,
9673 getDefaultFirstprivateAddressSpace());
9674 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage);
9675 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty);
9676 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr));
9677 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9678 VarName, Addr, VarSize,
9679 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage);
9680 return Addr;
9681}
9682
Alexey Bataev03f270c2018-03-30 18:31:07 +00009683void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
9684 llvm::Constant *Addr) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009685 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9686 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
9687 if (!Res) {
9688 if (CGM.getLangOpts().OpenMPIsDevice) {
9689 // Register non-target variables being emitted in device code (debug info
9690 // may cause this).
9691 StringRef VarName = CGM.getMangledName(VD);
9692 EmittedNonTargetVariables.try_emplace(VarName, Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009693 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009694 return;
Alexey Bataev03f270c2018-03-30 18:31:07 +00009695 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009696 // Register declare target variables.
9697 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
9698 StringRef VarName;
9699 CharUnits VarSize;
9700 llvm::GlobalValue::LinkageTypes Linkage;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009701
9702 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9703 !HasRequiresUnifiedSharedMemory) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009704 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9705 VarName = CGM.getMangledName(VD);
9706 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) {
9707 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType());
9708 assert(!VarSize.isZero() && "Expected non-zero size of the variable");
9709 } else {
9710 VarSize = CharUnits::Zero();
9711 }
9712 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
9713 // Temp solution to prevent optimizations of the internal variables.
9714 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) {
9715 std::string RefName = getName({VarName, "ref"});
9716 if (!CGM.GetGlobalValue(RefName)) {
9717 llvm::Constant *AddrRef =
9718 getOrCreateInternalVariable(Addr->getType(), RefName);
9719 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef);
9720 GVAddrRef->setConstant(/*Val=*/true);
9721 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage);
9722 GVAddrRef->setInitializer(Addr);
9723 CGM.addCompilerUsedGlobal(GVAddrRef);
9724 }
9725 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009726 } else {
9727 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
9728 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9729 HasRequiresUnifiedSharedMemory)) &&
9730 "Declare target attribute must link or to with unified memory.");
9731 if (*Res == OMPDeclareTargetDeclAttr::MT_Link)
9732 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink;
9733 else
9734 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9735
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009736 if (CGM.getLangOpts().OpenMPIsDevice) {
9737 VarName = Addr->getName();
9738 Addr = nullptr;
9739 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009740 VarName = getAddrOfDeclareTargetVar(VD).getName();
9741 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009742 }
9743 VarSize = CGM.getPointerSize();
9744 Linkage = llvm::GlobalValue::WeakAnyLinkage;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009745 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009746
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009747 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9748 VarName, Addr, VarSize, Flags, Linkage);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009749}
9750
Samuel Antaoee8fb302016-01-06 13:42:12 +00009751bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009752 if (isa<FunctionDecl>(GD.getDecl()) ||
9753 isa<OMPDeclareReductionDecl>(GD.getDecl()))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009754 return emitTargetFunctions(GD);
9755
9756 return emitTargetGlobalVariable(GD);
9757}
9758
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009759void CGOpenMPRuntime::emitDeferredTargetDecls() const {
9760 for (const VarDecl *VD : DeferredGlobalVariables) {
9761 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009762 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009763 if (!Res)
9764 continue;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009765 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9766 !HasRequiresUnifiedSharedMemory) {
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009767 CGM.EmitGlobal(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009768 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009769 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
9770 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9771 HasRequiresUnifiedSharedMemory)) &&
9772 "Expected link clause or to clause with unified memory.");
9773 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009774 }
9775 }
9776}
9777
Alexey Bataev60705422018-10-30 15:50:12 +00009778void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas(
9779 CodeGenFunction &CGF, const OMPExecutableDirective &D) const {
9780 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) &&
9781 " Expected target-based directive.");
9782}
9783
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009784void CGOpenMPRuntime::checkArchForUnifiedAddressing(
9785 const OMPRequiresDecl *D) {
9786 for (const OMPClause *Clause : D->clauselists()) {
9787 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
9788 HasRequiresUnifiedSharedMemory = true;
9789 break;
9790 }
9791 }
9792}
9793
Alexey Bataevc5687252019-03-21 19:35:27 +00009794bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD,
9795 LangAS &AS) {
9796 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())
9797 return false;
9798 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
9799 switch(A->getAllocatorType()) {
9800 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
9801 // Not supported, fallback to the default mem space.
9802 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
9803 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
9804 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
9805 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
9806 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
9807 case OMPAllocateDeclAttr::OMPConstMemAlloc:
9808 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
9809 AS = LangAS::Default;
9810 return true;
9811 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
9812 llvm_unreachable("Expected predefined allocator for the variables with the "
9813 "static storage.");
9814 }
9815 return false;
9816}
9817
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00009818bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const {
9819 return HasRequiresUnifiedSharedMemory;
9820}
9821
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009822CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
9823 CodeGenModule &CGM)
9824 : CGM(CGM) {
9825 if (CGM.getLangOpts().OpenMPIsDevice) {
9826 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
9827 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
9828 }
9829}
9830
9831CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() {
9832 if (CGM.getLangOpts().OpenMPIsDevice)
9833 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
9834}
9835
Alexey Bataev6d944102018-05-02 15:45:28 +00009836bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009837 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal)
9838 return true;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009839
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009840 StringRef Name = CGM.getMangledName(GD);
Alexey Bataev6d944102018-05-02 15:45:28 +00009841 const auto *D = cast<FunctionDecl>(GD.getDecl());
Alexey Bataev34f8a702018-03-28 14:28:54 +00009842 // Do not to emit function if it is marked as declare target as it was already
9843 // emitted.
Alexey Bataev97b72212018-08-14 18:31:20 +00009844 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009845 if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) {
9846 if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name)))
Alexey Bataev34f8a702018-03-28 14:28:54 +00009847 return !F->isDeclaration();
9848 return false;
9849 }
9850 return true;
9851 }
9852
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009853 return !AlreadyEmittedTargetFunctions.insert(Name).second;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009854}
9855
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009856llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() {
9857 // If we don't have entries or if we are emitting code for the device, we
9858 // don't need to do anything.
9859 if (CGM.getLangOpts().OMPTargetTriples.empty() ||
9860 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice ||
9861 (OffloadEntriesInfoManager.empty() &&
9862 !HasEmittedDeclareTargetRegion &&
9863 !HasEmittedTargetRegion))
9864 return nullptr;
9865
9866 // Create and register the function that handles the requires directives.
9867 ASTContext &C = CGM.getContext();
9868
9869 llvm::Function *RequiresRegFn;
9870 {
9871 CodeGenFunction CGF(CGM);
9872 const auto &FI = CGM.getTypes().arrangeNullaryFunction();
9873 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
9874 std::string ReqName = getName({"omp_offloading", "requires_reg"});
9875 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI);
9876 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {});
9877 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE;
9878 // TODO: check for other requires clauses.
9879 // The requires directive takes effect only when a target region is
9880 // present in the compilation unit. Otherwise it is ignored and not
9881 // passed to the runtime. This avoids the runtime from throwing an error
9882 // for mismatching requires clauses across compilation units that don't
9883 // contain at least 1 target region.
9884 assert((HasEmittedTargetRegion ||
9885 HasEmittedDeclareTargetRegion ||
9886 !OffloadEntriesInfoManager.empty()) &&
9887 "Target or declare target region expected.");
9888 if (HasRequiresUnifiedSharedMemory)
9889 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY;
9890 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires),
9891 llvm::ConstantInt::get(CGM.Int64Ty, Flags));
9892 CGF.FinishFunction();
9893 }
9894 return RequiresRegFn;
9895}
9896
Samuel Antaoee8fb302016-01-06 13:42:12 +00009897llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() {
9898 // If we have offloading in the current module, we need to emit the entries
9899 // now and register the offloading descriptor.
9900 createOffloadEntriesAndInfoMetadata();
9901
9902 // Create and register the offloading binary descriptors. This is the main
9903 // entity that captures all the information about offloading in the current
9904 // compilation unit.
9905 return createOffloadingBinaryDescriptorRegistration();
9906}
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009907
9908void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
9909 const OMPExecutableDirective &D,
9910 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00009911 llvm::Function *OutlinedFn,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009912 ArrayRef<llvm::Value *> CapturedVars) {
9913 if (!CGF.HaveInsertPoint())
9914 return;
9915
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009916 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009917 CodeGenFunction::RunCleanupsScope Scope(CGF);
9918
9919 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
9920 llvm::Value *Args[] = {
9921 RTLoc,
9922 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
9923 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
9924 llvm::SmallVector<llvm::Value *, 16> RealArgs;
9925 RealArgs.append(std::begin(Args), std::end(Args));
9926 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
9927
James Y Knight9871db02019-02-05 16:42:33 +00009928 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009929 CGF.EmitRuntimeCall(RTLFn, RealArgs);
9930}
9931
9932void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
Carlo Bertollic6872252016-04-04 15:55:02 +00009933 const Expr *NumTeams,
9934 const Expr *ThreadLimit,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009935 SourceLocation Loc) {
9936 if (!CGF.HaveInsertPoint())
9937 return;
9938
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009939 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009940
Carlo Bertollic6872252016-04-04 15:55:02 +00009941 llvm::Value *NumTeamsVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009942 NumTeams
Carlo Bertollic6872252016-04-04 15:55:02 +00009943 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
9944 CGF.CGM.Int32Ty, /* isSigned = */ true)
9945 : CGF.Builder.getInt32(0);
9946
9947 llvm::Value *ThreadLimitVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009948 ThreadLimit
Carlo Bertollic6872252016-04-04 15:55:02 +00009949 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
9950 CGF.CGM.Int32Ty, /* isSigned = */ true)
9951 : CGF.Builder.getInt32(0);
9952
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009953 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
Carlo Bertollic6872252016-04-04 15:55:02 +00009954 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
9955 ThreadLimitVal};
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009956 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams),
9957 PushNumTeamsArgs);
9958}
Samuel Antaodf158d52016-04-27 22:58:19 +00009959
Samuel Antaocc10b852016-07-28 14:23:26 +00009960void CGOpenMPRuntime::emitTargetDataCalls(
9961 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
9962 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009963 if (!CGF.HaveInsertPoint())
9964 return;
9965
Samuel Antaocc10b852016-07-28 14:23:26 +00009966 // Action used to replace the default codegen action and turn privatization
9967 // off.
9968 PrePostActionTy NoPrivAction;
Samuel Antaodf158d52016-04-27 22:58:19 +00009969
9970 // Generate the code for the opening of the data environment. Capture all the
9971 // arguments of the runtime call by reference because they are used in the
9972 // closing of the region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009973 auto &&BeginThenGen = [this, &D, Device, &Info,
9974 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009975 // Fill up the arrays with all the mapped variables.
Samuel Antaocc10b852016-07-28 14:23:26 +00009976 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
Samuel Antaodf158d52016-04-27 22:58:19 +00009977 MappableExprsHandler::MapValuesArrayTy Pointers;
9978 MappableExprsHandler::MapValuesArrayTy Sizes;
9979 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9980
9981 // Get map clause information.
9982 MappableExprsHandler MCHandler(D, CGF);
9983 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
Samuel Antaodf158d52016-04-27 22:58:19 +00009984
9985 // Fill up the arrays and create the arguments.
Samuel Antaocc10b852016-07-28 14:23:26 +00009986 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +00009987
9988 llvm::Value *BasePointersArrayArg = nullptr;
9989 llvm::Value *PointersArrayArg = nullptr;
9990 llvm::Value *SizesArrayArg = nullptr;
9991 llvm::Value *MapTypesArrayArg = nullptr;
9992 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00009993 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +00009994
9995 // Emit device ID if any.
9996 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +00009997 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009998 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009999 CGF.Int64Ty, /*isSigned=*/true);
10000 } else {
10001 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10002 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010003
10004 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010005 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +000010006
10007 llvm::Value *OffloadingArgs[] = {
10008 DeviceID, PointerNum, BasePointersArrayArg,
10009 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010010 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin),
Samuel Antaodf158d52016-04-27 22:58:19 +000010011 OffloadingArgs);
Samuel Antaocc10b852016-07-28 14:23:26 +000010012
10013 // If device pointer privatization is required, emit the body of the region
10014 // here. It will have to be duplicated: with and without privatization.
10015 if (!Info.CaptureDeviceAddrMap.empty())
10016 CodeGen(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010017 };
10018
10019 // Generate code for the closing of the data region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010020 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF,
10021 PrePostActionTy &) {
Samuel Antaocc10b852016-07-28 14:23:26 +000010022 assert(Info.isValid() && "Invalid data environment closing arguments.");
Samuel Antaodf158d52016-04-27 22:58:19 +000010023
10024 llvm::Value *BasePointersArrayArg = nullptr;
10025 llvm::Value *PointersArrayArg = nullptr;
10026 llvm::Value *SizesArrayArg = nullptr;
10027 llvm::Value *MapTypesArrayArg = nullptr;
10028 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +000010029 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +000010030
10031 // Emit device ID if any.
10032 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010033 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +000010034 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010035 CGF.Int64Ty, /*isSigned=*/true);
10036 } else {
10037 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10038 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010039
10040 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010041 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +000010042
10043 llvm::Value *OffloadingArgs[] = {
10044 DeviceID, PointerNum, BasePointersArrayArg,
10045 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010046 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end),
Samuel Antaodf158d52016-04-27 22:58:19 +000010047 OffloadingArgs);
10048 };
10049
Samuel Antaocc10b852016-07-28 14:23:26 +000010050 // If we need device pointer privatization, we need to emit the body of the
10051 // region with no privatization in the 'else' branch of the conditional.
10052 // Otherwise, we don't have to do anything.
10053 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF,
10054 PrePostActionTy &) {
10055 if (!Info.CaptureDeviceAddrMap.empty()) {
10056 CodeGen.setAction(NoPrivAction);
10057 CodeGen(CGF);
10058 }
10059 };
10060
10061 // We don't have to do anything to close the region if the if clause evaluates
10062 // to false.
10063 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
Samuel Antaodf158d52016-04-27 22:58:19 +000010064
10065 if (IfCond) {
Samuel Antaocc10b852016-07-28 14:23:26 +000010066 emitOMPIfClause(CGF, IfCond, BeginThenGen, BeginElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +000010067 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +000010068 RegionCodeGenTy RCG(BeginThenGen);
10069 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010070 }
10071
Samuel Antaocc10b852016-07-28 14:23:26 +000010072 // If we don't require privatization of device pointers, we emit the body in
10073 // between the runtime calls. This avoids duplicating the body code.
10074 if (Info.CaptureDeviceAddrMap.empty()) {
10075 CodeGen.setAction(NoPrivAction);
10076 CodeGen(CGF);
10077 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010078
10079 if (IfCond) {
Samuel Antaocc10b852016-07-28 14:23:26 +000010080 emitOMPIfClause(CGF, IfCond, EndThenGen, EndElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +000010081 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +000010082 RegionCodeGenTy RCG(EndThenGen);
10083 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010084 }
10085}
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010086
Samuel Antao8d2d7302016-05-26 18:30:22 +000010087void CGOpenMPRuntime::emitTargetDataStandAloneCall(
Samuel Antao8dd66282016-04-27 23:14:30 +000010088 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10089 const Expr *Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010090 if (!CGF.HaveInsertPoint())
10091 return;
10092
Samuel Antao8dd66282016-04-27 23:14:30 +000010093 assert((isa<OMPTargetEnterDataDirective>(D) ||
Samuel Antao8d2d7302016-05-26 18:30:22 +000010094 isa<OMPTargetExitDataDirective>(D) ||
10095 isa<OMPTargetUpdateDirective>(D)) &&
10096 "Expecting either target enter, exit data, or update directives.");
Samuel Antao8dd66282016-04-27 23:14:30 +000010097
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010098 CodeGenFunction::OMPTargetDataInfo InputInfo;
10099 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010100 // Generate the code for the opening of the data environment.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010101 auto &&ThenGen = [this, &D, Device, &InputInfo,
10102 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010103 // Emit device ID if any.
10104 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010105 if (Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010106 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010107 CGF.Int64Ty, /*isSigned=*/true);
10108 } else {
10109 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10110 }
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010111
10112 // Emit the number of elements in the offloading arrays.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010113 llvm::Constant *PointerNum =
10114 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010115
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010116 llvm::Value *OffloadingArgs[] = {DeviceID,
10117 PointerNum,
10118 InputInfo.BasePointersArray.getPointer(),
10119 InputInfo.PointersArray.getPointer(),
10120 InputInfo.SizesArray.getPointer(),
10121 MapTypesArray};
Samuel Antao8d2d7302016-05-26 18:30:22 +000010122
Samuel Antao8d2d7302016-05-26 18:30:22 +000010123 // Select the right runtime function call for each expected standalone
10124 // directive.
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010125 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Samuel Antao8d2d7302016-05-26 18:30:22 +000010126 OpenMPRTLFunction RTLFn;
10127 switch (D.getDirectiveKind()) {
Samuel Antao8d2d7302016-05-26 18:30:22 +000010128 case OMPD_target_enter_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010129 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait
10130 : OMPRTL__tgt_target_data_begin;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010131 break;
10132 case OMPD_target_exit_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010133 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait
10134 : OMPRTL__tgt_target_data_end;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010135 break;
10136 case OMPD_target_update:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010137 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait
10138 : OMPRTL__tgt_target_data_update;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010139 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010140 case OMPD_parallel:
10141 case OMPD_for:
10142 case OMPD_parallel_for:
10143 case OMPD_parallel_sections:
10144 case OMPD_for_simd:
10145 case OMPD_parallel_for_simd:
10146 case OMPD_cancel:
10147 case OMPD_cancellation_point:
10148 case OMPD_ordered:
10149 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +000010150 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010151 case OMPD_task:
10152 case OMPD_simd:
10153 case OMPD_sections:
10154 case OMPD_section:
10155 case OMPD_single:
10156 case OMPD_master:
10157 case OMPD_critical:
10158 case OMPD_taskyield:
10159 case OMPD_barrier:
10160 case OMPD_taskwait:
10161 case OMPD_taskgroup:
10162 case OMPD_atomic:
10163 case OMPD_flush:
10164 case OMPD_teams:
10165 case OMPD_target_data:
10166 case OMPD_distribute:
10167 case OMPD_distribute_simd:
10168 case OMPD_distribute_parallel_for:
10169 case OMPD_distribute_parallel_for_simd:
10170 case OMPD_teams_distribute:
10171 case OMPD_teams_distribute_simd:
10172 case OMPD_teams_distribute_parallel_for:
10173 case OMPD_teams_distribute_parallel_for_simd:
10174 case OMPD_declare_simd:
10175 case OMPD_declare_target:
10176 case OMPD_end_declare_target:
10177 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +000010178 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010179 case OMPD_taskloop:
10180 case OMPD_taskloop_simd:
10181 case OMPD_target:
10182 case OMPD_target_simd:
10183 case OMPD_target_teams_distribute:
10184 case OMPD_target_teams_distribute_simd:
10185 case OMPD_target_teams_distribute_parallel_for:
10186 case OMPD_target_teams_distribute_parallel_for_simd:
10187 case OMPD_target_teams:
10188 case OMPD_target_parallel:
10189 case OMPD_target_parallel_for:
10190 case OMPD_target_parallel_for_simd:
Kelvin Li1408f912018-09-26 04:28:39 +000010191 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010192 case OMPD_unknown:
10193 llvm_unreachable("Unexpected standalone target data directive.");
10194 break;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010195 }
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010196 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010197 };
10198
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010199 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray](
10200 CodeGenFunction &CGF, PrePostActionTy &) {
10201 // Fill up the arrays with all the mapped variables.
10202 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
10203 MappableExprsHandler::MapValuesArrayTy Pointers;
10204 MappableExprsHandler::MapValuesArrayTy Sizes;
10205 MappableExprsHandler::MapFlagsArrayTy MapTypes;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010206
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010207 // Get map clause information.
10208 MappableExprsHandler MEHandler(D, CGF);
10209 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
10210
10211 TargetDataInfo Info;
10212 // Fill up the arrays and create the arguments.
10213 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
10214 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
10215 Info.PointersArray, Info.SizesArray,
10216 Info.MapTypesArray, Info);
10217 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
10218 InputInfo.BasePointersArray =
10219 Address(Info.BasePointersArray, CGM.getPointerAlign());
10220 InputInfo.PointersArray =
10221 Address(Info.PointersArray, CGM.getPointerAlign());
10222 InputInfo.SizesArray =
10223 Address(Info.SizesArray, CGM.getPointerAlign());
10224 MapTypesArray = Info.MapTypesArray;
10225 if (D.hasClausesOfKind<OMPDependClause>())
10226 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
10227 else
Alexey Bataev768f1f22018-01-09 19:59:25 +000010228 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010229 };
10230
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010231 if (IfCond) {
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010232 emitOMPIfClause(CGF, IfCond, TargetThenGen,
10233 [](CodeGenFunction &CGF, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010234 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010235 RegionCodeGenTy ThenRCG(TargetThenGen);
10236 ThenRCG(CGF);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010237 }
10238}
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010239
10240namespace {
10241 /// Kind of parameter in a function with 'declare simd' directive.
10242 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector };
10243 /// Attribute set of the parameter.
10244 struct ParamAttrTy {
10245 ParamKindTy Kind = Vector;
10246 llvm::APSInt StrideOrArg;
10247 llvm::APSInt Alignment;
10248 };
10249} // namespace
10250
10251static unsigned evaluateCDTSize(const FunctionDecl *FD,
10252 ArrayRef<ParamAttrTy> ParamAttrs) {
10253 // Every vector variant of a SIMD-enabled function has a vector length (VLEN).
10254 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument
10255 // of that clause. The VLEN value must be power of 2.
10256 // In other case the notion of the function`s "characteristic data type" (CDT)
10257 // is used to compute the vector length.
10258 // CDT is defined in the following order:
10259 // a) For non-void function, the CDT is the return type.
10260 // b) If the function has any non-uniform, non-linear parameters, then the
10261 // CDT is the type of the first such parameter.
10262 // c) If the CDT determined by a) or b) above is struct, union, or class
10263 // type which is pass-by-value (except for the type that maps to the
10264 // built-in complex data type), the characteristic data type is int.
10265 // d) If none of the above three cases is applicable, the CDT is int.
10266 // The VLEN is then determined based on the CDT and the size of vector
10267 // register of that ISA for which current vector version is generated. The
10268 // VLEN is computed using the formula below:
10269 // VLEN = sizeof(vector_register) / sizeof(CDT),
10270 // where vector register size specified in section 3.2.1 Registers and the
10271 // Stack Frame of original AMD64 ABI document.
10272 QualType RetType = FD->getReturnType();
10273 if (RetType.isNull())
10274 return 0;
10275 ASTContext &C = FD->getASTContext();
10276 QualType CDT;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010277 if (!RetType.isNull() && !RetType->isVoidType()) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010278 CDT = RetType;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010279 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010280 unsigned Offset = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010281 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010282 if (ParamAttrs[Offset].Kind == Vector)
10283 CDT = C.getPointerType(C.getRecordType(MD->getParent()));
10284 ++Offset;
10285 }
10286 if (CDT.isNull()) {
10287 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10288 if (ParamAttrs[I + Offset].Kind == Vector) {
10289 CDT = FD->getParamDecl(I)->getType();
10290 break;
10291 }
10292 }
10293 }
10294 }
10295 if (CDT.isNull())
10296 CDT = C.IntTy;
10297 CDT = CDT->getCanonicalTypeUnqualified();
10298 if (CDT->isRecordType() || CDT->isUnionType())
10299 CDT = C.IntTy;
10300 return C.getTypeSize(CDT);
10301}
10302
10303static void
10304emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
Benjamin Kramer81cb4b72016-11-24 16:01:20 +000010305 const llvm::APSInt &VLENVal,
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010306 ArrayRef<ParamAttrTy> ParamAttrs,
10307 OMPDeclareSimdDeclAttr::BranchStateTy State) {
10308 struct ISADataTy {
10309 char ISA;
10310 unsigned VecRegSize;
10311 };
10312 ISADataTy ISAData[] = {
10313 {
10314 'b', 128
10315 }, // SSE
10316 {
10317 'c', 256
10318 }, // AVX
10319 {
10320 'd', 256
10321 }, // AVX2
10322 {
10323 'e', 512
10324 }, // AVX512
10325 };
10326 llvm::SmallVector<char, 2> Masked;
10327 switch (State) {
10328 case OMPDeclareSimdDeclAttr::BS_Undefined:
10329 Masked.push_back('N');
10330 Masked.push_back('M');
10331 break;
10332 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10333 Masked.push_back('N');
10334 break;
10335 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10336 Masked.push_back('M');
10337 break;
10338 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010339 for (char Mask : Masked) {
10340 for (const ISADataTy &Data : ISAData) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010341 SmallString<256> Buffer;
10342 llvm::raw_svector_ostream Out(Buffer);
10343 Out << "_ZGV" << Data.ISA << Mask;
10344 if (!VLENVal) {
Simon Pilgrim823a99c2019-05-22 13:02:19 +000010345 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs);
10346 assert(NumElts && "Non-zero simdlen/cdtsize expected");
10347 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010348 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010349 Out << VLENVal;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010350 }
10351 for (const ParamAttrTy &ParamAttr : ParamAttrs) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010352 switch (ParamAttr.Kind){
10353 case LinearWithVarStride:
10354 Out << 's' << ParamAttr.StrideOrArg;
10355 break;
10356 case Linear:
10357 Out << 'l';
10358 if (!!ParamAttr.StrideOrArg)
10359 Out << ParamAttr.StrideOrArg;
10360 break;
10361 case Uniform:
10362 Out << 'u';
10363 break;
10364 case Vector:
10365 Out << 'v';
10366 break;
10367 }
10368 if (!!ParamAttr.Alignment)
10369 Out << 'a' << ParamAttr.Alignment;
10370 }
10371 Out << '_' << Fn->getName();
10372 Fn->addFnAttr(Out.str());
10373 }
10374 }
10375}
10376
Alexey Bataeva0a22642019-04-16 13:56:21 +000010377// This are the Functions that are needed to mangle the name of the
10378// vector functions generated by the compiler, according to the rules
10379// defined in the "Vector Function ABI specifications for AArch64",
10380// available at
10381// https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi.
10382
10383/// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI.
10384///
10385/// TODO: Need to implement the behavior for reference marked with a
10386/// var or no linear modifiers (1.b in the section). For this, we
10387/// need to extend ParamKindTy to support the linear modifiers.
10388static bool getAArch64MTV(QualType QT, ParamKindTy Kind) {
10389 QT = QT.getCanonicalType();
10390
10391 if (QT->isVoidType())
10392 return false;
10393
10394 if (Kind == ParamKindTy::Uniform)
10395 return false;
10396
10397 if (Kind == ParamKindTy::Linear)
10398 return false;
10399
10400 // TODO: Handle linear references with modifiers
10401
10402 if (Kind == ParamKindTy::LinearWithVarStride)
10403 return false;
10404
10405 return true;
10406}
10407
10408/// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
10409static bool getAArch64PBV(QualType QT, ASTContext &C) {
10410 QT = QT.getCanonicalType();
10411 unsigned Size = C.getTypeSize(QT);
10412
10413 // Only scalars and complex within 16 bytes wide set PVB to true.
10414 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
10415 return false;
10416
10417 if (QT->isFloatingType())
10418 return true;
10419
10420 if (QT->isIntegerType())
10421 return true;
10422
10423 if (QT->isPointerType())
10424 return true;
10425
10426 // TODO: Add support for complex types (section 3.1.2, item 2).
10427
10428 return false;
10429}
10430
10431/// Computes the lane size (LS) of a return type or of an input parameter,
10432/// as defined by `LS(P)` in 3.2.1 of the AAVFABI.
10433/// TODO: Add support for references, section 3.2.1, item 1.
10434static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) {
10435 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) {
10436 QualType PTy = QT.getCanonicalType()->getPointeeType();
10437 if (getAArch64PBV(PTy, C))
10438 return C.getTypeSize(PTy);
10439 }
10440 if (getAArch64PBV(QT, C))
10441 return C.getTypeSize(QT);
10442
10443 return C.getTypeSize(C.getUIntPtrType());
10444}
10445
10446// Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the
10447// signature of the scalar function, as defined in 3.2.2 of the
10448// AAVFABI.
10449static std::tuple<unsigned, unsigned, bool>
10450getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) {
10451 QualType RetType = FD->getReturnType().getCanonicalType();
10452
10453 ASTContext &C = FD->getASTContext();
10454
10455 bool OutputBecomesInput = false;
10456
10457 llvm::SmallVector<unsigned, 8> Sizes;
10458 if (!RetType->isVoidType()) {
10459 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C));
10460 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {}))
10461 OutputBecomesInput = true;
10462 }
10463 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10464 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType();
10465 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C));
10466 }
10467
10468 assert(!Sizes.empty() && "Unable to determine NDS and WDS.");
10469 // The LS of a function parameter / return value can only be a power
10470 // of 2, starting from 8 bits, up to 128.
10471 assert(std::all_of(Sizes.begin(), Sizes.end(),
10472 [](unsigned Size) {
10473 return Size == 8 || Size == 16 || Size == 32 ||
10474 Size == 64 || Size == 128;
10475 }) &&
10476 "Invalid size");
10477
10478 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)),
10479 *std::max_element(std::begin(Sizes), std::end(Sizes)),
10480 OutputBecomesInput);
10481}
10482
10483/// Mangle the parameter part of the vector function name according to
10484/// their OpenMP classification. The mangling function is defined in
10485/// section 3.5 of the AAVFABI.
10486static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) {
10487 SmallString<256> Buffer;
10488 llvm::raw_svector_ostream Out(Buffer);
10489 for (const auto &ParamAttr : ParamAttrs) {
10490 switch (ParamAttr.Kind) {
10491 case LinearWithVarStride:
10492 Out << "ls" << ParamAttr.StrideOrArg;
10493 break;
10494 case Linear:
10495 Out << 'l';
10496 // Don't print the step value if it is not present or if it is
10497 // equal to 1.
10498 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1)
10499 Out << ParamAttr.StrideOrArg;
10500 break;
10501 case Uniform:
10502 Out << 'u';
10503 break;
10504 case Vector:
10505 Out << 'v';
10506 break;
10507 }
10508
10509 if (!!ParamAttr.Alignment)
10510 Out << 'a' << ParamAttr.Alignment;
10511 }
10512
10513 return Out.str();
10514}
10515
10516// Function used to add the attribute. The parameter `VLEN` is
10517// templated to allow the use of "x" when targeting scalable functions
10518// for SVE.
10519template <typename T>
10520static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix,
10521 char ISA, StringRef ParSeq,
10522 StringRef MangledName, bool OutputBecomesInput,
10523 llvm::Function *Fn) {
10524 SmallString<256> Buffer;
10525 llvm::raw_svector_ostream Out(Buffer);
10526 Out << Prefix << ISA << LMask << VLEN;
10527 if (OutputBecomesInput)
10528 Out << "v";
10529 Out << ParSeq << "_" << MangledName;
10530 Fn->addFnAttr(Out.str());
10531}
10532
10533// Helper function to generate the Advanced SIMD names depending on
10534// the value of the NDS when simdlen is not present.
10535static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask,
10536 StringRef Prefix, char ISA,
10537 StringRef ParSeq, StringRef MangledName,
10538 bool OutputBecomesInput,
10539 llvm::Function *Fn) {
10540 switch (NDS) {
10541 case 8:
10542 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10543 OutputBecomesInput, Fn);
10544 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName,
10545 OutputBecomesInput, Fn);
10546 break;
10547 case 16:
10548 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10549 OutputBecomesInput, Fn);
10550 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10551 OutputBecomesInput, Fn);
10552 break;
10553 case 32:
10554 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10555 OutputBecomesInput, Fn);
10556 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10557 OutputBecomesInput, Fn);
10558 break;
10559 case 64:
10560 case 128:
10561 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10562 OutputBecomesInput, Fn);
10563 break;
10564 default:
10565 llvm_unreachable("Scalar type is too wide.");
10566 }
10567}
10568
10569/// Emit vector function attributes for AArch64, as defined in the AAVFABI.
10570static void emitAArch64DeclareSimdFunction(
10571 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN,
10572 ArrayRef<ParamAttrTy> ParamAttrs,
10573 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
10574 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) {
10575
10576 // Get basic data for building the vector signature.
10577 const auto Data = getNDSWDS(FD, ParamAttrs);
10578 const unsigned NDS = std::get<0>(Data);
10579 const unsigned WDS = std::get<1>(Data);
10580 const bool OutputBecomesInput = std::get<2>(Data);
10581
10582 // Check the values provided via `simdlen` by the user.
10583 // 1. A `simdlen(1)` doesn't produce vector signatures,
10584 if (UserVLEN == 1) {
10585 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10586 DiagnosticsEngine::Warning,
10587 "The clause simdlen(1) has no effect when targeting aarch64.");
10588 CGM.getDiags().Report(SLoc, DiagID);
10589 return;
10590 }
10591
10592 // 2. Section 3.3.1, item 1: user input must be a power of 2 for
10593 // Advanced SIMD output.
10594 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
10595 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10596 DiagnosticsEngine::Warning, "The value specified in simdlen must be a "
10597 "power of 2 when targeting Advanced SIMD.");
10598 CGM.getDiags().Report(SLoc, DiagID);
10599 return;
10600 }
10601
10602 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural
10603 // limits.
10604 if (ISA == 's' && UserVLEN != 0) {
10605 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
10606 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10607 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit "
10608 "lanes in the architectural constraints "
10609 "for SVE (min is 128-bit, max is "
10610 "2048-bit, by steps of 128-bit)");
10611 CGM.getDiags().Report(SLoc, DiagID) << WDS;
10612 return;
10613 }
10614 }
10615
10616 // Sort out parameter sequence.
10617 const std::string ParSeq = mangleVectorParameters(ParamAttrs);
10618 StringRef Prefix = "_ZGV";
10619 // Generate simdlen from user input (if any).
10620 if (UserVLEN) {
10621 if (ISA == 's') {
10622 // SVE generates only a masked function.
10623 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10624 OutputBecomesInput, Fn);
10625 } else {
10626 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10627 // Advanced SIMD generates one or two functions, depending on
10628 // the `[not]inbranch` clause.
10629 switch (State) {
10630 case OMPDeclareSimdDeclAttr::BS_Undefined:
10631 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10632 OutputBecomesInput, Fn);
10633 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10634 OutputBecomesInput, Fn);
10635 break;
10636 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10637 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10638 OutputBecomesInput, Fn);
10639 break;
10640 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10641 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10642 OutputBecomesInput, Fn);
10643 break;
10644 }
10645 }
10646 } else {
10647 // If no user simdlen is provided, follow the AAVFABI rules for
10648 // generating the vector length.
10649 if (ISA == 's') {
10650 // SVE, section 3.4.1, item 1.
10651 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName,
10652 OutputBecomesInput, Fn);
10653 } else {
10654 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10655 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or
10656 // two vector names depending on the use of the clause
10657 // `[not]inbranch`.
10658 switch (State) {
10659 case OMPDeclareSimdDeclAttr::BS_Undefined:
10660 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10661 OutputBecomesInput, Fn);
10662 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10663 OutputBecomesInput, Fn);
10664 break;
10665 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10666 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10667 OutputBecomesInput, Fn);
10668 break;
10669 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10670 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10671 OutputBecomesInput, Fn);
10672 break;
10673 }
10674 }
10675 }
10676}
10677
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010678void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
10679 llvm::Function *Fn) {
10680 ASTContext &C = CGM.getContext();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010681 FD = FD->getMostRecentDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010682 // Map params to their positions in function decl.
10683 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
10684 if (isa<CXXMethodDecl>(FD))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010685 ParamPositions.try_emplace(FD, 0);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010686 unsigned ParamPos = ParamPositions.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010687 for (const ParmVarDecl *P : FD->parameters()) {
10688 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010689 ++ParamPos;
10690 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010691 while (FD) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010692 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010693 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
10694 // Mark uniform parameters.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010695 for (const Expr *E : Attr->uniforms()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010696 E = E->IgnoreParenImpCasts();
10697 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010698 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010699 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010700 } else {
10701 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10702 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010703 Pos = ParamPositions[PVD];
10704 }
10705 ParamAttrs[Pos].Kind = Uniform;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010706 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010707 // Get alignment info.
10708 auto NI = Attr->alignments_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010709 for (const Expr *E : Attr->aligneds()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010710 E = E->IgnoreParenImpCasts();
10711 unsigned Pos;
10712 QualType ParmTy;
10713 if (isa<CXXThisExpr>(E)) {
10714 Pos = ParamPositions[FD];
10715 ParmTy = E->getType();
10716 } else {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010717 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10718 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010719 Pos = ParamPositions[PVD];
10720 ParmTy = PVD->getType();
10721 }
10722 ParamAttrs[Pos].Alignment =
10723 (*NI)
10724 ? (*NI)->EvaluateKnownConstInt(C)
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010725 : llvm::APSInt::getUnsigned(
10726 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy))
10727 .getQuantity());
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010728 ++NI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010729 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010730 // Mark linear parameters.
10731 auto SI = Attr->steps_begin();
10732 auto MI = Attr->modifiers_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010733 for (const Expr *E : Attr->linears()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010734 E = E->IgnoreParenImpCasts();
10735 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010736 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010737 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010738 } else {
10739 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10740 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010741 Pos = ParamPositions[PVD];
10742 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010743 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010744 ParamAttr.Kind = Linear;
10745 if (*SI) {
Fangrui Song407659a2018-11-30 23:41:18 +000010746 Expr::EvalResult Result;
10747 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010748 if (const auto *DRE =
10749 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
10750 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010751 ParamAttr.Kind = LinearWithVarStride;
10752 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(
10753 ParamPositions[StridePVD->getCanonicalDecl()]);
10754 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010755 }
Fangrui Song407659a2018-11-30 23:41:18 +000010756 } else {
10757 ParamAttr.StrideOrArg = Result.Val.getInt();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010758 }
10759 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010760 ++SI;
10761 ++MI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010762 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010763 llvm::APSInt VLENVal;
Alexey Bataeva0a22642019-04-16 13:56:21 +000010764 SourceLocation ExprLoc;
10765 const Expr *VLENExpr = Attr->getSimdlen();
10766 if (VLENExpr) {
10767 VLENVal = VLENExpr->EvaluateKnownConstInt(C);
10768 ExprLoc = VLENExpr->getExprLoc();
10769 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010770 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
10771 if (CGM.getTriple().getArch() == llvm::Triple::x86 ||
Alexey Bataeva0a22642019-04-16 13:56:21 +000010772 CGM.getTriple().getArch() == llvm::Triple::x86_64) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010773 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
Alexey Bataeva0a22642019-04-16 13:56:21 +000010774 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) {
10775 unsigned VLEN = VLENVal.getExtValue();
10776 StringRef MangledName = Fn->getName();
10777 if (CGM.getTarget().hasFeature("sve"))
10778 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10779 MangledName, 's', 128, Fn, ExprLoc);
10780 if (CGM.getTarget().hasFeature("neon"))
10781 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10782 MangledName, 'n', 128, Fn, ExprLoc);
10783 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010784 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010785 FD = FD->getPreviousDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010786 }
10787}
Alexey Bataev8b427062016-05-25 12:36:08 +000010788
10789namespace {
10790/// Cleanup action for doacross support.
10791class DoacrossCleanupTy final : public EHScopeStack::Cleanup {
10792public:
10793 static const int DoacrossFinArgs = 2;
10794
10795private:
James Y Knight9871db02019-02-05 16:42:33 +000010796 llvm::FunctionCallee RTLFn;
Alexey Bataev8b427062016-05-25 12:36:08 +000010797 llvm::Value *Args[DoacrossFinArgs];
10798
10799public:
James Y Knight9871db02019-02-05 16:42:33 +000010800 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
10801 ArrayRef<llvm::Value *> CallArgs)
Alexey Bataev8b427062016-05-25 12:36:08 +000010802 : RTLFn(RTLFn) {
10803 assert(CallArgs.size() == DoacrossFinArgs);
10804 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10805 }
10806 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10807 if (!CGF.HaveInsertPoint())
10808 return;
10809 CGF.EmitRuntimeCall(RTLFn, Args);
10810 }
10811};
10812} // namespace
10813
10814void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000010815 const OMPLoopDirective &D,
10816 ArrayRef<Expr *> NumIterations) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010817 if (!CGF.HaveInsertPoint())
10818 return;
10819
10820 ASTContext &C = CGM.getContext();
10821 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
10822 RecordDecl *RD;
10823 if (KmpDimTy.isNull()) {
10824 // Build struct kmp_dim { // loop bounds info casted to kmp_int64
10825 // kmp_int64 lo; // lower
10826 // kmp_int64 up; // upper
10827 // kmp_int64 st; // stride
10828 // };
10829 RD = C.buildImplicitRecord("kmp_dim");
10830 RD->startDefinition();
10831 addFieldToRecordDecl(C, RD, Int64Ty);
10832 addFieldToRecordDecl(C, RD, Int64Ty);
10833 addFieldToRecordDecl(C, RD, Int64Ty);
10834 RD->completeDefinition();
10835 KmpDimTy = C.getRecordType(RD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010836 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010837 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010838 }
Alexey Bataevf138fda2018-08-13 19:04:24 +000010839 llvm::APInt Size(/*numBits=*/32, NumIterations.size());
10840 QualType ArrayTy =
10841 C.getConstantArrayType(KmpDimTy, Size, ArrayType::Normal, 0);
Alexey Bataev8b427062016-05-25 12:36:08 +000010842
Alexey Bataevf138fda2018-08-13 19:04:24 +000010843 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
10844 CGF.EmitNullInitialization(DimsAddr, ArrayTy);
Alexey Bataev8b427062016-05-25 12:36:08 +000010845 enum { LowerFD = 0, UpperFD, StrideFD };
10846 // Fill dims with data.
Alexey Bataevf138fda2018-08-13 19:04:24 +000010847 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +000010848 LValue DimsLVal = CGF.MakeAddrLValue(
10849 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010850 // dims.upper = num_iterations;
10851 LValue UpperLVal = CGF.EmitLValueForField(
10852 DimsLVal, *std::next(RD->field_begin(), UpperFD));
10853 llvm::Value *NumIterVal =
10854 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]),
10855 D.getNumIterations()->getType(), Int64Ty,
10856 D.getNumIterations()->getExprLoc());
10857 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
10858 // dims.stride = 1;
10859 LValue StrideLVal = CGF.EmitLValueForField(
10860 DimsLVal, *std::next(RD->field_begin(), StrideFD));
10861 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
10862 StrideLVal);
10863 }
Alexey Bataev8b427062016-05-25 12:36:08 +000010864
10865 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
10866 // kmp_int32 num_dims, struct kmp_dim * dims);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010867 llvm::Value *Args[] = {
10868 emitUpdateLocation(CGF, D.getBeginLoc()),
10869 getThreadID(CGF, D.getBeginLoc()),
10870 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()),
10871 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knight751fe282019-02-09 22:22:28 +000010872 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(),
Alexey Bataevf138fda2018-08-13 19:04:24 +000010873 CGM.VoidPtrTy)};
Alexey Bataev8b427062016-05-25 12:36:08 +000010874
James Y Knight9871db02019-02-05 16:42:33 +000010875 llvm::FunctionCallee RTLFn =
10876 createRuntimeFunction(OMPRTL__kmpc_doacross_init);
Alexey Bataev8b427062016-05-25 12:36:08 +000010877 CGF.EmitRuntimeCall(RTLFn, Args);
10878 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
Stephen Kelly1c301dc2018-08-09 21:09:38 +000010879 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())};
James Y Knight9871db02019-02-05 16:42:33 +000010880 llvm::FunctionCallee FiniRTLFn =
10881 createRuntimeFunction(OMPRTL__kmpc_doacross_fini);
Alexey Bataev8b427062016-05-25 12:36:08 +000010882 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
10883 llvm::makeArrayRef(FiniArgs));
10884}
10885
10886void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
10887 const OMPDependClause *C) {
10888 QualType Int64Ty =
10889 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010890 llvm::APInt Size(/*numBits=*/32, C->getNumLoops());
10891 QualType ArrayTy = CGM.getContext().getConstantArrayType(
10892 Int64Ty, Size, ArrayType::Normal, 0);
10893 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr");
10894 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) {
10895 const Expr *CounterVal = C->getLoopData(I);
10896 assert(CounterVal);
10897 llvm::Value *CntVal = CGF.EmitScalarConversion(
10898 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
10899 CounterVal->getExprLoc());
James Y Knight751fe282019-02-09 22:22:28 +000010900 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I),
10901 /*Volatile=*/false, Int64Ty);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010902 }
10903 llvm::Value *Args[] = {
10904 emitUpdateLocation(CGF, C->getBeginLoc()),
10905 getThreadID(CGF, C->getBeginLoc()),
James Y Knight751fe282019-02-09 22:22:28 +000010906 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()};
James Y Knight9871db02019-02-05 16:42:33 +000010907 llvm::FunctionCallee RTLFn;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010908 if (C->getDependencyKind() == OMPC_DEPEND_source) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010909 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010910 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010911 assert(C->getDependencyKind() == OMPC_DEPEND_sink);
10912 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait);
10913 }
10914 CGF.EmitRuntimeCall(RTLFn, Args);
10915}
10916
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010917void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000010918 llvm::FunctionCallee Callee,
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010919 ArrayRef<llvm::Value *> Args) const {
10920 assert(Loc.isValid() && "Outlined function call location must be valid.");
Alexey Bataev3c595a62017-08-14 15:01:03 +000010921 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
10922
James Y Knight9871db02019-02-05 16:42:33 +000010923 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010924 if (Fn->doesNotThrow()) {
Alexey Bataev3c595a62017-08-14 15:01:03 +000010925 CGF.EmitNounwindRuntimeCall(Fn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010926 return;
10927 }
10928 }
Alexey Bataev3c595a62017-08-14 15:01:03 +000010929 CGF.EmitRuntimeCall(Callee, Args);
10930}
10931
10932void CGOpenMPRuntime::emitOutlinedFunctionCall(
James Y Knight9871db02019-02-05 16:42:33 +000010933 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn,
Alexey Bataev3c595a62017-08-14 15:01:03 +000010934 ArrayRef<llvm::Value *> Args) const {
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010935 emitCall(CGF, Loc, OutlinedFn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010936}
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010937
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +000010938void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) {
10939 if (const auto *FD = dyn_cast<FunctionDecl>(D))
10940 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
10941 HasEmittedDeclareTargetRegion = true;
10942}
10943
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010944Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
10945 const VarDecl *NativeParam,
10946 const VarDecl *TargetParam) const {
10947 return CGF.GetAddrOfLocalVar(NativeParam);
10948}
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010949
Alexey Bataev4f680db2019-03-19 16:41:16 +000010950namespace {
10951/// Cleanup action for allocate support.
10952class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup {
10953public:
10954 static const int CleanupArgs = 3;
10955
10956private:
10957 llvm::FunctionCallee RTLFn;
10958 llvm::Value *Args[CleanupArgs];
10959
10960public:
10961 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
10962 ArrayRef<llvm::Value *> CallArgs)
10963 : RTLFn(RTLFn) {
10964 assert(CallArgs.size() == CleanupArgs &&
10965 "Size of arguments does not match.");
10966 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10967 }
10968 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10969 if (!CGF.HaveInsertPoint())
10970 return;
10971 CGF.EmitRuntimeCall(RTLFn, Args);
10972 }
10973};
10974} // namespace
10975
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000010976Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF,
10977 const VarDecl *VD) {
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010978 if (!VD)
10979 return Address::invalid();
Alexey Bataev4f680db2019-03-19 16:41:16 +000010980 const VarDecl *CVD = VD->getCanonicalDecl();
10981 if (!CVD->hasAttr<OMPAllocateDeclAttr>())
10982 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010983 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
10984 // Use the default allocation.
Alexey Bataev0fd3c682019-04-02 19:44:46 +000010985 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
10986 !AA->getAllocator())
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010987 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010988 llvm::Value *Size;
10989 CharUnits Align = CGM.getContext().getDeclAlign(CVD);
10990 if (CVD->getType()->isVariablyModifiedType()) {
10991 Size = CGF.getTypeSize(CVD->getType());
Alexey Bataev9c397812019-04-03 17:57:06 +000010992 // Align the size: ((size + align - 1) / align) * align
10993 Size = CGF.Builder.CreateNUWAdd(
10994 Size, CGM.getSize(Align - CharUnits::fromQuantity(1)));
10995 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align));
10996 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align));
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010997 } else {
10998 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType());
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010999 Size = CGM.getSize(Sz.alignTo(Align));
Alexey Bataev4f680db2019-03-19 16:41:16 +000011000 }
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011001 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc());
11002 assert(AA->getAllocator() &&
11003 "Expected allocator expression for non-default allocator.");
11004 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator());
Alexey Bataev6cf7b712019-04-08 19:06:42 +000011005 // According to the standard, the original allocator type is a enum (integer).
11006 // Convert to pointer type, if required.
11007 if (Allocator->getType()->isIntegerTy())
11008 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy);
11009 else if (Allocator->getType()->isPointerTy())
11010 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator,
11011 CGM.VoidPtrTy);
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011012 llvm::Value *Args[] = {ThreadID, Size, Allocator};
11013
11014 llvm::Value *Addr =
11015 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args,
11016 CVD->getName() + ".void.addr");
11017 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr,
11018 Allocator};
11019 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free);
11020
11021 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
11022 llvm::makeArrayRef(FiniArgs));
11023 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11024 Addr,
11025 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())),
11026 CVD->getName() + ".addr");
11027 return Address(Addr, Align);
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000011028}
11029
James Y Knight9871db02019-02-05 16:42:33 +000011030llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011031 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11032 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11033 llvm_unreachable("Not supported in SIMD-only mode");
11034}
11035
James Y Knight9871db02019-02-05 16:42:33 +000011036llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011037 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11038 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11039 llvm_unreachable("Not supported in SIMD-only mode");
11040}
11041
James Y Knight9871db02019-02-05 16:42:33 +000011042llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011043 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11044 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
11045 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
11046 bool Tied, unsigned &NumberOfParts) {
11047 llvm_unreachable("Not supported in SIMD-only mode");
11048}
11049
11050void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF,
11051 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000011052 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011053 ArrayRef<llvm::Value *> CapturedVars,
11054 const Expr *IfCond) {
11055 llvm_unreachable("Not supported in SIMD-only mode");
11056}
11057
11058void CGOpenMPSIMDRuntime::emitCriticalRegion(
11059 CodeGenFunction &CGF, StringRef CriticalName,
11060 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
11061 const Expr *Hint) {
11062 llvm_unreachable("Not supported in SIMD-only mode");
11063}
11064
11065void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF,
11066 const RegionCodeGenTy &MasterOpGen,
11067 SourceLocation Loc) {
11068 llvm_unreachable("Not supported in SIMD-only mode");
11069}
11070
11071void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
11072 SourceLocation Loc) {
11073 llvm_unreachable("Not supported in SIMD-only mode");
11074}
11075
11076void CGOpenMPSIMDRuntime::emitTaskgroupRegion(
11077 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen,
11078 SourceLocation Loc) {
11079 llvm_unreachable("Not supported in SIMD-only mode");
11080}
11081
11082void CGOpenMPSIMDRuntime::emitSingleRegion(
11083 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen,
11084 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars,
11085 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs,
11086 ArrayRef<const Expr *> AssignmentOps) {
11087 llvm_unreachable("Not supported in SIMD-only mode");
11088}
11089
11090void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF,
11091 const RegionCodeGenTy &OrderedOpGen,
11092 SourceLocation Loc,
11093 bool IsThreads) {
11094 llvm_unreachable("Not supported in SIMD-only mode");
11095}
11096
11097void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF,
11098 SourceLocation Loc,
11099 OpenMPDirectiveKind Kind,
11100 bool EmitChecks,
11101 bool ForceSimpleCall) {
11102 llvm_unreachable("Not supported in SIMD-only mode");
11103}
11104
11105void CGOpenMPSIMDRuntime::emitForDispatchInit(
11106 CodeGenFunction &CGF, SourceLocation Loc,
11107 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
11108 bool Ordered, const DispatchRTInput &DispatchValues) {
11109 llvm_unreachable("Not supported in SIMD-only mode");
11110}
11111
11112void CGOpenMPSIMDRuntime::emitForStaticInit(
11113 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind,
11114 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) {
11115 llvm_unreachable("Not supported in SIMD-only mode");
11116}
11117
11118void CGOpenMPSIMDRuntime::emitDistributeStaticInit(
11119 CodeGenFunction &CGF, SourceLocation Loc,
11120 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) {
11121 llvm_unreachable("Not supported in SIMD-only mode");
11122}
11123
11124void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
11125 SourceLocation Loc,
11126 unsigned IVSize,
11127 bool IVSigned) {
11128 llvm_unreachable("Not supported in SIMD-only mode");
11129}
11130
11131void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF,
11132 SourceLocation Loc,
11133 OpenMPDirectiveKind DKind) {
11134 llvm_unreachable("Not supported in SIMD-only mode");
11135}
11136
11137llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF,
11138 SourceLocation Loc,
11139 unsigned IVSize, bool IVSigned,
11140 Address IL, Address LB,
11141 Address UB, Address ST) {
11142 llvm_unreachable("Not supported in SIMD-only mode");
11143}
11144
11145void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
11146 llvm::Value *NumThreads,
11147 SourceLocation Loc) {
11148 llvm_unreachable("Not supported in SIMD-only mode");
11149}
11150
11151void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF,
11152 OpenMPProcBindClauseKind ProcBind,
11153 SourceLocation Loc) {
11154 llvm_unreachable("Not supported in SIMD-only mode");
11155}
11156
11157Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
11158 const VarDecl *VD,
11159 Address VDAddr,
11160 SourceLocation Loc) {
11161 llvm_unreachable("Not supported in SIMD-only mode");
11162}
11163
11164llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition(
11165 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit,
11166 CodeGenFunction *CGF) {
11167 llvm_unreachable("Not supported in SIMD-only mode");
11168}
11169
11170Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate(
11171 CodeGenFunction &CGF, QualType VarType, StringRef Name) {
11172 llvm_unreachable("Not supported in SIMD-only mode");
11173}
11174
11175void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF,
11176 ArrayRef<const Expr *> Vars,
11177 SourceLocation Loc) {
11178 llvm_unreachable("Not supported in SIMD-only mode");
11179}
11180
11181void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
11182 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000011183 llvm::Function *TaskFunction,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011184 QualType SharedsTy, Address Shareds,
11185 const Expr *IfCond,
11186 const OMPTaskDataTy &Data) {
11187 llvm_unreachable("Not supported in SIMD-only mode");
11188}
11189
11190void CGOpenMPSIMDRuntime::emitTaskLoopCall(
11191 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000011192 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011193 const Expr *IfCond, const OMPTaskDataTy &Data) {
11194 llvm_unreachable("Not supported in SIMD-only mode");
11195}
11196
11197void CGOpenMPSIMDRuntime::emitReduction(
11198 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates,
11199 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
11200 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) {
11201 assert(Options.SimpleReduction && "Only simple reduction is expected.");
11202 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
11203 ReductionOps, Options);
11204}
11205
11206llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit(
11207 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
11208 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
11209 llvm_unreachable("Not supported in SIMD-only mode");
11210}
11211
11212void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
11213 SourceLocation Loc,
11214 ReductionCodeGen &RCG,
11215 unsigned N) {
11216 llvm_unreachable("Not supported in SIMD-only mode");
11217}
11218
11219Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
11220 SourceLocation Loc,
11221 llvm::Value *ReductionsPtr,
11222 LValue SharedLVal) {
11223 llvm_unreachable("Not supported in SIMD-only mode");
11224}
11225
11226void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
11227 SourceLocation Loc) {
11228 llvm_unreachable("Not supported in SIMD-only mode");
11229}
11230
11231void CGOpenMPSIMDRuntime::emitCancellationPointCall(
11232 CodeGenFunction &CGF, SourceLocation Loc,
11233 OpenMPDirectiveKind CancelRegion) {
11234 llvm_unreachable("Not supported in SIMD-only mode");
11235}
11236
11237void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF,
11238 SourceLocation Loc, const Expr *IfCond,
11239 OpenMPDirectiveKind CancelRegion) {
11240 llvm_unreachable("Not supported in SIMD-only mode");
11241}
11242
11243void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction(
11244 const OMPExecutableDirective &D, StringRef ParentName,
11245 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
11246 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
11247 llvm_unreachable("Not supported in SIMD-only mode");
11248}
11249
11250void CGOpenMPSIMDRuntime::emitTargetCall(CodeGenFunction &CGF,
11251 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000011252 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011253 llvm::Value *OutlinedFnID,
James Y Knight9871db02019-02-05 16:42:33 +000011254 const Expr *IfCond,
11255 const Expr *Device) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011256 llvm_unreachable("Not supported in SIMD-only mode");
11257}
11258
11259bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) {
11260 llvm_unreachable("Not supported in SIMD-only mode");
11261}
11262
11263bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
11264 llvm_unreachable("Not supported in SIMD-only mode");
11265}
11266
11267bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) {
11268 return false;
11269}
11270
11271llvm::Function *CGOpenMPSIMDRuntime::emitRegistrationFunction() {
11272 return nullptr;
11273}
11274
11275void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF,
11276 const OMPExecutableDirective &D,
11277 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000011278 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011279 ArrayRef<llvm::Value *> CapturedVars) {
11280 llvm_unreachable("Not supported in SIMD-only mode");
11281}
11282
11283void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
11284 const Expr *NumTeams,
11285 const Expr *ThreadLimit,
11286 SourceLocation Loc) {
11287 llvm_unreachable("Not supported in SIMD-only mode");
11288}
11289
11290void CGOpenMPSIMDRuntime::emitTargetDataCalls(
11291 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
11292 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
11293 llvm_unreachable("Not supported in SIMD-only mode");
11294}
11295
11296void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
11297 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
11298 const Expr *Device) {
11299 llvm_unreachable("Not supported in SIMD-only mode");
11300}
11301
11302void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000011303 const OMPLoopDirective &D,
11304 ArrayRef<Expr *> NumIterations) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011305 llvm_unreachable("Not supported in SIMD-only mode");
11306}
11307
11308void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
11309 const OMPDependClause *C) {
11310 llvm_unreachable("Not supported in SIMD-only mode");
11311}
11312
11313const VarDecl *
11314CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD,
11315 const VarDecl *NativeParam) const {
11316 llvm_unreachable("Not supported in SIMD-only mode");
11317}
11318
11319Address
11320CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF,
11321 const VarDecl *NativeParam,
11322 const VarDecl *TargetParam) const {
11323 llvm_unreachable("Not supported in SIMD-only mode");
11324}