blob: a38007001258767a287b56f46edda997b9285f76 [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 Bataevc2cd2d42019-10-10 17:28:10 +00001267bool CGOpenMPRuntime::tryEmitDeclareVariant(const GlobalDecl &NewGD,
1268 const GlobalDecl &OldGD,
1269 llvm::GlobalValue *OrigAddr,
1270 bool IsForDefinition) {
Alexey Bataev2df5f122019-10-01 20:18:32 +00001271 // Emit at least a definition for the aliasee if the the address of the
1272 // original function is requested.
1273 if (IsForDefinition || OrigAddr)
1274 (void)CGM.GetAddrOfGlobal(NewGD);
1275 StringRef NewMangledName = CGM.getMangledName(NewGD);
1276 llvm::GlobalValue *Addr = CGM.GetGlobalValue(NewMangledName);
1277 if (Addr && !Addr->isDeclaration()) {
1278 const auto *D = cast<FunctionDecl>(OldGD.getDecl());
1279 const CGFunctionInfo &FI = CGM.getTypes().arrangeGlobalDeclaration(OldGD);
1280 llvm::Type *DeclTy = CGM.getTypes().GetFunctionType(FI);
1281
1282 // Create a reference to the named value. This ensures that it is emitted
1283 // if a deferred decl.
1284 llvm::GlobalValue::LinkageTypes LT = CGM.getFunctionLinkage(OldGD);
1285
1286 // Create the new alias itself, but don't set a name yet.
1287 auto *GA =
1288 llvm::GlobalAlias::create(DeclTy, 0, LT, "", Addr, &CGM.getModule());
1289
1290 if (OrigAddr) {
1291 assert(OrigAddr->isDeclaration() && "Expected declaration");
1292
1293 GA->takeName(OrigAddr);
1294 OrigAddr->replaceAllUsesWith(
1295 llvm::ConstantExpr::getBitCast(GA, OrigAddr->getType()));
1296 OrigAddr->eraseFromParent();
1297 } else {
1298 GA->setName(CGM.getMangledName(OldGD));
1299 }
1300
1301 // Set attributes which are particular to an alias; this is a
1302 // specialization of the attributes which may be set on a global function.
1303 if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakRefAttr>() ||
1304 D->isWeakImported())
1305 GA->setLinkage(llvm::Function::WeakAnyLinkage);
1306
1307 CGM.SetCommonAttributes(OldGD, GA);
1308 return true;
1309 }
1310 return false;
1311}
1312
Alexey Bataev91797552015-03-18 04:13:55 +00001313void CGOpenMPRuntime::clear() {
1314 InternalVars.clear();
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00001315 // Clean non-target variable declarations possibly used only in debug info.
1316 for (const auto &Data : EmittedNonTargetVariables) {
1317 if (!Data.getValue().pointsToAliveValue())
1318 continue;
1319 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue());
1320 if (!GV)
1321 continue;
1322 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1323 continue;
1324 GV->eraseFromParent();
1325 }
Alexey Bataev2df5f122019-10-01 20:18:32 +00001326 // Emit aliases for the deferred aliasees.
1327 for (const auto &Pair : DeferredVariantFunction) {
1328 StringRef MangledName = CGM.getMangledName(Pair.second.second);
1329 llvm::GlobalValue *Addr = CGM.GetGlobalValue(MangledName);
1330 // If not able to emit alias, just emit original declaration.
Alexey Bataevc2cd2d42019-10-10 17:28:10 +00001331 (void)tryEmitDeclareVariant(Pair.second.first, Pair.second.second, Addr,
1332 /*IsForDefinition=*/false);
Alexey Bataev2df5f122019-10-01 20:18:32 +00001333 }
Alexey Bataev91797552015-03-18 04:13:55 +00001334}
1335
Alexey Bataev18fa2322018-05-02 14:20:50 +00001336std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const {
1337 SmallString<128> Buffer;
1338 llvm::raw_svector_ostream OS(Buffer);
1339 StringRef Sep = FirstSeparator;
1340 for (StringRef Part : Parts) {
1341 OS << Sep << Part;
1342 Sep = Separator;
1343 }
1344 return OS.str();
1345}
1346
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001347static llvm::Function *
1348emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
1349 const Expr *CombinerInitializer, const VarDecl *In,
1350 const VarDecl *Out, bool IsCombiner) {
1351 // void .omp_combiner.(Ty *in, Ty *out);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001352 ASTContext &C = CGM.getContext();
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001353 QualType PtrTy = C.getPointerType(Ty).withRestrict();
1354 FunctionArgList Args;
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001355 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(),
Alexey Bataev56223232017-06-09 13:40:18 +00001356 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001357 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(),
Alexey Bataev56223232017-06-09 13:40:18 +00001358 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001359 Args.push_back(&OmpOutParm);
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001360 Args.push_back(&OmpInParm);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001361 const CGFunctionInfo &FnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00001362 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001363 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00001364 std::string Name = CGM.getOpenMPRuntime().getName(
1365 {IsCombiner ? "omp_combiner" : "omp_initializer", ""});
1366 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1367 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00001368 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataev8c5555c2019-05-21 15:11:58 +00001369 if (CGM.getLangOpts().Optimize) {
1370 Fn->removeFnAttr(llvm::Attribute::NoInline);
1371 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1372 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1373 }
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001374 CodeGenFunction CGF(CGM);
1375 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
1376 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions.
Alexey Bataev7cae94e2018-01-04 19:45:16 +00001377 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(),
1378 Out->getLocation());
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001379 CodeGenFunction::OMPPrivateScope Scope(CGF);
1380 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001381 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() {
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001382 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>())
1383 .getAddress();
1384 });
1385 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001386 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() {
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001387 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>())
1388 .getAddress();
1389 });
1390 (void)Scope.Privatize();
Alexey Bataev070f43a2017-09-06 14:49:58 +00001391 if (!IsCombiner && Out->hasInit() &&
1392 !CGF.isTrivialInitializer(Out->getInit())) {
1393 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out),
1394 Out->getType().getQualifiers(),
1395 /*IsInitializer=*/true);
1396 }
1397 if (CombinerInitializer)
1398 CGF.EmitIgnoredExpr(CombinerInitializer);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001399 Scope.ForceCleanup();
1400 CGF.FinishFunction();
1401 return Fn;
1402}
1403
1404void CGOpenMPRuntime::emitUserDefinedReduction(
1405 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) {
1406 if (UDRMap.count(D) > 0)
1407 return;
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001408 llvm::Function *Combiner = emitCombinerOrInitializer(
Alexey Bataeve6aa4692018-09-13 16:54:05 +00001409 CGM, D->getType(), D->getCombiner(),
1410 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()),
1411 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()),
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001412 /*IsCombiner=*/true);
1413 llvm::Function *Initializer = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001414 if (const Expr *Init = D->getInitializer()) {
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001415 Initializer = emitCombinerOrInitializer(
Alexey Bataev070f43a2017-09-06 14:49:58 +00001416 CGM, D->getType(),
1417 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init
1418 : nullptr,
Alexey Bataeve6aa4692018-09-13 16:54:05 +00001419 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()),
1420 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()),
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001421 /*IsCombiner=*/false);
1422 }
Alexey Bataev43a919f2018-04-13 17:48:43 +00001423 UDRMap.try_emplace(D, Combiner, Initializer);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001424 if (CGF) {
1425 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn);
1426 Decls.second.push_back(D);
1427 }
1428}
1429
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001430std::pair<llvm::Function *, llvm::Function *>
1431CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) {
1432 auto I = UDRMap.find(D);
1433 if (I != UDRMap.end())
1434 return I->second;
1435 emitUserDefinedReduction(/*CGF=*/nullptr, D);
1436 return UDRMap.lookup(D);
1437}
1438
James Y Knight9871db02019-02-05 16:42:33 +00001439static llvm::Function *emitParallelOrTeamsOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001440 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS,
1441 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind,
1442 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00001443 assert(ThreadIDVar->getType()->isPointerType() &&
1444 "thread id variable must be of type kmp_int32 *");
Alexey Bataev18095712014-10-10 12:19:54 +00001445 CodeGenFunction CGF(CGM, true);
Alexey Bataev25e5b442015-09-15 12:52:43 +00001446 bool HasCancel = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001447 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001448 HasCancel = OPD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001449 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001450 HasCancel = OPSD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001451 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001452 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001453 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
Alexey Bataev2139ed62017-11-16 18:20:21 +00001454 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001455 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
Alexey Bataev10a54312017-11-27 16:54:08 +00001456 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001457 else if (const auto *OPFD =
1458 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
Alexey Bataev10a54312017-11-27 16:54:08 +00001459 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001460 else if (const auto *OPFD =
Alexey Bataev10a54312017-11-27 16:54:08 +00001461 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1462 HasCancel = OPFD->hasCancel();
Alexey Bataev25e5b442015-09-15 12:52:43 +00001463 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001464 HasCancel, OutlinedHelperName);
Alexey Bataevd157d472015-06-24 03:35:38 +00001465 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev2377fe92015-09-10 08:12:02 +00001466 return CGF.GenerateOpenMPCapturedStmtFunction(*CS);
Alexey Bataev18095712014-10-10 12:19:54 +00001467}
1468
James Y Knight9871db02019-02-05 16:42:33 +00001469llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001470 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1471 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1472 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1473 return emitParallelOrTeamsOutlinedFunction(
1474 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1475}
1476
James Y Knight9871db02019-02-05 16:42:33 +00001477llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001478 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1479 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1480 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1481 return emitParallelOrTeamsOutlinedFunction(
1482 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1483}
1484
James Y Knight9871db02019-02-05 16:42:33 +00001485llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001486 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
Alexey Bataev48591dd2016-04-20 04:01:36 +00001487 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
1488 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
1489 bool Tied, unsigned &NumberOfParts) {
1490 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF,
1491 PrePostActionTy &) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00001492 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc());
1493 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc());
Alexey Bataev48591dd2016-04-20 04:01:36 +00001494 llvm::Value *TaskArgs[] = {
1495 UpLoc, ThreadID,
1496 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1497 TaskTVar->getType()->castAs<PointerType>())
1498 .getPointer()};
1499 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs);
1500 };
1501 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1502 UntiedCodeGen);
1503 CodeGen.setAction(Action);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001504 assert(!ThreadIDVar->getType()->isPointerType() &&
1505 "thread id variable must be of type kmp_int32 for tasks");
Alexey Bataev475a7442018-01-12 19:39:11 +00001506 const OpenMPDirectiveKind Region =
1507 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop
1508 : OMPD_task;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001509 const CapturedStmt *CS = D.getCapturedStmt(Region);
1510 const auto *TD = dyn_cast<OMPTaskDirective>(&D);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001511 CodeGenFunction CGF(CGM, true);
Alexey Bataev7292c292016-04-25 12:22:29 +00001512 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
1513 InnermostKind,
1514 TD ? TD->hasCancel() : false, Action);
Alexey Bataevd157d472015-06-24 03:35:38 +00001515 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
James Y Knight9871db02019-02-05 16:42:33 +00001516 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
Alexey Bataev48591dd2016-04-20 04:01:36 +00001517 if (!Tied)
1518 NumberOfParts = Action.getNumberOfParts();
1519 return Res;
Alexey Bataev62b63b12015-03-10 07:28:44 +00001520}
1521
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001522static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM,
1523 const RecordDecl *RD, const CGRecordLayout &RL,
1524 ArrayRef<llvm::Constant *> Data) {
1525 llvm::StructType *StructTy = RL.getLLVMType();
1526 unsigned PrevIdx = 0;
1527 ConstantInitBuilder CIBuilder(CGM);
1528 auto DI = Data.begin();
1529 for (const FieldDecl *FD : RD->fields()) {
1530 unsigned Idx = RL.getLLVMFieldNo(FD);
1531 // Fill the alignment.
1532 for (unsigned I = PrevIdx; I < Idx; ++I)
1533 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I)));
1534 PrevIdx = Idx + 1;
1535 Fields.add(*DI);
1536 ++DI;
1537 }
1538}
1539
1540template <class... As>
1541static llvm::GlobalVariable *
Mike Ricee1ca7b62018-08-29 15:45:11 +00001542createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant,
1543 ArrayRef<llvm::Constant *> Data, const Twine &Name,
1544 As &&... Args) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001545 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1546 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1547 ConstantInitBuilder CIBuilder(CGM);
1548 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType());
1549 buildStructValue(Fields, CGM, RD, RL, Data);
1550 return Fields.finishAndCreateGlobal(
Mike Ricee1ca7b62018-08-29 15:45:11 +00001551 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant,
1552 std::forward<As>(Args)...);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001553}
1554
1555template <typename T>
Benjamin Kramer651d0bf2018-05-15 21:26:47 +00001556static void
1557createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty,
1558 ArrayRef<llvm::Constant *> Data,
1559 T &Parent) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001560 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1561 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1562 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType());
1563 buildStructValue(Fields, CGM, RD, RL, Data);
1564 Fields.finishAndAddTo(Parent);
1565}
1566
Alexey Bataev50b3c952016-02-19 10:38:26 +00001567Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001568 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy);
Alexey Bataevceeaa482018-11-21 21:04:34 +00001569 unsigned Reserved2Flags = getDefaultLocationReserved2Flags();
1570 FlagsTy FlagsKey(Flags, Reserved2Flags);
1571 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey);
Alexey Bataev9959db52014-05-06 10:08:46 +00001572 if (!Entry) {
1573 if (!DefaultOpenMPPSource) {
1574 // Initialize default location for psource field of ident_t structure of
1575 // all ident_t objects. Format is ";file;function;line;column;;".
1576 // Taken from
James Y Knight5d71fc52019-01-29 16:37:27 +00001577 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp
Alexey Bataev9959db52014-05-06 10:08:46 +00001578 DefaultOpenMPPSource =
John McCall7f416cc2015-09-08 08:05:57 +00001579 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001580 DefaultOpenMPPSource =
1581 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
1582 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001583
Alexey Bataevceeaa482018-11-21 21:04:34 +00001584 llvm::Constant *Data[] = {
1585 llvm::ConstantInt::getNullValue(CGM.Int32Ty),
1586 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
1587 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags),
1588 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource};
Mike Ricee1ca7b62018-08-29 15:45:11 +00001589 llvm::GlobalValue *DefaultOpenMPLocation =
Alexey Bataevceeaa482018-11-21 21:04:34 +00001590 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "",
Mike Ricee1ca7b62018-08-29 15:45:11 +00001591 llvm::GlobalValue::PrivateLinkage);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001592 DefaultOpenMPLocation->setUnnamedAddr(
1593 llvm::GlobalValue::UnnamedAddr::Global);
John McCall6c9f1fdb2016-11-19 08:17:24 +00001594
Alexey Bataevceeaa482018-11-21 21:04:34 +00001595 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation;
Alexey Bataev9959db52014-05-06 10:08:46 +00001596 }
John McCall7f416cc2015-09-08 08:05:57 +00001597 return Address(Entry, Align);
Alexey Bataev9959db52014-05-06 10:08:46 +00001598}
1599
Alexey Bataevfd006c42018-10-05 15:08:53 +00001600void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF,
1601 bool AtCurrentPoint) {
1602 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1603 assert(!Elem.second.ServiceInsertPt && "Insert point is set already.");
1604
1605 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty);
1606 if (AtCurrentPoint) {
1607 Elem.second.ServiceInsertPt = new llvm::BitCastInst(
1608 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock());
1609 } else {
1610 Elem.second.ServiceInsertPt =
1611 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt");
1612 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt);
1613 }
1614}
1615
1616void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) {
1617 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1618 if (Elem.second.ServiceInsertPt) {
1619 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt;
1620 Elem.second.ServiceInsertPt = nullptr;
1621 Ptr->eraseFromParent();
1622 }
1623}
1624
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001625llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
1626 SourceLocation Loc,
Alexey Bataev50b3c952016-02-19 10:38:26 +00001627 unsigned Flags) {
1628 Flags |= OMP_IDENT_KMPC;
Alexey Bataev9959db52014-05-06 10:08:46 +00001629 // If no debug info is generated - return global default location.
Benjamin Kramer8c305922016-02-02 11:06:51 +00001630 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo ||
Alexey Bataev9959db52014-05-06 10:08:46 +00001631 Loc.isInvalid())
John McCall7f416cc2015-09-08 08:05:57 +00001632 return getOrCreateDefaultLocation(Flags).getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001633
1634 assert(CGF.CurFn && "No function in current CodeGenFunction.");
1635
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001636 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy);
John McCall7f416cc2015-09-08 08:05:57 +00001637 Address LocValue = Address::invalid();
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001638 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
1639 if (I != OpenMPLocThreadIDMap.end())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001640 LocValue = Address(I->second.DebugLoc, Align);
John McCall7f416cc2015-09-08 08:05:57 +00001641
Alexander Musmanc6388682014-12-15 07:07:06 +00001642 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
1643 // GetOpenMPThreadID was called before this routine.
John McCall7f416cc2015-09-08 08:05:57 +00001644 if (!LocValue.isValid()) {
Alexey Bataev15007ba2014-05-07 06:18:01 +00001645 // Generate "ident_t .kmpc_loc.addr;"
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001646 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr");
Alexey Bataev18095712014-10-10 12:19:54 +00001647 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
John McCall7f416cc2015-09-08 08:05:57 +00001648 Elem.second.DebugLoc = AI.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001649 LocValue = AI;
1650
Alexey Bataevfd006c42018-10-05 15:08:53 +00001651 if (!Elem.second.ServiceInsertPt)
1652 setLocThreadIdInsertPt(CGF);
Alexey Bataev9959db52014-05-06 10:08:46 +00001653 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001654 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001655 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001656 CGF.getTypeSize(IdentQTy));
Alexey Bataev9959db52014-05-06 10:08:46 +00001657 }
1658
1659 // char **psource = &.kmpc_loc_<flags>.addr.psource;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001660 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy);
1661 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin();
1662 LValue PSource =
1663 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource));
Alexey Bataev9959db52014-05-06 10:08:46 +00001664
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001665 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
Alexey Bataevf002aca2014-05-30 05:48:40 +00001666 if (OMPDebugLoc == nullptr) {
1667 SmallString<128> Buffer2;
1668 llvm::raw_svector_ostream OS2(Buffer2);
1669 // Build debug location
1670 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
1671 OS2 << ";" << PLoc.getFilename() << ";";
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001672 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl))
Alexey Bataevf002aca2014-05-30 05:48:40 +00001673 OS2 << FD->getQualifiedNameAsString();
Alexey Bataevf002aca2014-05-30 05:48:40 +00001674 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
1675 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
1676 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
Alexey Bataev9959db52014-05-06 10:08:46 +00001677 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001678 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001679 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource);
Alexey Bataevf002aca2014-05-30 05:48:40 +00001680
John McCall7f416cc2015-09-08 08:05:57 +00001681 // Our callers always pass this to a runtime function, so for
1682 // convenience, go ahead and return a naked pointer.
1683 return LocValue.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001684}
1685
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001686llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
1687 SourceLocation Loc) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001688 assert(CGF.CurFn && "No function in current CodeGenFunction.");
1689
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001690 llvm::Value *ThreadID = nullptr;
Alexey Bataev18095712014-10-10 12:19:54 +00001691 // Check whether we've already cached a load of the thread id in this
1692 // function.
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001693 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
Alexey Bataev18095712014-10-10 12:19:54 +00001694 if (I != OpenMPLocThreadIDMap.end()) {
1695 ThreadID = I->second.ThreadID;
Alexey Bataev03b340a2014-10-21 03:16:40 +00001696 if (ThreadID != nullptr)
1697 return ThreadID;
1698 }
Alexey Bataevaee18552017-08-16 14:01:00 +00001699 // If exceptions are enabled, do not use parameter to avoid possible crash.
Alexey Bataev780f5552019-10-17 17:12:03 +00001700 if (auto *OMPRegionInfo =
1701 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
1702 if (OMPRegionInfo->getThreadIDVariable()) {
1703 // Check if this an outlined function with thread id passed as argument.
1704 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1705 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent();
1706 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions ||
1707 !CGF.getLangOpts().CXXExceptions ||
1708 CGF.Builder.GetInsertBlock() == TopBlock ||
1709 !isa<llvm::Instruction>(LVal.getPointer()) ||
1710 cast<llvm::Instruction>(LVal.getPointer())->getParent() == TopBlock ||
1711 cast<llvm::Instruction>(LVal.getPointer())->getParent() ==
1712 CGF.Builder.GetInsertBlock()) {
Alexey Bataev1e491372018-01-23 18:44:14 +00001713 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc);
Alexey Bataevaee18552017-08-16 14:01:00 +00001714 // If value loaded in entry block, cache it and use it everywhere in
1715 // function.
Alexey Bataev780f5552019-10-17 17:12:03 +00001716 if (CGF.Builder.GetInsertBlock() == TopBlock) {
Alexey Bataevaee18552017-08-16 14:01:00 +00001717 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1718 Elem.second.ThreadID = ThreadID;
1719 }
1720 return ThreadID;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001721 }
Alexey Bataevd6c57552014-07-25 07:55:17 +00001722 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001723 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001724
1725 // This is not an outlined function region - need to call __kmpc_int32
1726 // kmpc_global_thread_num(ident_t *loc).
1727 // Generate thread id value and cache this value for use across the
1728 // function.
Alexey Bataevfd006c42018-10-05 15:08:53 +00001729 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1730 if (!Elem.second.ServiceInsertPt)
1731 setLocThreadIdInsertPt(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001732 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001733 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001734 llvm::CallInst *Call = CGF.Builder.CreateCall(
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001735 createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
1736 emitUpdateLocation(CGF, Loc));
1737 Call->setCallingConv(CGF.getRuntimeCC());
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001738 Elem.second.ThreadID = Call;
1739 return Call;
Alexey Bataev9959db52014-05-06 10:08:46 +00001740}
1741
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001742void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001743 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataevfd006c42018-10-05 15:08:53 +00001744 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) {
1745 clearLocThreadIdInsertPt(CGF);
Alexey Bataev03b340a2014-10-21 03:16:40 +00001746 OpenMPLocThreadIDMap.erase(CGF.CurFn);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001747 }
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001748 if (FunctionUDRMap.count(CGF.CurFn) > 0) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001749 for(auto *D : FunctionUDRMap[CGF.CurFn])
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001750 UDRMap.erase(D);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001751 FunctionUDRMap.erase(CGF.CurFn);
1752 }
Michael Krused47b9432019-08-05 18:43:21 +00001753 auto I = FunctionUDMMap.find(CGF.CurFn);
1754 if (I != FunctionUDMMap.end()) {
1755 for(auto *D : I->second)
1756 UDMMap.erase(D);
1757 FunctionUDMMap.erase(I);
1758 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001759}
1760
1761llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001762 return IdentTy->getPointerTo();
Alexey Bataev9959db52014-05-06 10:08:46 +00001763}
1764
1765llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001766 if (!Kmpc_MicroTy) {
1767 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
1768 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
1769 llvm::PointerType::getUnqual(CGM.Int32Ty)};
1770 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
1771 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001772 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
1773}
1774
James Y Knight9871db02019-02-05 16:42:33 +00001775llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
1776 llvm::FunctionCallee RTLFn = nullptr;
Alexey Bataev50b3c952016-02-19 10:38:26 +00001777 switch (static_cast<OpenMPRTLFunction>(Function)) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001778 case OMPRTL__kmpc_fork_call: {
1779 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
1780 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +00001781 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1782 getKmpc_MicroPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001783 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001784 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
Alexey Bataev9959db52014-05-06 10:08:46 +00001785 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
James Y Knight9871db02019-02-05 16:42:33 +00001786 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) {
Johannes Doerfertac991bb2019-01-19 05:36:54 +00001787 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
1788 llvm::LLVMContext &Ctx = F->getContext();
1789 llvm::MDBuilder MDB(Ctx);
1790 // Annotate the callback behavior of the __kmpc_fork_call:
1791 // - The callback callee is argument number 2 (microtask).
1792 // - The first two arguments of the callback callee are unknown (-1).
1793 // - All variadic arguments to the __kmpc_fork_call are passed to the
1794 // callback callee.
1795 F->addMetadata(
1796 llvm::LLVMContext::MD_callback,
1797 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
1798 2, {-1, -1},
1799 /* VarArgsArePassed */ true)}));
1800 }
1801 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001802 break;
1803 }
1804 case OMPRTL__kmpc_global_thread_num: {
1805 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +00001806 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001807 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001808 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
Alexey Bataev9959db52014-05-06 10:08:46 +00001809 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
1810 break;
1811 }
Alexey Bataev97720002014-11-11 04:05:39 +00001812 case OMPRTL__kmpc_threadprivate_cached: {
1813 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
1814 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
1815 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1816 CGM.VoidPtrTy, CGM.SizeTy,
1817 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001818 auto *FnTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001819 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
1820 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
1821 break;
1822 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001823 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001824 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
1825 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001826 llvm::Type *TypeParams[] = {
1827 getIdentTyPointerTy(), CGM.Int32Ty,
1828 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001829 auto *FnTy =
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001830 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1831 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
1832 break;
1833 }
Alexey Bataevfc57d162015-12-15 10:55:09 +00001834 case OMPRTL__kmpc_critical_with_hint: {
1835 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid,
1836 // kmp_critical_name *crit, uintptr_t hint);
1837 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1838 llvm::PointerType::getUnqual(KmpCriticalNameTy),
1839 CGM.IntPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001840 auto *FnTy =
Alexey Bataevfc57d162015-12-15 10:55:09 +00001841 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1842 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint");
1843 break;
1844 }
Alexey Bataev97720002014-11-11 04:05:39 +00001845 case OMPRTL__kmpc_threadprivate_register: {
1846 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
1847 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
1848 // typedef void *(*kmpc_ctor)(void *);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001849 auto *KmpcCtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001850 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1851 /*isVarArg*/ false)->getPointerTo();
1852 // typedef void *(*kmpc_cctor)(void *, void *);
1853 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001854 auto *KmpcCopyCtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001855 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001856 /*isVarArg*/ false)
1857 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00001858 // typedef void (*kmpc_dtor)(void *);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001859 auto *KmpcDtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001860 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
1861 ->getPointerTo();
1862 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
1863 KmpcCopyCtorTy, KmpcDtorTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001864 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
Alexey Bataev97720002014-11-11 04:05:39 +00001865 /*isVarArg*/ false);
1866 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
1867 break;
1868 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001869 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001870 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
1871 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001872 llvm::Type *TypeParams[] = {
1873 getIdentTyPointerTy(), CGM.Int32Ty,
1874 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001875 auto *FnTy =
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001876 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1877 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
1878 break;
1879 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001880 case OMPRTL__kmpc_cancel_barrier: {
1881 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
1882 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001883 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001884 auto *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001885 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1886 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001887 break;
1888 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001889 case OMPRTL__kmpc_barrier: {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001890 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001891 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001892 auto *FnTy =
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001893 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1894 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
1895 break;
1896 }
Alexander Musmanc6388682014-12-15 07:07:06 +00001897 case OMPRTL__kmpc_for_static_fini: {
1898 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
1899 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001900 auto *FnTy =
Alexander Musmanc6388682014-12-15 07:07:06 +00001901 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1902 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
1903 break;
1904 }
Alexey Bataevb2059782014-10-13 08:23:51 +00001905 case OMPRTL__kmpc_push_num_threads: {
1906 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
1907 // kmp_int32 num_threads)
1908 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1909 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001910 auto *FnTy =
Alexey Bataevb2059782014-10-13 08:23:51 +00001911 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1912 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
1913 break;
1914 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001915 case OMPRTL__kmpc_serialized_parallel: {
1916 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
1917 // global_tid);
1918 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001919 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001920 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1921 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
1922 break;
1923 }
1924 case OMPRTL__kmpc_end_serialized_parallel: {
1925 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
1926 // global_tid);
1927 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001928 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001929 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1930 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
1931 break;
1932 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001933 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001934 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001935 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001936 auto *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001937 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001938 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
1939 break;
1940 }
Alexey Bataev8d690652014-12-04 07:23:53 +00001941 case OMPRTL__kmpc_master: {
1942 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
1943 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001944 auto *FnTy =
Alexey Bataev8d690652014-12-04 07:23:53 +00001945 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1946 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
1947 break;
1948 }
1949 case OMPRTL__kmpc_end_master: {
1950 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
1951 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001952 auto *FnTy =
Alexey Bataev8d690652014-12-04 07:23:53 +00001953 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1954 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
1955 break;
1956 }
Alexey Bataev9f797f32015-02-05 05:57:51 +00001957 case OMPRTL__kmpc_omp_taskyield: {
1958 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
1959 // int end_part);
1960 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001961 auto *FnTy =
Alexey Bataev9f797f32015-02-05 05:57:51 +00001962 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1963 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
1964 break;
1965 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001966 case OMPRTL__kmpc_single: {
1967 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
1968 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001969 auto *FnTy =
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001970 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1971 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
1972 break;
1973 }
1974 case OMPRTL__kmpc_end_single: {
1975 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
1976 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001977 auto *FnTy =
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001978 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1979 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
1980 break;
1981 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00001982 case OMPRTL__kmpc_omp_task_alloc: {
1983 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
1984 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
1985 // kmp_routine_entry_t *task_entry);
1986 assert(KmpRoutineEntryPtrTy != nullptr &&
1987 "Type kmp_routine_entry_t must be created.");
1988 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1989 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
1990 // Return void * and then cast to particular kmp_task_t type.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001991 auto *FnTy =
Alexey Bataev62b63b12015-03-10 07:28:44 +00001992 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
1993 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
1994 break;
1995 }
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00001996 case OMPRTL__kmpc_omp_target_task_alloc: {
1997 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid,
1998 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
1999 // kmp_routine_entry_t *task_entry, kmp_int64 device_id);
2000 assert(KmpRoutineEntryPtrTy != nullptr &&
2001 "Type kmp_routine_entry_t must be created.");
2002 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
2003 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy,
2004 CGM.Int64Ty};
2005 // Return void * and then cast to particular kmp_task_t type.
2006 auto *FnTy =
2007 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2008 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc");
2009 break;
2010 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002011 case OMPRTL__kmpc_omp_task: {
2012 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2013 // *new_task);
2014 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2015 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002016 auto *FnTy =
Alexey Bataev62b63b12015-03-10 07:28:44 +00002017 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2018 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
2019 break;
2020 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00002021 case OMPRTL__kmpc_copyprivate: {
2022 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
Alexey Bataev66beaa92015-04-30 03:47:32 +00002023 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
Alexey Bataeva63048e2015-03-23 06:18:07 +00002024 // kmp_int32 didit);
2025 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2026 auto *CpyFnTy =
2027 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
Alexey Bataev66beaa92015-04-30 03:47:32 +00002028 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
Alexey Bataeva63048e2015-03-23 06:18:07 +00002029 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
2030 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002031 auto *FnTy =
Alexey Bataeva63048e2015-03-23 06:18:07 +00002032 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2033 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
2034 break;
2035 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002036 case OMPRTL__kmpc_reduce: {
2037 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
2038 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
2039 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
2040 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2041 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
2042 /*isVarArg=*/false);
2043 llvm::Type *TypeParams[] = {
2044 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
2045 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
2046 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002047 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002048 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2049 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
2050 break;
2051 }
2052 case OMPRTL__kmpc_reduce_nowait: {
2053 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
2054 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
2055 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
2056 // *lck);
2057 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2058 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
2059 /*isVarArg=*/false);
2060 llvm::Type *TypeParams[] = {
2061 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
2062 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
2063 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002064 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002065 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2066 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
2067 break;
2068 }
2069 case OMPRTL__kmpc_end_reduce: {
2070 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
2071 // kmp_critical_name *lck);
2072 llvm::Type *TypeParams[] = {
2073 getIdentTyPointerTy(), CGM.Int32Ty,
2074 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002075 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002076 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2077 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
2078 break;
2079 }
2080 case OMPRTL__kmpc_end_reduce_nowait: {
2081 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
2082 // kmp_critical_name *lck);
2083 llvm::Type *TypeParams[] = {
2084 getIdentTyPointerTy(), CGM.Int32Ty,
2085 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002086 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002087 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2088 RTLFn =
2089 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
2090 break;
2091 }
Alexey Bataev1d677132015-04-22 13:57:31 +00002092 case OMPRTL__kmpc_omp_task_begin_if0: {
2093 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2094 // *new_task);
2095 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2096 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002097 auto *FnTy =
Alexey Bataev1d677132015-04-22 13:57:31 +00002098 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2099 RTLFn =
2100 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
2101 break;
2102 }
2103 case OMPRTL__kmpc_omp_task_complete_if0: {
2104 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2105 // *new_task);
2106 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2107 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002108 auto *FnTy =
Alexey Bataev1d677132015-04-22 13:57:31 +00002109 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2110 RTLFn = CGM.CreateRuntimeFunction(FnTy,
2111 /*Name=*/"__kmpc_omp_task_complete_if0");
2112 break;
2113 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002114 case OMPRTL__kmpc_ordered: {
2115 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
2116 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002117 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002118 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2119 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
2120 break;
2121 }
2122 case OMPRTL__kmpc_end_ordered: {
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002123 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002124 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002125 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002126 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2127 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
2128 break;
2129 }
Alexey Bataev8b8e2022015-04-27 05:22:09 +00002130 case OMPRTL__kmpc_omp_taskwait: {
2131 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
2132 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002133 auto *FnTy =
Alexey Bataev8b8e2022015-04-27 05:22:09 +00002134 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2135 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
2136 break;
2137 }
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002138 case OMPRTL__kmpc_taskgroup: {
2139 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
2140 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002141 auto *FnTy =
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002142 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2143 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
2144 break;
2145 }
2146 case OMPRTL__kmpc_end_taskgroup: {
2147 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
2148 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002149 auto *FnTy =
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002150 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2151 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
2152 break;
2153 }
Alexey Bataev7f210c62015-06-18 13:40:03 +00002154 case OMPRTL__kmpc_push_proc_bind: {
2155 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
2156 // int proc_bind)
2157 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002158 auto *FnTy =
Alexey Bataev7f210c62015-06-18 13:40:03 +00002159 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2160 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
2161 break;
2162 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002163 case OMPRTL__kmpc_omp_task_with_deps: {
2164 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
2165 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
2166 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
2167 llvm::Type *TypeParams[] = {
2168 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
2169 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002170 auto *FnTy =
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002171 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2172 RTLFn =
2173 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
2174 break;
2175 }
2176 case OMPRTL__kmpc_omp_wait_deps: {
2177 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
2178 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
2179 // kmp_depend_info_t *noalias_dep_list);
2180 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2181 CGM.Int32Ty, CGM.VoidPtrTy,
2182 CGM.Int32Ty, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002183 auto *FnTy =
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002184 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2185 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
2186 break;
2187 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00002188 case OMPRTL__kmpc_cancellationpoint: {
2189 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
2190 // global_tid, kmp_int32 cncl_kind)
2191 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002192 auto *FnTy =
Alexey Bataev0f34da12015-07-02 04:17:07 +00002193 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2194 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
2195 break;
2196 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002197 case OMPRTL__kmpc_cancel: {
2198 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
2199 // kmp_int32 cncl_kind)
2200 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002201 auto *FnTy =
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002202 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2203 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
2204 break;
2205 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002206 case OMPRTL__kmpc_push_num_teams: {
2207 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid,
2208 // kmp_int32 num_teams, kmp_int32 num_threads)
2209 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
2210 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002211 auto *FnTy =
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002212 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2213 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams");
2214 break;
2215 }
2216 case OMPRTL__kmpc_fork_teams: {
2217 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
2218 // microtask, ...);
2219 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2220 getKmpc_MicroPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002221 auto *FnTy =
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002222 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
2223 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams");
James Y Knight9871db02019-02-05 16:42:33 +00002224 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) {
Johannes Doerfertac991bb2019-01-19 05:36:54 +00002225 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
2226 llvm::LLVMContext &Ctx = F->getContext();
2227 llvm::MDBuilder MDB(Ctx);
2228 // Annotate the callback behavior of the __kmpc_fork_teams:
2229 // - The callback callee is argument number 2 (microtask).
2230 // - The first two arguments of the callback callee are unknown (-1).
2231 // - All variadic arguments to the __kmpc_fork_teams are passed to the
2232 // callback callee.
2233 F->addMetadata(
2234 llvm::LLVMContext::MD_callback,
2235 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
2236 2, {-1, -1},
2237 /* VarArgsArePassed */ true)}));
2238 }
2239 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002240 break;
2241 }
Alexey Bataev7292c292016-04-25 12:22:29 +00002242 case OMPRTL__kmpc_taskloop: {
2243 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
2244 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
2245 // sched, kmp_uint64 grainsize, void *task_dup);
2246 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
2247 CGM.IntTy,
2248 CGM.VoidPtrTy,
2249 CGM.IntTy,
2250 CGM.Int64Ty->getPointerTo(),
2251 CGM.Int64Ty->getPointerTo(),
2252 CGM.Int64Ty,
2253 CGM.IntTy,
2254 CGM.IntTy,
2255 CGM.Int64Ty,
2256 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002257 auto *FnTy =
Alexey Bataev7292c292016-04-25 12:22:29 +00002258 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2259 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop");
2260 break;
2261 }
Alexey Bataev8b427062016-05-25 12:36:08 +00002262 case OMPRTL__kmpc_doacross_init: {
2263 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32
2264 // num_dims, struct kmp_dim *dims);
2265 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
2266 CGM.Int32Ty,
2267 CGM.Int32Ty,
2268 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002269 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002270 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2271 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init");
2272 break;
2273 }
2274 case OMPRTL__kmpc_doacross_fini: {
2275 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid);
2276 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002277 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002278 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2279 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini");
2280 break;
2281 }
2282 case OMPRTL__kmpc_doacross_post: {
2283 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64
2284 // *vec);
2285 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2286 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002287 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002288 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2289 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post");
2290 break;
2291 }
2292 case OMPRTL__kmpc_doacross_wait: {
2293 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64
2294 // *vec);
2295 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2296 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002297 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002298 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2299 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait");
2300 break;
2301 }
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002302 case OMPRTL__kmpc_task_reduction_init: {
2303 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void
2304 // *data);
2305 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002306 auto *FnTy =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002307 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2308 RTLFn =
2309 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init");
2310 break;
2311 }
2312 case OMPRTL__kmpc_task_reduction_get_th_data: {
2313 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
2314 // *d);
2315 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002316 auto *FnTy =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002317 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2318 RTLFn = CGM.CreateRuntimeFunction(
2319 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data");
2320 break;
2321 }
Alexey Bataev4f680db2019-03-19 16:41:16 +00002322 case OMPRTL__kmpc_alloc: {
Alexey Bataev6cf7b712019-04-08 19:06:42 +00002323 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t
2324 // al); omp_allocator_handle_t type is void *.
2325 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy};
Alexey Bataev4f680db2019-03-19 16:41:16 +00002326 auto *FnTy =
2327 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2328 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc");
2329 break;
2330 }
2331 case OMPRTL__kmpc_free: {
Alexey Bataev6cf7b712019-04-08 19:06:42 +00002332 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t
2333 // al); omp_allocator_handle_t type is void *.
2334 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataev4f680db2019-03-19 16:41:16 +00002335 auto *FnTy =
2336 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2337 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free");
2338 break;
2339 }
Alexey Bataev7bb33532019-01-07 21:30:43 +00002340 case OMPRTL__kmpc_push_target_tripcount: {
2341 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64
2342 // size);
2343 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty};
2344 llvm::FunctionType *FnTy =
2345 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2346 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount");
2347 break;
2348 }
Samuel Antaobed3c462015-10-02 16:14:20 +00002349 case OMPRTL__tgt_target: {
George Rokos63bc9d62017-11-21 18:25:12 +00002350 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002351 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Samuel Antaobed3c462015-10-02 16:14:20 +00002352 // *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002353 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaobed3c462015-10-02 16:14:20 +00002354 CGM.VoidPtrTy,
2355 CGM.Int32Ty,
2356 CGM.VoidPtrPtrTy,
2357 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002358 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002359 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002360 auto *FnTy =
Samuel Antaobed3c462015-10-02 16:14:20 +00002361 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2362 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
2363 break;
2364 }
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002365 case OMPRTL__tgt_target_nowait: {
2366 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002367 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes,
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002368 // int64_t *arg_types);
2369 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2370 CGM.VoidPtrTy,
2371 CGM.Int32Ty,
2372 CGM.VoidPtrPtrTy,
2373 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002374 CGM.Int64Ty->getPointerTo(),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002375 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002376 auto *FnTy =
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002377 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2378 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait");
2379 break;
2380 }
Samuel Antaob68e2db2016-03-03 16:20:23 +00002381 case OMPRTL__tgt_target_teams: {
George Rokos63bc9d62017-11-21 18:25:12 +00002382 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002383 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes,
George Rokos63bc9d62017-11-21 18:25:12 +00002384 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
2385 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaob68e2db2016-03-03 16:20:23 +00002386 CGM.VoidPtrTy,
2387 CGM.Int32Ty,
2388 CGM.VoidPtrPtrTy,
2389 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002390 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002391 CGM.Int64Ty->getPointerTo(),
Samuel Antaob68e2db2016-03-03 16:20:23 +00002392 CGM.Int32Ty,
2393 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002394 auto *FnTy =
Samuel Antaob68e2db2016-03-03 16:20:23 +00002395 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2396 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams");
2397 break;
2398 }
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002399 case OMPRTL__tgt_target_teams_nowait: {
2400 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void
Alexey Bataeva90fc662019-06-25 16:00:43 +00002401 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002402 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
2403 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2404 CGM.VoidPtrTy,
2405 CGM.Int32Ty,
2406 CGM.VoidPtrPtrTy,
2407 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002408 CGM.Int64Ty->getPointerTo(),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002409 CGM.Int64Ty->getPointerTo(),
2410 CGM.Int32Ty,
2411 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002412 auto *FnTy =
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002413 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2414 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait");
2415 break;
2416 }
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00002417 case OMPRTL__tgt_register_requires: {
2418 // Build void __tgt_register_requires(int64_t flags);
2419 llvm::Type *TypeParams[] = {CGM.Int64Ty};
2420 auto *FnTy =
2421 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2422 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires");
2423 break;
2424 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00002425 case OMPRTL__tgt_register_lib: {
2426 // Build void __tgt_register_lib(__tgt_bin_desc *desc);
2427 QualType ParamTy =
2428 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
2429 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002430 auto *FnTy =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002431 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2432 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib");
2433 break;
2434 }
2435 case OMPRTL__tgt_unregister_lib: {
2436 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc);
2437 QualType ParamTy =
2438 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
2439 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002440 auto *FnTy =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002441 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2442 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib");
2443 break;
2444 }
Samuel Antaodf158d52016-04-27 22:58:19 +00002445 case OMPRTL__tgt_target_data_begin: {
George Rokos63bc9d62017-11-21 18:25:12 +00002446 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002447 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002448 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaodf158d52016-04-27 22:58:19 +00002449 CGM.Int32Ty,
2450 CGM.VoidPtrPtrTy,
2451 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002452 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002453 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002454 auto *FnTy =
Samuel Antaodf158d52016-04-27 22:58:19 +00002455 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2456 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin");
2457 break;
2458 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002459 case OMPRTL__tgt_target_data_begin_nowait: {
2460 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002461 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002462 // *arg_types);
2463 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2464 CGM.Int32Ty,
2465 CGM.VoidPtrPtrTy,
2466 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002467 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002468 CGM.Int64Ty->getPointerTo()};
2469 auto *FnTy =
2470 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2471 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait");
2472 break;
2473 }
Samuel Antaodf158d52016-04-27 22:58:19 +00002474 case OMPRTL__tgt_target_data_end: {
George Rokos63bc9d62017-11-21 18:25:12 +00002475 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002476 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002477 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaodf158d52016-04-27 22:58:19 +00002478 CGM.Int32Ty,
2479 CGM.VoidPtrPtrTy,
2480 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002481 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002482 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002483 auto *FnTy =
Samuel Antaodf158d52016-04-27 22:58:19 +00002484 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2485 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end");
2486 break;
2487 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002488 case OMPRTL__tgt_target_data_end_nowait: {
2489 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002490 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002491 // *arg_types);
2492 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2493 CGM.Int32Ty,
2494 CGM.VoidPtrPtrTy,
2495 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002496 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002497 CGM.Int64Ty->getPointerTo()};
2498 auto *FnTy =
2499 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2500 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait");
2501 break;
2502 }
Samuel Antao8d2d7302016-05-26 18:30:22 +00002503 case OMPRTL__tgt_target_data_update: {
George Rokos63bc9d62017-11-21 18:25:12 +00002504 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002505 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002506 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antao8d2d7302016-05-26 18:30:22 +00002507 CGM.Int32Ty,
2508 CGM.VoidPtrPtrTy,
2509 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002510 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002511 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002512 auto *FnTy =
Samuel Antao8d2d7302016-05-26 18:30:22 +00002513 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2514 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update");
2515 break;
2516 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002517 case OMPRTL__tgt_target_data_update_nowait: {
2518 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002519 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002520 // *arg_types);
2521 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2522 CGM.Int32Ty,
2523 CGM.VoidPtrPtrTy,
2524 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002525 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002526 CGM.Int64Ty->getPointerTo()};
2527 auto *FnTy =
2528 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2529 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait");
2530 break;
2531 }
Michael Krused47b9432019-08-05 18:43:21 +00002532 case OMPRTL__tgt_mapper_num_components: {
2533 // Build int64_t __tgt_mapper_num_components(void *rt_mapper_handle);
2534 llvm::Type *TypeParams[] = {CGM.VoidPtrTy};
2535 auto *FnTy =
2536 llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false);
2537 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_mapper_num_components");
2538 break;
2539 }
2540 case OMPRTL__tgt_push_mapper_component: {
2541 // Build void __tgt_push_mapper_component(void *rt_mapper_handle, void
2542 // *base, void *begin, int64_t size, int64_t type);
2543 llvm::Type *TypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.VoidPtrTy,
2544 CGM.Int64Ty, CGM.Int64Ty};
2545 auto *FnTy =
2546 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2547 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_push_mapper_component");
2548 break;
2549 }
Alexey Bataev9959db52014-05-06 10:08:46 +00002550 }
Alexey Bataev50b3c952016-02-19 10:38:26 +00002551 assert(RTLFn && "Unable to find OpenMP runtime function");
Alexey Bataev9959db52014-05-06 10:08:46 +00002552 return RTLFn;
2553}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00002554
James Y Knight9871db02019-02-05 16:42:33 +00002555llvm::FunctionCallee
2556CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman21212e42015-03-13 10:38:23 +00002557 assert((IVSize == 32 || IVSize == 64) &&
2558 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002559 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
2560 : "__kmpc_for_static_init_4u")
2561 : (IVSigned ? "__kmpc_for_static_init_8"
2562 : "__kmpc_for_static_init_8u");
2563 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
2564 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
Alexander Musman21212e42015-03-13 10:38:23 +00002565 llvm::Type *TypeParams[] = {
2566 getIdentTyPointerTy(), // loc
2567 CGM.Int32Ty, // tid
2568 CGM.Int32Ty, // schedtype
2569 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
2570 PtrTy, // p_lower
2571 PtrTy, // p_upper
2572 PtrTy, // p_stride
2573 ITy, // incr
2574 ITy // chunk
2575 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002576 auto *FnTy =
Alexander Musman21212e42015-03-13 10:38:23 +00002577 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2578 return CGM.CreateRuntimeFunction(FnTy, Name);
2579}
2580
James Y Knight9871db02019-02-05 16:42:33 +00002581llvm::FunctionCallee
2582CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002583 assert((IVSize == 32 || IVSize == 64) &&
2584 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002585 StringRef Name =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002586 IVSize == 32
2587 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
2588 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002589 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
Alexander Musman92bdaab2015-03-12 13:37:50 +00002590 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
2591 CGM.Int32Ty, // tid
2592 CGM.Int32Ty, // schedtype
2593 ITy, // lower
2594 ITy, // upper
2595 ITy, // stride
2596 ITy // chunk
2597 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002598 auto *FnTy =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002599 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2600 return CGM.CreateRuntimeFunction(FnTy, Name);
2601}
2602
James Y Knight9871db02019-02-05 16:42:33 +00002603llvm::FunctionCallee
2604CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002605 assert((IVSize == 32 || IVSize == 64) &&
2606 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002607 StringRef Name =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002608 IVSize == 32
2609 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
2610 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
2611 llvm::Type *TypeParams[] = {
2612 getIdentTyPointerTy(), // loc
2613 CGM.Int32Ty, // tid
2614 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002615 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002616 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2617 return CGM.CreateRuntimeFunction(FnTy, Name);
2618}
2619
James Y Knight9871db02019-02-05 16:42:33 +00002620llvm::FunctionCallee
2621CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002622 assert((IVSize == 32 || IVSize == 64) &&
2623 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002624 StringRef Name =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002625 IVSize == 32
2626 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
2627 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002628 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
2629 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002630 llvm::Type *TypeParams[] = {
2631 getIdentTyPointerTy(), // loc
2632 CGM.Int32Ty, // tid
2633 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
2634 PtrTy, // p_lower
2635 PtrTy, // p_upper
2636 PtrTy // p_stride
2637 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002638 auto *FnTy =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002639 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2640 return CGM.CreateRuntimeFunction(FnTy, Name);
2641}
2642
Gheorghe-Teodor Bercea625f59d2019-08-01 21:15:58 +00002643/// Obtain information that uniquely identifies a target entry. This
2644/// consists of the file and device IDs as well as line number associated with
2645/// the relevant entry source location.
2646static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
2647 unsigned &DeviceID, unsigned &FileID,
2648 unsigned &LineNum) {
2649 SourceManager &SM = C.getSourceManager();
2650
2651 // The loc should be always valid and have a file ID (the user cannot use
2652 // #pragma directives in macros)
2653
2654 assert(Loc.isValid() && "Source location is expected to be always valid.");
2655
2656 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
2657 assert(PLoc.isValid() && "Source location is expected to be always valid.");
2658
2659 llvm::sys::fs::UniqueID ID;
2660 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
2661 SM.getDiagnostics().Report(diag::err_cannot_open_file)
2662 << PLoc.getFilename() << EC.message();
2663
2664 DeviceID = ID.getDevice();
2665 FileID = ID.getFile();
2666 LineNum = PLoc.getLine();
2667}
2668
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002669Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) {
Alexey Bataev03f270c2018-03-30 18:31:07 +00002670 if (CGM.getLangOpts().OpenMPSimd)
2671 return Address::invalid();
Alexey Bataev92327c52018-03-26 16:40:55 +00002672 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00002673 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002674 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link ||
2675 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
2676 HasRequiresUnifiedSharedMemory))) {
Alexey Bataev92327c52018-03-26 16:40:55 +00002677 SmallString<64> PtrName;
2678 {
2679 llvm::raw_svector_ostream OS(PtrName);
Gheorghe-Teodor Bercea625f59d2019-08-01 21:15:58 +00002680 OS << CGM.getMangledName(GlobalDecl(VD));
2681 if (!VD->isExternallyVisible()) {
2682 unsigned DeviceID, FileID, Line;
2683 getTargetEntryUniqueInfo(CGM.getContext(),
2684 VD->getCanonicalDecl()->getBeginLoc(),
2685 DeviceID, FileID, Line);
2686 OS << llvm::format("_%x", FileID);
2687 }
2688 OS << "_decl_tgt_ref_ptr";
Alexey Bataev92327c52018-03-26 16:40:55 +00002689 }
2690 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName);
2691 if (!Ptr) {
2692 QualType PtrTy = CGM.getContext().getPointerType(VD->getType());
2693 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy),
2694 PtrName);
Gheorghe-Teodor Bercea625f59d2019-08-01 21:15:58 +00002695
2696 auto *GV = cast<llvm::GlobalVariable>(Ptr);
2697 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
2698
2699 if (!CGM.getLangOpts().OpenMPIsDevice)
Alexey Bataev03f270c2018-03-30 18:31:07 +00002700 GV->setInitializer(CGM.GetAddrOfGlobal(VD));
Alexey Bataev03f270c2018-03-30 18:31:07 +00002701 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr));
Alexey Bataev92327c52018-03-26 16:40:55 +00002702 }
2703 return Address(Ptr, CGM.getContext().getDeclAlign(VD));
2704 }
2705 return Address::invalid();
2706}
2707
Alexey Bataev97720002014-11-11 04:05:39 +00002708llvm::Constant *
2709CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002710 assert(!CGM.getLangOpts().OpenMPUseTLS ||
2711 !CGM.getContext().getTargetInfo().isTLSSupported());
Alexey Bataev97720002014-11-11 04:05:39 +00002712 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev18fa2322018-05-02 14:20:50 +00002713 std::string Suffix = getName({"cache", ""});
2714 return getOrCreateInternalVariable(
2715 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix));
Alexey Bataev97720002014-11-11 04:05:39 +00002716}
2717
John McCall7f416cc2015-09-08 08:05:57 +00002718Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
2719 const VarDecl *VD,
2720 Address VDAddr,
2721 SourceLocation Loc) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002722 if (CGM.getLangOpts().OpenMPUseTLS &&
2723 CGM.getContext().getTargetInfo().isTLSSupported())
2724 return VDAddr;
2725
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002726 llvm::Type *VarTy = VDAddr.getElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002727 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00002728 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
2729 CGM.Int8PtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00002730 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
2731 getOrCreateThreadPrivateCache(VD)};
John McCall7f416cc2015-09-08 08:05:57 +00002732 return Address(CGF.EmitRuntimeCall(
2733 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
2734 VDAddr.getAlignment());
Alexey Bataev97720002014-11-11 04:05:39 +00002735}
2736
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002737void CGOpenMPRuntime::emitThreadPrivateVarInit(
John McCall7f416cc2015-09-08 08:05:57 +00002738 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
Alexey Bataev97720002014-11-11 04:05:39 +00002739 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
2740 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
2741 // library.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002742 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002743 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +00002744 OMPLoc);
2745 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
2746 // to register constructor/destructor for variable.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002747 llvm::Value *Args[] = {
2748 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy),
2749 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +00002750 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002751 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +00002752}
2753
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002754llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
John McCall7f416cc2015-09-08 08:05:57 +00002755 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
Alexey Bataev97720002014-11-11 04:05:39 +00002756 bool PerformInit, CodeGenFunction *CGF) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002757 if (CGM.getLangOpts().OpenMPUseTLS &&
2758 CGM.getContext().getTargetInfo().isTLSSupported())
2759 return nullptr;
2760
Alexey Bataev97720002014-11-11 04:05:39 +00002761 VD = VD->getDefinition(CGM.getContext());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00002762 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) {
Alexey Bataev97720002014-11-11 04:05:39 +00002763 QualType ASTTy = VD->getType();
2764
2765 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002766 const Expr *Init = VD->getAnyInitializer();
Alexey Bataev97720002014-11-11 04:05:39 +00002767 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
2768 // Generate function that re-emits the declaration's initializer into the
2769 // threadprivate copy of the variable VD
2770 CodeGenFunction CtorCGF(CGM);
2771 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002772 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
2773 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
Alexey Bataev56223232017-06-09 13:40:18 +00002774 ImplicitParamDecl::Other);
Alexey Bataev97720002014-11-11 04:05:39 +00002775 Args.push_back(&Dst);
2776
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002777 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
John McCallc56a8b32016-03-11 04:30:31 +00002778 CGM.getContext().VoidPtrTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002779 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002780 std::string Name = getName({"__kmpc_global_ctor_", ""});
2781 llvm::Function *Fn =
2782 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002783 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002784 Args, Loc, Loc);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002785 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002786 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00002787 CGM.getContext().VoidPtrTy, Dst.getLocation());
John McCall7f416cc2015-09-08 08:05:57 +00002788 Address Arg = Address(ArgVal, VDAddr.getAlignment());
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002789 Arg = CtorCGF.Builder.CreateElementBitCast(
2790 Arg, CtorCGF.ConvertTypeForMem(ASTTy));
Alexey Bataev97720002014-11-11 04:05:39 +00002791 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
2792 /*IsInitializer=*/true);
2793 ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002794 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00002795 CGM.getContext().VoidPtrTy, Dst.getLocation());
2796 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
2797 CtorCGF.FinishFunction();
2798 Ctor = Fn;
2799 }
2800 if (VD->getType().isDestructedType() != QualType::DK_none) {
2801 // Generate function that emits destructor call for the threadprivate copy
2802 // of the variable VD
2803 CodeGenFunction DtorCGF(CGM);
2804 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002805 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
2806 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
Alexey Bataev56223232017-06-09 13:40:18 +00002807 ImplicitParamDecl::Other);
Alexey Bataev97720002014-11-11 04:05:39 +00002808 Args.push_back(&Dst);
2809
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002810 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
John McCallc56a8b32016-03-11 04:30:31 +00002811 CGM.getContext().VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002812 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002813 std::string Name = getName({"__kmpc_global_dtor_", ""});
2814 llvm::Function *Fn =
2815 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
Adrian Prantl1858c662016-04-24 22:22:29 +00002816 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
Alexey Bataev97720002014-11-11 04:05:39 +00002817 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002818 Loc, Loc);
Adrian Prantl1858c662016-04-24 22:22:29 +00002819 // Create a scope with an artificial location for the body of this function.
2820 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002821 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar(
Alexey Bataev97720002014-11-11 04:05:39 +00002822 DtorCGF.GetAddrOfLocalVar(&Dst),
John McCall7f416cc2015-09-08 08:05:57 +00002823 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
2824 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
Alexey Bataev97720002014-11-11 04:05:39 +00002825 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
2826 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
2827 DtorCGF.FinishFunction();
2828 Dtor = Fn;
2829 }
2830 // Do not emit init function if it is not required.
2831 if (!Ctor && !Dtor)
2832 return nullptr;
2833
2834 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002835 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
2836 /*isVarArg=*/false)
2837 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002838 // Copying constructor for the threadprivate variable.
2839 // Must be NULL - reserved by runtime, but currently it requires that this
2840 // parameter is always NULL. Otherwise it fires assertion.
2841 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
2842 if (Ctor == nullptr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002843 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
2844 /*isVarArg=*/false)
2845 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002846 Ctor = llvm::Constant::getNullValue(CtorTy);
2847 }
2848 if (Dtor == nullptr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002849 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
2850 /*isVarArg=*/false)
2851 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002852 Dtor = llvm::Constant::getNullValue(DtorTy);
2853 }
2854 if (!CGF) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002855 auto *InitFunctionTy =
Alexey Bataev97720002014-11-11 04:05:39 +00002856 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002857 std::string Name = getName({"__omp_threadprivate_init_", ""});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002858 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction(
Alexey Bataev18fa2322018-05-02 14:20:50 +00002859 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction());
Alexey Bataev97720002014-11-11 04:05:39 +00002860 CodeGenFunction InitCGF(CGM);
2861 FunctionArgList ArgList;
2862 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
2863 CGM.getTypes().arrangeNullaryFunction(), ArgList,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002864 Loc, Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002865 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002866 InitCGF.FinishFunction();
2867 return InitFunction;
2868 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002869 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002870 }
2871 return nullptr;
2872}
2873
Alexey Bataev34f8a702018-03-28 14:28:54 +00002874bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD,
2875 llvm::GlobalVariable *Addr,
2876 bool PerformInit) {
Alexey Bataev36724b72019-10-03 16:46:49 +00002877 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
2878 !CGM.getLangOpts().OpenMPIsDevice)
Alexey Bataev4db9dc62019-09-23 15:53:51 +00002879 return false;
Alexey Bataev34f8a702018-03-28 14:28:54 +00002880 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00002881 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002882 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
2883 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
2884 HasRequiresUnifiedSharedMemory))
Alexey Bataevd01b7492018-08-15 19:45:12 +00002885 return CGM.getLangOpts().OpenMPIsDevice;
Alexey Bataev34f8a702018-03-28 14:28:54 +00002886 VD = VD->getDefinition(CGM.getContext());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00002887 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second)
Alexey Bataev34f8a702018-03-28 14:28:54 +00002888 return CGM.getLangOpts().OpenMPIsDevice;
2889
2890 QualType ASTTy = VD->getType();
2891
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002892 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc();
Alexey Bataev34f8a702018-03-28 14:28:54 +00002893 // Produce the unique prefix to identify the new target regions. We use
2894 // the source location of the variable declaration which we know to not
2895 // conflict with any target region.
2896 unsigned DeviceID;
2897 unsigned FileID;
2898 unsigned Line;
2899 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line);
2900 SmallString<128> Buffer, Out;
2901 {
2902 llvm::raw_svector_ostream OS(Buffer);
2903 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID)
2904 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
2905 }
2906
2907 const Expr *Init = VD->getAnyInitializer();
2908 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
2909 llvm::Constant *Ctor;
2910 llvm::Constant *ID;
2911 if (CGM.getLangOpts().OpenMPIsDevice) {
2912 // Generate function that re-emits the declaration's initializer into
2913 // the threadprivate copy of the variable VD
2914 CodeGenFunction CtorCGF(CGM);
2915
2916 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2917 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2918 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
2919 FTy, Twine(Buffer, "_ctor"), FI, Loc);
2920 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF);
2921 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
2922 FunctionArgList(), Loc, Loc);
2923 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF);
2924 CtorCGF.EmitAnyExprToMem(Init,
2925 Address(Addr, CGM.getContext().getDeclAlign(VD)),
2926 Init->getType().getQualifiers(),
2927 /*IsInitializer=*/true);
2928 CtorCGF.FinishFunction();
2929 Ctor = Fn;
2930 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
Alexey Bataeve253f2f2018-05-09 14:15:18 +00002931 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor));
Alexey Bataev34f8a702018-03-28 14:28:54 +00002932 } else {
2933 Ctor = new llvm::GlobalVariable(
2934 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
2935 llvm::GlobalValue::PrivateLinkage,
2936 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor"));
2937 ID = Ctor;
2938 }
2939
2940 // Register the information for the entry associated with the constructor.
2941 Out.clear();
2942 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
2943 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor,
Alexey Bataev03f270c2018-03-30 18:31:07 +00002944 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor);
Alexey Bataev34f8a702018-03-28 14:28:54 +00002945 }
2946 if (VD->getType().isDestructedType() != QualType::DK_none) {
2947 llvm::Constant *Dtor;
2948 llvm::Constant *ID;
2949 if (CGM.getLangOpts().OpenMPIsDevice) {
2950 // Generate function that emits destructor call for the threadprivate
2951 // copy of the variable VD
2952 CodeGenFunction DtorCGF(CGM);
2953
2954 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2955 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2956 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
2957 FTy, Twine(Buffer, "_dtor"), FI, Loc);
2958 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
2959 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
2960 FunctionArgList(), Loc, Loc);
2961 // Create a scope with an artificial location for the body of this
2962 // function.
2963 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
2964 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)),
2965 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()),
2966 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
2967 DtorCGF.FinishFunction();
2968 Dtor = Fn;
2969 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
Alexey Bataeve253f2f2018-05-09 14:15:18 +00002970 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor));
Alexey Bataev34f8a702018-03-28 14:28:54 +00002971 } else {
2972 Dtor = new llvm::GlobalVariable(
2973 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
2974 llvm::GlobalValue::PrivateLinkage,
2975 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor"));
2976 ID = Dtor;
2977 }
2978 // Register the information for the entry associated with the destructor.
2979 Out.clear();
2980 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
2981 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor,
Alexey Bataev03f270c2018-03-30 18:31:07 +00002982 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor);
Alexey Bataev34f8a702018-03-28 14:28:54 +00002983 }
2984 return CGM.getLangOpts().OpenMPIsDevice;
2985}
2986
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002987Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
2988 QualType VarType,
2989 StringRef Name) {
Alexey Bataev18fa2322018-05-02 14:20:50 +00002990 std::string Suffix = getName({"artificial", ""});
2991 std::string CacheSuffix = getName({"cache", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002992 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002993 llvm::Value *GAddr =
2994 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002995 llvm::Value *Args[] = {
2996 emitUpdateLocation(CGF, SourceLocation()),
2997 getThreadID(CGF, SourceLocation()),
2998 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy),
2999 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00003000 /*isSigned=*/false),
Alexey Bataev18fa2322018-05-02 14:20:50 +00003001 getOrCreateInternalVariable(
3002 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))};
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003003 return Address(
3004 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3005 CGF.EmitRuntimeCall(
3006 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
3007 VarLVType->getPointerTo(/*AddrSpace=*/0)),
3008 CGM.getPointerAlign());
3009}
3010
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +00003011void CGOpenMPRuntime::emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
3012 const RegionCodeGenTy &ThenGen,
3013 const RegionCodeGenTy &ElseGen) {
Alexey Bataev1d677132015-04-22 13:57:31 +00003014 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
3015
3016 // If the condition constant folds and can be elided, try to avoid emitting
3017 // the condition and the dead arm of the if/else.
3018 bool CondConstant;
3019 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003020 if (CondConstant)
Alexey Bataev1d677132015-04-22 13:57:31 +00003021 ThenGen(CGF);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003022 else
Alexey Bataev1d677132015-04-22 13:57:31 +00003023 ElseGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00003024 return;
3025 }
3026
3027 // Otherwise, the condition did not fold, or we couldn't elide it. Just
3028 // emit the conditional branch.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003029 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then");
3030 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else");
3031 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end");
Alexey Bataev1d677132015-04-22 13:57:31 +00003032 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
3033
3034 // Emit the 'then' code.
3035 CGF.EmitBlock(ThenBlock);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003036 ThenGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00003037 CGF.EmitBranch(ContBlock);
3038 // Emit the 'else' code if present.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003039 // There is no need to emit line number for unconditional branch.
3040 (void)ApplyDebugLocation::CreateEmpty(CGF);
3041 CGF.EmitBlock(ElseBlock);
3042 ElseGen(CGF);
3043 // There is no need to emit line number for unconditional branch.
3044 (void)ApplyDebugLocation::CreateEmpty(CGF);
3045 CGF.EmitBranch(ContBlock);
Alexey Bataev1d677132015-04-22 13:57:31 +00003046 // Emit the continuation block for code after the if.
3047 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003048}
3049
Alexey Bataev1d677132015-04-22 13:57:31 +00003050void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00003051 llvm::Function *OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00003052 ArrayRef<llvm::Value *> CapturedVars,
Alexey Bataev1d677132015-04-22 13:57:31 +00003053 const Expr *IfCond) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003054 if (!CGF.HaveInsertPoint())
3055 return;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003056 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003057 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF,
3058 PrePostActionTy &) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00003059 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003060 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev2377fe92015-09-10 08:12:02 +00003061 llvm::Value *Args[] = {
3062 RTLoc,
3063 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003064 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())};
Alexey Bataev2377fe92015-09-10 08:12:02 +00003065 llvm::SmallVector<llvm::Value *, 16> RealArgs;
3066 RealArgs.append(std::begin(Args), std::end(Args));
3067 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
3068
James Y Knight9871db02019-02-05 16:42:33 +00003069 llvm::FunctionCallee RTLFn =
3070 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call);
Alexey Bataev2377fe92015-09-10 08:12:02 +00003071 CGF.EmitRuntimeCall(RTLFn, RealArgs);
3072 };
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003073 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF,
3074 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003075 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
3076 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc);
Alexey Bataev1d677132015-04-22 13:57:31 +00003077 // Build calls:
3078 // __kmpc_serialized_parallel(&Loc, GTid);
3079 llvm::Value *Args[] = {RTLoc, ThreadID};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003080 CGF.EmitRuntimeCall(
3081 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +00003082
Alexey Bataev3e0f4f82019-10-17 14:36:43 +00003083 // OutlinedFn(&GTid, &zero_bound, CapturedStruct);
3084 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc);
Alexey Bataevf89cf212019-10-16 16:59:01 +00003085 Address ZeroAddrBound =
3086 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty,
3087 /*Name=*/".bound.zero.addr");
3088 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0));
Alexey Bataev2377fe92015-09-10 08:12:02 +00003089 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
Alexey Bataev8521ff62018-07-25 20:03:01 +00003090 // ThreadId for serialized parallels is 0.
Alexey Bataev3e0f4f82019-10-17 14:36:43 +00003091 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
Alexey Bataevf89cf212019-10-16 16:59:01 +00003092 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer());
Alexey Bataev2377fe92015-09-10 08:12:02 +00003093 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
Alexey Bataev3c595a62017-08-14 15:01:03 +00003094 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +00003095
Alexey Bataev1d677132015-04-22 13:57:31 +00003096 // __kmpc_end_serialized_parallel(&Loc, GTid);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003097 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID};
Alexey Bataev1d677132015-04-22 13:57:31 +00003098 CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003099 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel),
3100 EndArgs);
Alexey Bataev1d677132015-04-22 13:57:31 +00003101 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003102 if (IfCond) {
Alexey Bataev1d677132015-04-22 13:57:31 +00003103 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003104 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003105 RegionCodeGenTy ThenRCG(ThenGen);
3106 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00003107 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00003108}
3109
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00003110// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +00003111// thread-ID variable (it is passed in a first argument of the outlined function
3112// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
3113// regular serial code region, get thread ID by calling kmp_int32
3114// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
3115// return the address of that temp.
John McCall7f416cc2015-09-08 08:05:57 +00003116Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
3117 SourceLocation Loc) {
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003118 if (auto *OMPRegionInfo =
Alexey Bataevd74d0602014-10-13 06:02:40 +00003119 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003120 if (OMPRegionInfo->getThreadIDVariable())
Alexey Bataev62b63b12015-03-10 07:28:44 +00003121 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003122
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003123 llvm::Value *ThreadID = getThreadID(CGF, Loc);
3124 QualType Int32Ty =
Alexey Bataevd74d0602014-10-13 06:02:40 +00003125 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003126 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
Alexey Bataevd74d0602014-10-13 06:02:40 +00003127 CGF.EmitStoreOfScalar(ThreadID,
John McCall7f416cc2015-09-08 08:05:57 +00003128 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
Alexey Bataevd74d0602014-10-13 06:02:40 +00003129
3130 return ThreadIDTemp;
3131}
3132
Alexey Bataev1af5bd52019-03-05 17:47:18 +00003133llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable(
3134 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003135 SmallString<256> Buffer;
3136 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00003137 Out << Name;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003138 StringRef RuntimeName = Out.str();
Alexey Bataev43a919f2018-04-13 17:48:43 +00003139 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first;
David Blaikie13156b62014-11-19 03:06:06 +00003140 if (Elem.second) {
3141 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00003142 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00003143 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00003144 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003145
David Blaikie13156b62014-11-19 03:06:06 +00003146 return Elem.second = new llvm::GlobalVariable(
3147 CGM.getModule(), Ty, /*IsConstant*/ false,
3148 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
Alexey Bataev1af5bd52019-03-05 17:47:18 +00003149 Elem.first(), /*InsertBefore=*/nullptr,
3150 llvm::GlobalValue::NotThreadLocal, AddressSpace);
Alexey Bataev97720002014-11-11 04:05:39 +00003151}
3152
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003153llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev18fa2322018-05-02 14:20:50 +00003154 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str();
3155 std::string Name = getName({Prefix, "var"});
3156 return getOrCreateInternalVariable(KmpCriticalNameTy, Name);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003157}
3158
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003159namespace {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003160/// Common pre(post)-action for different OpenMP constructs.
3161class CommonActionTy final : public PrePostActionTy {
James Y Knight9871db02019-02-05 16:42:33 +00003162 llvm::FunctionCallee EnterCallee;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003163 ArrayRef<llvm::Value *> EnterArgs;
James Y Knight9871db02019-02-05 16:42:33 +00003164 llvm::FunctionCallee ExitCallee;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003165 ArrayRef<llvm::Value *> ExitArgs;
3166 bool Conditional;
3167 llvm::BasicBlock *ContBlock = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003168
3169public:
James Y Knight9871db02019-02-05 16:42:33 +00003170 CommonActionTy(llvm::FunctionCallee EnterCallee,
3171 ArrayRef<llvm::Value *> EnterArgs,
3172 llvm::FunctionCallee ExitCallee,
3173 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003174 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
3175 ExitArgs(ExitArgs), Conditional(Conditional) {}
3176 void Enter(CodeGenFunction &CGF) override {
3177 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs);
3178 if (Conditional) {
3179 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes);
3180 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
3181 ContBlock = CGF.createBasicBlock("omp_if.end");
3182 // Generate the branch (If-stmt)
3183 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
3184 CGF.EmitBlock(ThenBlock);
3185 }
Alexey Bataeva744ff52015-05-05 09:24:37 +00003186 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003187 void Done(CodeGenFunction &CGF) {
3188 // Emit the rest of blocks/branches
3189 CGF.EmitBranch(ContBlock);
3190 CGF.EmitBlock(ContBlock, true);
3191 }
3192 void Exit(CodeGenFunction &CGF) override {
3193 CGF.EmitRuntimeCall(ExitCallee, ExitArgs);
Alexey Bataev3e6124b2015-04-10 07:48:12 +00003194 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003195};
Hans Wennborg7eb54642015-09-10 17:07:54 +00003196} // anonymous namespace
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003197
3198void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
3199 StringRef CriticalName,
3200 const RegionCodeGenTy &CriticalOpGen,
Alexey Bataevfc57d162015-12-15 10:55:09 +00003201 SourceLocation Loc, const Expr *Hint) {
3202 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
Alexey Bataev75ddfab2014-12-01 11:32:38 +00003203 // CriticalOpGen();
3204 // __kmpc_end_critical(ident_t *, gtid, Lock);
3205 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev8ef31412015-12-18 07:58:25 +00003206 if (!CGF.HaveInsertPoint())
3207 return;
Alexey Bataevfc57d162015-12-15 10:55:09 +00003208 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3209 getCriticalRegionLock(CriticalName)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003210 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args),
3211 std::end(Args));
Alexey Bataevfc57d162015-12-15 10:55:09 +00003212 if (Hint) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003213 EnterArgs.push_back(CGF.Builder.CreateIntCast(
3214 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false));
3215 }
3216 CommonActionTy Action(
3217 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint
3218 : OMPRTL__kmpc_critical),
3219 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args);
3220 CriticalOpGen.setAction(Action);
Alexey Bataevfc57d162015-12-15 10:55:09 +00003221 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003222}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003223
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003224void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003225 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003226 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003227 if (!CGF.HaveInsertPoint())
3228 return;
Alexey Bataev8d690652014-12-04 07:23:53 +00003229 // if(__kmpc_master(ident_t *, gtid)) {
3230 // MasterOpGen();
3231 // __kmpc_end_master(ident_t *, gtid);
3232 // }
3233 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00003234 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003235 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args,
3236 createRuntimeFunction(OMPRTL__kmpc_end_master), Args,
3237 /*Conditional=*/true);
3238 MasterOpGen.setAction(Action);
3239 emitInlinedDirective(CGF, OMPD_master, MasterOpGen);
3240 Action.Done(CGF);
Alexey Bataev8d690652014-12-04 07:23:53 +00003241}
3242
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003243void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
3244 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003245 if (!CGF.HaveInsertPoint())
3246 return;
Alexey Bataev9f797f32015-02-05 05:57:51 +00003247 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
3248 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003249 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00003250 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003251 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00003252 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
3253 Region->emitUntiedSwitch(CGF);
Alexey Bataev9f797f32015-02-05 05:57:51 +00003254}
3255
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003256void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
3257 const RegionCodeGenTy &TaskgroupOpGen,
3258 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003259 if (!CGF.HaveInsertPoint())
3260 return;
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003261 // __kmpc_taskgroup(ident_t *, gtid);
3262 // TaskgroupOpGen();
3263 // __kmpc_end_taskgroup(ident_t *, gtid);
3264 // Prepare arguments and build a call to __kmpc_taskgroup
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003265 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
3266 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args,
3267 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
3268 Args);
3269 TaskgroupOpGen.setAction(Action);
3270 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003271}
3272
John McCall7f416cc2015-09-08 08:05:57 +00003273/// Given an array of pointers to variables, project the address of a
3274/// given variable.
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003275static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
3276 unsigned Index, const VarDecl *Var) {
John McCall7f416cc2015-09-08 08:05:57 +00003277 // Pull out the pointer to the variable.
James Y Knight751fe282019-02-09 22:22:28 +00003278 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index);
John McCall7f416cc2015-09-08 08:05:57 +00003279 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
3280
3281 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003282 Addr = CGF.Builder.CreateElementBitCast(
3283 Addr, CGF.ConvertTypeForMem(Var->getType()));
John McCall7f416cc2015-09-08 08:05:57 +00003284 return Addr;
3285}
3286
Alexey Bataeva63048e2015-03-23 06:18:07 +00003287static llvm::Value *emitCopyprivateCopyFunction(
Alexey Bataev420d45b2015-04-14 05:11:24 +00003288 CodeGenModule &CGM, llvm::Type *ArgsType,
3289 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003290 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps,
3291 SourceLocation Loc) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003292 ASTContext &C = CGM.getContext();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003293 // void copy_func(void *LHSArg, void *RHSArg);
3294 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003295 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3296 ImplicitParamDecl::Other);
3297 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3298 ImplicitParamDecl::Other);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003299 Args.push_back(&LHSArg);
3300 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003301 const auto &CGFI =
3302 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00003303 std::string Name =
3304 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"});
3305 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
3306 llvm::GlobalValue::InternalLinkage, Name,
3307 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00003308 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00003309 Fn->setDoesNotRecurse();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003310 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003311 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev420d45b2015-04-14 05:11:24 +00003312 // Dest = (void*[n])(LHSArg);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003313 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00003314 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3315 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
3316 ArgsType), CGF.getPointerAlign());
3317 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3318 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
3319 ArgsType), CGF.getPointerAlign());
Alexey Bataeva63048e2015-03-23 06:18:07 +00003320 // *(Type0*)Dst[0] = *(Type0*)Src[0];
3321 // *(Type1*)Dst[1] = *(Type1*)Src[1];
3322 // ...
3323 // *(Typen*)Dst[n] = *(Typen*)Src[n];
Alexey Bataeva63048e2015-03-23 06:18:07 +00003324 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003325 const auto *DestVar =
3326 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +00003327 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
3328
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003329 const auto *SrcVar =
3330 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +00003331 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
3332
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003333 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003334 QualType Type = VD->getType();
John McCall7f416cc2015-09-08 08:05:57 +00003335 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003336 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00003337 CGF.FinishFunction();
3338 return Fn;
3339}
3340
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003341void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003342 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00003343 SourceLocation Loc,
3344 ArrayRef<const Expr *> CopyprivateVars,
3345 ArrayRef<const Expr *> SrcExprs,
3346 ArrayRef<const Expr *> DstExprs,
3347 ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003348 if (!CGF.HaveInsertPoint())
3349 return;
Alexey Bataeva63048e2015-03-23 06:18:07 +00003350 assert(CopyprivateVars.size() == SrcExprs.size() &&
3351 CopyprivateVars.size() == DstExprs.size() &&
3352 CopyprivateVars.size() == AssignmentOps.size());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003353 ASTContext &C = CGM.getContext();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003354 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003355 // if(__kmpc_single(ident_t *, gtid)) {
3356 // SingleOpGen();
3357 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003358 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003359 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00003360 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3361 // <copy_func>, did_it);
3362
John McCall7f416cc2015-09-08 08:05:57 +00003363 Address DidIt = Address::invalid();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003364 if (!CopyprivateVars.empty()) {
3365 // int32 did_it = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003366 QualType KmpInt32Ty =
3367 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003368 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
John McCall7f416cc2015-09-08 08:05:57 +00003369 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003370 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003371 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00003372 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003373 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args,
3374 createRuntimeFunction(OMPRTL__kmpc_end_single), Args,
3375 /*Conditional=*/true);
3376 SingleOpGen.setAction(Action);
3377 emitInlinedDirective(CGF, OMPD_single, SingleOpGen);
3378 if (DidIt.isValid()) {
3379 // did_it = 1;
3380 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
3381 }
3382 Action.Done(CGF);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003383 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3384 // <copy_func>, did_it);
John McCall7f416cc2015-09-08 08:05:57 +00003385 if (DidIt.isValid()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00003386 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
Richard Smith772e2662019-10-04 01:25:59 +00003387 QualType CopyprivateArrayTy = C.getConstantArrayType(
3388 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
3389 /*IndexTypeQuals=*/0);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003390 // Create a list of all private variables for copyprivate.
John McCall7f416cc2015-09-08 08:05:57 +00003391 Address CopyprivateList =
Alexey Bataeva63048e2015-03-23 06:18:07 +00003392 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
3393 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +00003394 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I);
John McCall7f416cc2015-09-08 08:05:57 +00003395 CGF.Builder.CreateStore(
Alexey Bataeva63048e2015-03-23 06:18:07 +00003396 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00003397 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy),
3398 Elem);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003399 }
3400 // Build function that copies private values from single region to all other
3401 // threads in the corresponding parallel region.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003402 llvm::Value *CpyFn = emitCopyprivateCopyFunction(
Alexey Bataeva63048e2015-03-23 06:18:07 +00003403 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003404 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003405 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00003406 Address CL =
3407 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
3408 CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003409 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003410 llvm::Value *Args[] = {
3411 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
3412 getThreadID(CGF, Loc), // i32 <gtid>
Alexey Bataev66beaa92015-04-30 03:47:32 +00003413 BufSize, // size_t <buf_size>
John McCall7f416cc2015-09-08 08:05:57 +00003414 CL.getPointer(), // void *<copyprivate list>
Alexey Bataeva63048e2015-03-23 06:18:07 +00003415 CpyFn, // void (*) (void *, void *) <copy_func>
3416 DidItVal // i32 did_it
3417 };
3418 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
3419 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003420}
3421
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003422void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
3423 const RegionCodeGenTy &OrderedOpGen,
Alexey Bataev5f600d62015-09-29 03:48:57 +00003424 SourceLocation Loc, bool IsThreads) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003425 if (!CGF.HaveInsertPoint())
3426 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003427 // __kmpc_ordered(ident_t *, gtid);
3428 // OrderedOpGen();
3429 // __kmpc_end_ordered(ident_t *, gtid);
3430 // Prepare arguments and build a call to __kmpc_ordered
Alexey Bataev5f600d62015-09-29 03:48:57 +00003431 if (IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003432 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003433 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args,
3434 createRuntimeFunction(OMPRTL__kmpc_end_ordered),
3435 Args);
3436 OrderedOpGen.setAction(Action);
3437 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
3438 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003439 }
Alexey Bataev5f600d62015-09-29 03:48:57 +00003440 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003441}
3442
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003443unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) {
Alexey Bataev50b3c952016-02-19 10:38:26 +00003444 unsigned Flags;
3445 if (Kind == OMPD_for)
3446 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
3447 else if (Kind == OMPD_sections)
3448 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
3449 else if (Kind == OMPD_single)
3450 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
3451 else if (Kind == OMPD_barrier)
3452 Flags = OMP_IDENT_BARRIER_EXPL;
3453 else
3454 Flags = OMP_IDENT_BARRIER_IMPL;
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003455 return Flags;
3456}
3457
Alexey Bataevf6a53d62019-03-18 18:40:00 +00003458void CGOpenMPRuntime::getDefaultScheduleAndChunk(
3459 CodeGenFunction &CGF, const OMPLoopDirective &S,
3460 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const {
3461 // Check if the loop directive is actually a doacross loop directive. In this
3462 // case choose static, 1 schedule.
3463 if (llvm::any_of(
3464 S.getClausesOfKind<OMPOrderedClause>(),
3465 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) {
3466 ScheduleKind = OMPC_SCHEDULE_static;
3467 // Chunk size is 1 in this case.
3468 llvm::APInt ChunkSize(32, 1);
3469 ChunkExpr = IntegerLiteral::Create(
3470 CGF.getContext(), ChunkSize,
3471 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
3472 SourceLocation());
3473 }
3474}
3475
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003476void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
3477 OpenMPDirectiveKind Kind, bool EmitChecks,
3478 bool ForceSimpleCall) {
3479 if (!CGF.HaveInsertPoint())
3480 return;
3481 // Build call __kmpc_cancel_barrier(loc, thread_id);
3482 // Build call __kmpc_barrier(loc, thread_id);
3483 unsigned Flags = getDefaultFlagsForBarriers(Kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003484 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
3485 // thread_id);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003486 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
3487 getThreadID(CGF, Loc)};
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003488 if (auto *OMPRegionInfo =
3489 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00003490 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003491 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003492 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev25e5b442015-09-15 12:52:43 +00003493 if (EmitChecks) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003494 // if (__kmpc_cancel_barrier()) {
3495 // exit from construct;
3496 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003497 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
3498 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
3499 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003500 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
3501 CGF.EmitBlock(ExitBB);
3502 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003503 CodeGenFunction::JumpDest CancelDestination =
Alexey Bataev25e5b442015-09-15 12:52:43 +00003504 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003505 CGF.EmitBranchThroughCleanup(CancelDestination);
3506 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
3507 }
3508 return;
3509 }
3510 }
3511 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003512}
3513
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003514/// Map the OpenMP loop schedule to the runtime enumeration.
Alexander Musmanc6388682014-12-15 07:07:06 +00003515static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003516 bool Chunked, bool Ordered) {
Alexander Musmanc6388682014-12-15 07:07:06 +00003517 switch (ScheduleKind) {
3518 case OMPC_SCHEDULE_static:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003519 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
3520 : (Ordered ? OMP_ord_static : OMP_sch_static);
Alexander Musmanc6388682014-12-15 07:07:06 +00003521 case OMPC_SCHEDULE_dynamic:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003522 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00003523 case OMPC_SCHEDULE_guided:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003524 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00003525 case OMPC_SCHEDULE_runtime:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003526 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
3527 case OMPC_SCHEDULE_auto:
3528 return Ordered ? OMP_ord_auto : OMP_sch_auto;
Alexander Musmanc6388682014-12-15 07:07:06 +00003529 case OMPC_SCHEDULE_unknown:
3530 assert(!Chunked && "chunk was specified but schedule kind not known");
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003531 return Ordered ? OMP_ord_static : OMP_sch_static;
Alexander Musmanc6388682014-12-15 07:07:06 +00003532 }
3533 llvm_unreachable("Unexpected runtime schedule");
3534}
3535
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003536/// Map the OpenMP distribute schedule to the runtime enumeration.
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003537static OpenMPSchedType
3538getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
3539 // only static is allowed for dist_schedule
3540 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
3541}
3542
Alexander Musmanc6388682014-12-15 07:07:06 +00003543bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
3544 bool Chunked) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003545 OpenMPSchedType Schedule =
3546 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
Alexander Musmanc6388682014-12-15 07:07:06 +00003547 return Schedule == OMP_sch_static;
3548}
3549
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003550bool CGOpenMPRuntime::isStaticNonchunked(
3551 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003552 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003553 return Schedule == OMP_dist_sch_static;
3554}
3555
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00003556bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind,
3557 bool Chunked) const {
3558 OpenMPSchedType Schedule =
3559 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
3560 return Schedule == OMP_sch_static_chunked;
3561}
3562
3563bool CGOpenMPRuntime::isStaticChunked(
3564 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
3565 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
3566 return Schedule == OMP_dist_sch_static_chunked;
3567}
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003568
Alexander Musmandf7a8e22015-01-22 08:49:35 +00003569bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003570 OpenMPSchedType Schedule =
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003571 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00003572 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
3573 return Schedule != OMP_sch_static;
3574}
3575
Alexey Bataev07a3b592019-08-23 19:52:05 +00003576static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003577 OpenMPScheduleClauseModifier M1,
3578 OpenMPScheduleClauseModifier M2) {
Alexey Bataev6cff6242016-05-30 13:05:14 +00003579 int Modifier = 0;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003580 switch (M1) {
3581 case OMPC_SCHEDULE_MODIFIER_monotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003582 Modifier = OMP_sch_modifier_monotonic;
3583 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003584 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003585 Modifier = OMP_sch_modifier_nonmonotonic;
3586 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003587 case OMPC_SCHEDULE_MODIFIER_simd:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003588 if (Schedule == OMP_sch_static_chunked)
3589 Schedule = OMP_sch_static_balanced_chunked;
3590 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003591 case OMPC_SCHEDULE_MODIFIER_last:
3592 case OMPC_SCHEDULE_MODIFIER_unknown:
3593 break;
3594 }
3595 switch (M2) {
3596 case OMPC_SCHEDULE_MODIFIER_monotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003597 Modifier = OMP_sch_modifier_monotonic;
3598 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003599 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003600 Modifier = OMP_sch_modifier_nonmonotonic;
3601 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003602 case OMPC_SCHEDULE_MODIFIER_simd:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003603 if (Schedule == OMP_sch_static_chunked)
3604 Schedule = OMP_sch_static_balanced_chunked;
3605 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003606 case OMPC_SCHEDULE_MODIFIER_last:
3607 case OMPC_SCHEDULE_MODIFIER_unknown:
3608 break;
3609 }
Alexey Bataev07a3b592019-08-23 19:52:05 +00003610 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription.
3611 // If the static schedule kind is specified or if the ordered clause is
3612 // specified, and if the nonmonotonic modifier is not specified, the effect is
3613 // as if the monotonic modifier is specified. Otherwise, unless the monotonic
3614 // modifier is specified, the effect is as if the nonmonotonic modifier is
3615 // specified.
3616 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) {
3617 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
3618 Schedule == OMP_sch_static_balanced_chunked ||
Alexey Bataevc3eded02019-11-18 11:13:08 -05003619 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
3620 Schedule == OMP_dist_sch_static_chunked ||
3621 Schedule == OMP_dist_sch_static))
Alexey Bataev07a3b592019-08-23 19:52:05 +00003622 Modifier = OMP_sch_modifier_nonmonotonic;
3623 }
Alexey Bataev6cff6242016-05-30 13:05:14 +00003624 return Schedule | Modifier;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003625}
3626
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003627void CGOpenMPRuntime::emitForDispatchInit(
3628 CodeGenFunction &CGF, SourceLocation Loc,
3629 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
3630 bool Ordered, const DispatchRTInput &DispatchValues) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003631 if (!CGF.HaveInsertPoint())
3632 return;
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003633 OpenMPSchedType Schedule = getRuntimeSchedule(
3634 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered);
John McCall7f416cc2015-09-08 08:05:57 +00003635 assert(Ordered ||
3636 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
Alexey Bataev6cff6242016-05-30 13:05:14 +00003637 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
3638 Schedule != OMP_sch_static_balanced_chunked));
John McCall7f416cc2015-09-08 08:05:57 +00003639 // Call __kmpc_dispatch_init(
3640 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
3641 // kmp_int[32|64] lower, kmp_int[32|64] upper,
3642 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00003643
John McCall7f416cc2015-09-08 08:05:57 +00003644 // If the Chunk was not specified in the clause - use default value 1.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003645 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk
3646 : CGF.Builder.getIntN(IVSize, 1);
John McCall7f416cc2015-09-08 08:05:57 +00003647 llvm::Value *Args[] = {
Alexey Bataev07a3b592019-08-23 19:52:05 +00003648 emitUpdateLocation(CGF, Loc),
3649 getThreadID(CGF, Loc),
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003650 CGF.Builder.getInt32(addMonoNonMonoModifier(
Alexey Bataev07a3b592019-08-23 19:52:05 +00003651 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type
3652 DispatchValues.LB, // Lower
3653 DispatchValues.UB, // Upper
3654 CGF.Builder.getIntN(IVSize, 1), // Stride
3655 Chunk // Chunk
John McCall7f416cc2015-09-08 08:05:57 +00003656 };
3657 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
3658}
3659
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003660static void emitForStaticInitCall(
3661 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
James Y Knight9871db02019-02-05 16:42:33 +00003662 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003663 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003664 const CGOpenMPRuntime::StaticRTInput &Values) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003665 if (!CGF.HaveInsertPoint())
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003666 return;
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003667
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003668 assert(!Values.Ordered);
3669 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
3670 Schedule == OMP_sch_static_balanced_chunked ||
3671 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
3672 Schedule == OMP_dist_sch_static ||
3673 Schedule == OMP_dist_sch_static_chunked);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003674
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003675 // Call __kmpc_for_static_init(
3676 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
3677 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
3678 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
3679 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
3680 llvm::Value *Chunk = Values.Chunk;
3681 if (Chunk == nullptr) {
3682 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
3683 Schedule == OMP_dist_sch_static) &&
3684 "expected static non-chunked schedule");
3685 // If the Chunk was not specified in the clause - use default value 1.
3686 Chunk = CGF.Builder.getIntN(Values.IVSize, 1);
3687 } else {
3688 assert((Schedule == OMP_sch_static_chunked ||
3689 Schedule == OMP_sch_static_balanced_chunked ||
3690 Schedule == OMP_ord_static_chunked ||
3691 Schedule == OMP_dist_sch_static_chunked) &&
3692 "expected static chunked schedule");
3693 }
3694 llvm::Value *Args[] = {
3695 UpdateLocation,
3696 ThreadId,
Alexey Bataev07a3b592019-08-23 19:52:05 +00003697 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003698 M2)), // Schedule type
3699 Values.IL.getPointer(), // &isLastIter
3700 Values.LB.getPointer(), // &LB
3701 Values.UB.getPointer(), // &UB
3702 Values.ST.getPointer(), // &Stride
3703 CGF.Builder.getIntN(Values.IVSize, 1), // Incr
3704 Chunk // Chunk
3705 };
3706 CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003707}
3708
John McCall7f416cc2015-09-08 08:05:57 +00003709void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
3710 SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003711 OpenMPDirectiveKind DKind,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003712 const OpenMPScheduleTy &ScheduleKind,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003713 const StaticRTInput &Values) {
3714 OpenMPSchedType ScheduleNum = getRuntimeSchedule(
3715 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered);
3716 assert(isOpenMPWorksharingDirective(DKind) &&
3717 "Expected loop-based or sections-based directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003718 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003719 isOpenMPLoopDirective(DKind)
3720 ? OMP_IDENT_WORK_LOOP
3721 : OMP_IDENT_WORK_SECTIONS);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003722 llvm::Value *ThreadId = getThreadID(CGF, Loc);
James Y Knight9871db02019-02-05 16:42:33 +00003723 llvm::FunctionCallee StaticInitFunction =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003724 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003725 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003726 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003727}
John McCall7f416cc2015-09-08 08:05:57 +00003728
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003729void CGOpenMPRuntime::emitDistributeStaticInit(
3730 CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003731 OpenMPDistScheduleClauseKind SchedKind,
3732 const CGOpenMPRuntime::StaticRTInput &Values) {
3733 OpenMPSchedType ScheduleNum =
3734 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003735 llvm::Value *UpdatedLocation =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003736 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003737 llvm::Value *ThreadId = getThreadID(CGF, Loc);
James Y Knight9871db02019-02-05 16:42:33 +00003738 llvm::FunctionCallee StaticInitFunction =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003739 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003740 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
3741 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003742 OMPC_SCHEDULE_MODIFIER_unknown, Values);
Alexander Musmanc6388682014-12-15 07:07:06 +00003743}
3744
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003745void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
Alexey Bataevf43f7142017-09-06 16:17:35 +00003746 SourceLocation Loc,
3747 OpenMPDirectiveKind DKind) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003748 if (!CGF.HaveInsertPoint())
3749 return;
Alexander Musmanc6388682014-12-15 07:07:06 +00003750 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataevf43f7142017-09-06 16:17:35 +00003751 llvm::Value *Args[] = {
3752 emitUpdateLocation(CGF, Loc,
3753 isOpenMPDistributeDirective(DKind)
3754 ? OMP_IDENT_WORK_DISTRIBUTE
3755 : isOpenMPLoopDirective(DKind)
3756 ? OMP_IDENT_WORK_LOOP
3757 : OMP_IDENT_WORK_SECTIONS),
3758 getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003759 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
3760 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00003761}
3762
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003763void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
3764 SourceLocation Loc,
3765 unsigned IVSize,
3766 bool IVSigned) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003767 if (!CGF.HaveInsertPoint())
3768 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003769 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00003770 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003771 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
3772}
3773
Alexander Musman92bdaab2015-03-12 13:37:50 +00003774llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
3775 SourceLocation Loc, unsigned IVSize,
John McCall7f416cc2015-09-08 08:05:57 +00003776 bool IVSigned, Address IL,
3777 Address LB, Address UB,
3778 Address ST) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00003779 // Call __kmpc_dispatch_next(
3780 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
3781 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
3782 // kmp_int[32|64] *p_stride);
3783 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00003784 emitUpdateLocation(CGF, Loc),
3785 getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00003786 IL.getPointer(), // &isLastIter
3787 LB.getPointer(), // &Lower
3788 UB.getPointer(), // &Upper
3789 ST.getPointer() // &Stride
Alexander Musman92bdaab2015-03-12 13:37:50 +00003790 };
3791 llvm::Value *Call =
3792 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
3793 return CGF.EmitScalarConversion(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003794 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00003795 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00003796}
3797
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003798void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
3799 llvm::Value *NumThreads,
3800 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003801 if (!CGF.HaveInsertPoint())
3802 return;
Alexey Bataevb2059782014-10-13 08:23:51 +00003803 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
3804 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003805 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00003806 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003807 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
3808 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00003809}
3810
Alexey Bataev7f210c62015-06-18 13:40:03 +00003811void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
3812 OpenMPProcBindClauseKind ProcBind,
3813 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003814 if (!CGF.HaveInsertPoint())
3815 return;
Alexey Bataev7f210c62015-06-18 13:40:03 +00003816 // Constants for proc bind value accepted by the runtime.
3817 enum ProcBindTy {
3818 ProcBindFalse = 0,
3819 ProcBindTrue,
3820 ProcBindMaster,
3821 ProcBindClose,
3822 ProcBindSpread,
3823 ProcBindIntel,
3824 ProcBindDefault
3825 } RuntimeProcBind;
3826 switch (ProcBind) {
3827 case OMPC_PROC_BIND_master:
3828 RuntimeProcBind = ProcBindMaster;
3829 break;
3830 case OMPC_PROC_BIND_close:
3831 RuntimeProcBind = ProcBindClose;
3832 break;
3833 case OMPC_PROC_BIND_spread:
3834 RuntimeProcBind = ProcBindSpread;
3835 break;
3836 case OMPC_PROC_BIND_unknown:
3837 llvm_unreachable("Unsupported proc_bind value.");
3838 }
3839 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
3840 llvm::Value *Args[] = {
3841 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3842 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
3843 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
3844}
3845
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003846void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
3847 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003848 if (!CGF.HaveInsertPoint())
3849 return;
Alexey Bataevd76df6d2015-02-24 12:55:09 +00003850 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003851 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
3852 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00003853}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003854
Alexey Bataev62b63b12015-03-10 07:28:44 +00003855namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003856/// Indexes of fields for type kmp_task_t.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003857enum KmpTaskTFields {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003858 /// List of shared variables.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003859 KmpTaskTShareds,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003860 /// Task routine.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003861 KmpTaskTRoutine,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003862 /// Partition id for the untied tasks.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003863 KmpTaskTPartId,
Alexey Bataevad537bb2016-05-30 09:06:50 +00003864 /// Function with call of destructors for private variables.
3865 Data1,
3866 /// Task priority.
3867 Data2,
Alexey Bataev7292c292016-04-25 12:22:29 +00003868 /// (Taskloops only) Lower bound.
3869 KmpTaskTLowerBound,
3870 /// (Taskloops only) Upper bound.
3871 KmpTaskTUpperBound,
3872 /// (Taskloops only) Stride.
3873 KmpTaskTStride,
3874 /// (Taskloops only) Is last iteration flag.
3875 KmpTaskTLastIter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003876 /// (Taskloops only) Reduction data.
3877 KmpTaskTReductions,
Alexey Bataev62b63b12015-03-10 07:28:44 +00003878};
Hans Wennborg7eb54642015-09-10 17:07:54 +00003879} // anonymous namespace
Alexey Bataev62b63b12015-03-10 07:28:44 +00003880
Samuel Antaoee8fb302016-01-06 13:42:12 +00003881bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003882 return OffloadEntriesTargetRegion.empty() &&
3883 OffloadEntriesDeviceGlobalVar.empty();
Samuel Antaoee8fb302016-01-06 13:42:12 +00003884}
3885
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003886/// Initialize target region entry.
Samuel Antaoee8fb302016-01-06 13:42:12 +00003887void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3888 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3889 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00003890 unsigned Order) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003891 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
3892 "only required for the device "
3893 "code generation.");
Samuel Antao2de62b02016-02-13 23:35:10 +00003894 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
Samuel Antaof83efdb2017-01-05 16:02:49 +00003895 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003896 OMPTargetRegionEntryTargetRegion);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003897 ++OffloadingEntriesNum;
3898}
3899
3900void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3901 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3902 StringRef ParentName, unsigned LineNum,
Samuel Antaof83efdb2017-01-05 16:02:49 +00003903 llvm::Constant *Addr, llvm::Constant *ID,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003904 OMPTargetRegionEntryKind Flags) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003905 // If we are emitting code for a target, the entry is already initialized,
3906 // only has to be registered.
3907 if (CGM.getLangOpts().OpenMPIsDevice) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00003908 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) {
3909 unsigned DiagID = CGM.getDiags().getCustomDiagID(
3910 DiagnosticsEngine::Error,
3911 "Unable to find target region on line '%0' in the device code.");
3912 CGM.getDiags().Report(DiagID) << LineNum;
3913 return;
3914 }
Samuel Antao2de62b02016-02-13 23:35:10 +00003915 auto &Entry =
3916 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
Samuel Antaoee8fb302016-01-06 13:42:12 +00003917 assert(Entry.isValid() && "Entry not initialized!");
3918 Entry.setAddress(Addr);
3919 Entry.setID(ID);
Samuel Antaof83efdb2017-01-05 16:02:49 +00003920 Entry.setFlags(Flags);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003921 } else {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003922 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags);
Samuel Antao2de62b02016-02-13 23:35:10 +00003923 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00003924 ++OffloadingEntriesNum;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003925 }
3926}
3927
3928bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00003929 unsigned DeviceID, unsigned FileID, StringRef ParentName,
3930 unsigned LineNum) const {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003931 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
3932 if (PerDevice == OffloadEntriesTargetRegion.end())
3933 return false;
3934 auto PerFile = PerDevice->second.find(FileID);
3935 if (PerFile == PerDevice->second.end())
3936 return false;
3937 auto PerParentName = PerFile->second.find(ParentName);
3938 if (PerParentName == PerFile->second.end())
3939 return false;
3940 auto PerLine = PerParentName->second.find(LineNum);
3941 if (PerLine == PerParentName->second.end())
3942 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003943 // Fail if this entry is already registered.
Samuel Antao2de62b02016-02-13 23:35:10 +00003944 if (PerLine->second.getAddress() || PerLine->second.getID())
Samuel Antaoee8fb302016-01-06 13:42:12 +00003945 return false;
3946 return true;
3947}
3948
3949void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
3950 const OffloadTargetRegionEntryInfoActTy &Action) {
3951 // Scan all target region entries and perform the provided action.
Alexey Bataev03f270c2018-03-30 18:31:07 +00003952 for (const auto &D : OffloadEntriesTargetRegion)
3953 for (const auto &F : D.second)
3954 for (const auto &P : F.second)
3955 for (const auto &L : P.second)
Samuel Antao2de62b02016-02-13 23:35:10 +00003956 Action(D.first, F.first, P.first(), L.first, L.second);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003957}
3958
Alexey Bataev03f270c2018-03-30 18:31:07 +00003959void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3960 initializeDeviceGlobalVarEntryInfo(StringRef Name,
3961 OMPTargetGlobalVarEntryKind Flags,
3962 unsigned Order) {
3963 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
3964 "only required for the device "
3965 "code generation.");
3966 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
3967 ++OffloadingEntriesNum;
3968}
Samuel Antaoee8fb302016-01-06 13:42:12 +00003969
Alexey Bataev03f270c2018-03-30 18:31:07 +00003970void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3971 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr,
3972 CharUnits VarSize,
3973 OMPTargetGlobalVarEntryKind Flags,
3974 llvm::GlobalValue::LinkageTypes Linkage) {
3975 if (CGM.getLangOpts().OpenMPIsDevice) {
3976 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3977 assert(Entry.isValid() && Entry.getFlags() == Flags &&
3978 "Entry not initialized!");
3979 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
3980 "Resetting with the new address.");
Alexey Bataev8259cc32019-03-12 20:05:17 +00003981 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) {
3982 if (Entry.getVarSize().isZero()) {
3983 Entry.setVarSize(VarSize);
3984 Entry.setLinkage(Linkage);
3985 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003986 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00003987 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003988 Entry.setVarSize(VarSize);
3989 Entry.setLinkage(Linkage);
Alexey Bataev8259cc32019-03-12 20:05:17 +00003990 Entry.setAddress(Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00003991 } else {
Alexey Bataev8259cc32019-03-12 20:05:17 +00003992 if (hasDeviceGlobalVarEntryInfo(VarName)) {
3993 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3994 assert(Entry.isValid() && Entry.getFlags() == Flags &&
3995 "Entry not initialized!");
3996 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
3997 "Resetting with the new address.");
3998 if (Entry.getVarSize().isZero()) {
3999 Entry.setVarSize(VarSize);
4000 Entry.setLinkage(Linkage);
4001 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004002 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00004003 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004004 OffloadEntriesDeviceGlobalVar.try_emplace(
4005 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage);
4006 ++OffloadingEntriesNum;
4007 }
4008}
4009
4010void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
4011 actOnDeviceGlobalVarEntriesInfo(
4012 const OffloadDeviceGlobalVarEntryInfoActTy &Action) {
4013 // Scan all target region entries and perform the provided action.
4014 for (const auto &E : OffloadEntriesDeviceGlobalVar)
4015 Action(E.getKey(), E.getValue());
Samuel Antaoee8fb302016-01-06 13:42:12 +00004016}
4017
Alexey Bataev03f270c2018-03-30 18:31:07 +00004018void CGOpenMPRuntime::createOffloadEntry(
4019 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags,
4020 llvm::GlobalValue::LinkageTypes Linkage) {
Samuel Antao2de62b02016-02-13 23:35:10 +00004021 StringRef Name = Addr->getName();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004022 llvm::Module &M = CGM.getModule();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004023 llvm::LLVMContext &C = M.getContext();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004024
4025 // Create constant string with the name.
4026 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
4027
Alexey Bataev18fa2322018-05-02 14:20:50 +00004028 std::string StringName = getName({"omp_offloading", "entry_name"});
4029 auto *Str = new llvm::GlobalVariable(
4030 M, StrPtrInit->getType(), /*isConstant=*/true,
4031 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00004032 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004033
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004034 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy),
4035 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy),
4036 llvm::ConstantInt::get(CGM.SizeTy, Size),
4037 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
4038 llvm::ConstantInt::get(CGM.Int32Ty, 0)};
Alexey Bataev18fa2322018-05-02 14:20:50 +00004039 std::string EntryName = getName({"omp_offloading", "entry", ""});
Mike Ricee1ca7b62018-08-29 15:45:11 +00004040 llvm::GlobalVariable *Entry = createGlobalStruct(
4041 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data,
4042 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004043
4044 // The entry has to be created in the section the linker expects it to be.
Sergey Dmitriev4b343fd2019-09-27 20:00:51 +00004045 Entry->setSection("omp_offloading_entries");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004046}
4047
4048void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
4049 // Emit the offloading entries and metadata so that the device codegen side
Samuel Antao4c8035b2016-12-12 18:00:20 +00004050 // can easily figure out what to emit. The produced metadata looks like
4051 // this:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004052 //
4053 // !omp_offload.info = !{!1, ...}
4054 //
4055 // Right now we only generate metadata for function that contain target
4056 // regions.
4057
Sergey Dmitriev5836c352019-10-15 18:42:47 +00004058 // If we are in simd mode or there are no entries, we don't need to do
4059 // anything.
4060 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty())
Samuel Antaoee8fb302016-01-06 13:42:12 +00004061 return;
4062
4063 llvm::Module &M = CGM.getModule();
4064 llvm::LLVMContext &C = M.getContext();
Alexey Bataevba643691d2019-10-03 16:20:34 +00004065 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *,
4066 SourceLocation, StringRef>,
4067 16>
Samuel Antaoee8fb302016-01-06 13:42:12 +00004068 OrderedEntries(OffloadEntriesInfoManager.size());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004069 llvm::SmallVector<StringRef, 16> ParentFunctions(
4070 OffloadEntriesInfoManager.size());
Samuel Antaoee8fb302016-01-06 13:42:12 +00004071
Simon Pilgrim2c518802017-03-30 14:13:19 +00004072 // Auxiliary methods to create metadata values and strings.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004073 auto &&GetMDInt = [this](unsigned V) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004074 return llvm::ConstantAsMetadata::get(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004075 llvm::ConstantInt::get(CGM.Int32Ty, V));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004076 };
4077
Alexey Bataev03f270c2018-03-30 18:31:07 +00004078 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); };
4079
4080 // Create the offloading info metadata node.
4081 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004082
4083 // Create function that emits metadata for each target region entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00004084 auto &&TargetRegionMetadataEmitter =
Alexey Bataevba643691d2019-10-03 16:20:34 +00004085 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt,
4086 &GetMDString](
Alexey Bataev03f270c2018-03-30 18:31:07 +00004087 unsigned DeviceID, unsigned FileID, StringRef ParentName,
4088 unsigned Line,
4089 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
4090 // Generate metadata for target regions. Each entry of this metadata
4091 // contains:
4092 // - Entry 0 -> Kind of this type of metadata (0).
4093 // - Entry 1 -> Device ID of the file where the entry was identified.
4094 // - Entry 2 -> File ID of the file where the entry was identified.
4095 // - Entry 3 -> Mangled name of the function where the entry was
4096 // identified.
4097 // - Entry 4 -> Line in the file where the entry was identified.
4098 // - Entry 5 -> Order the entry was created.
4099 // The first element of the metadata node is the kind.
4100 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID),
4101 GetMDInt(FileID), GetMDString(ParentName),
4102 GetMDInt(Line), GetMDInt(E.getOrder())};
Samuel Antaoee8fb302016-01-06 13:42:12 +00004103
Alexey Bataevba643691d2019-10-03 16:20:34 +00004104 SourceLocation Loc;
4105 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(),
4106 E = CGM.getContext().getSourceManager().fileinfo_end();
4107 I != E; ++I) {
4108 if (I->getFirst()->getUniqueID().getDevice() == DeviceID &&
4109 I->getFirst()->getUniqueID().getFile() == FileID) {
4110 Loc = CGM.getContext().getSourceManager().translateFileLineCol(
4111 I->getFirst(), Line, 1);
4112 break;
4113 }
4114 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004115 // Save this entry in the right position of the ordered entries array.
Alexey Bataevba643691d2019-10-03 16:20:34 +00004116 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName);
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004117 ParentFunctions[E.getOrder()] = ParentName;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004118
Alexey Bataev03f270c2018-03-30 18:31:07 +00004119 // Add metadata to the named metadata node.
4120 MD->addOperand(llvm::MDNode::get(C, Ops));
4121 };
Samuel Antaoee8fb302016-01-06 13:42:12 +00004122
4123 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
4124 TargetRegionMetadataEmitter);
4125
Alexey Bataev03f270c2018-03-30 18:31:07 +00004126 // Create function that emits metadata for each device global variable entry;
4127 auto &&DeviceGlobalVarMetadataEmitter =
4128 [&C, &OrderedEntries, &GetMDInt, &GetMDString,
4129 MD](StringRef MangledName,
4130 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar
4131 &E) {
4132 // Generate metadata for global variables. Each entry of this metadata
4133 // contains:
4134 // - Entry 0 -> Kind of this type of metadata (1).
4135 // - Entry 1 -> Mangled name of the variable.
4136 // - Entry 2 -> Declare target kind.
4137 // - Entry 3 -> Order the entry was created.
4138 // The first element of the metadata node is the kind.
4139 llvm::Metadata *Ops[] = {
4140 GetMDInt(E.getKind()), GetMDString(MangledName),
4141 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
4142
4143 // Save this entry in the right position of the ordered entries array.
Alexey Bataevba643691d2019-10-03 16:20:34 +00004144 OrderedEntries[E.getOrder()] =
4145 std::make_tuple(&E, SourceLocation(), MangledName);
Alexey Bataev03f270c2018-03-30 18:31:07 +00004146
4147 // Add metadata to the named metadata node.
4148 MD->addOperand(llvm::MDNode::get(C, Ops));
4149 };
4150
4151 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo(
4152 DeviceGlobalVarMetadataEmitter);
4153
Alexey Bataevba643691d2019-10-03 16:20:34 +00004154 for (const auto &E : OrderedEntries) {
4155 assert(std::get<0>(E) && "All ordered entries must exist!");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004156 if (const auto *CE =
Samuel Antaoee8fb302016-01-06 13:42:12 +00004157 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
Alexey Bataevba643691d2019-10-03 16:20:34 +00004158 std::get<0>(E))) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004159 if (!CE->getID() || !CE->getAddress()) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004160 // Do not blame the entry if the parent funtion is not emitted.
4161 StringRef FnName = ParentFunctions[CE->getOrder()];
4162 if (!CGM.GetGlobalValue(FnName))
4163 continue;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004164 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4165 DiagnosticsEngine::Error,
Alexey Bataevba643691d2019-10-03 16:20:34 +00004166 "Offloading entry for target region in %0 is incorrect: either the "
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004167 "address or the ID is invalid.");
Alexey Bataevba643691d2019-10-03 16:20:34 +00004168 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004169 continue;
4170 }
Alexey Bataev34f8a702018-03-28 14:28:54 +00004171 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004172 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage);
Alexey Bataevba643691d2019-10-03 16:20:34 +00004173 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy::
4174 OffloadEntryInfoDeviceGlobalVar>(
4175 std::get<0>(E))) {
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004176 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags =
4177 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4178 CE->getFlags());
4179 switch (Flags) {
4180 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00004181 if (CGM.getLangOpts().OpenMPIsDevice &&
4182 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())
4183 continue;
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004184 if (!CE->getAddress()) {
4185 unsigned DiagID = CGM.getDiags().getCustomDiagID(
Alexey Bataevba643691d2019-10-03 16:20:34 +00004186 DiagnosticsEngine::Error, "Offloading entry for declare target "
4187 "variable %0 is incorrect: the "
4188 "address is invalid.");
4189 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E);
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004190 continue;
4191 }
Alexey Bataevb4dd6d22018-08-29 20:41:37 +00004192 // The vaiable has no definition - no need to add the entry.
4193 if (CE->getVarSize().isZero())
4194 continue;
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004195 break;
4196 }
4197 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink:
4198 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) ||
4199 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) &&
4200 "Declaret target link address is set.");
4201 if (CGM.getLangOpts().OpenMPIsDevice)
4202 continue;
4203 if (!CE->getAddress()) {
4204 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4205 DiagnosticsEngine::Error,
4206 "Offloading entry for declare target variable is incorrect: the "
4207 "address is invalid.");
4208 CGM.getDiags().Report(DiagID);
4209 continue;
4210 }
4211 break;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004212 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004213 createOffloadEntry(CE->getAddress(), CE->getAddress(),
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004214 CE->getVarSize().getQuantity(), Flags,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004215 CE->getLinkage());
4216 } else {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004217 llvm_unreachable("Unsupported entry kind.");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004218 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004219 }
4220}
4221
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004222/// Loads all the offload entries information from the host IR
Samuel Antaoee8fb302016-01-06 13:42:12 +00004223/// metadata.
4224void CGOpenMPRuntime::loadOffloadInfoMetadata() {
4225 // If we are in target mode, load the metadata from the host IR. This code has
4226 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
4227
4228 if (!CGM.getLangOpts().OpenMPIsDevice)
4229 return;
4230
4231 if (CGM.getLangOpts().OMPHostIRFile.empty())
4232 return;
4233
4234 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004235 if (auto EC = Buf.getError()) {
4236 CGM.getDiags().Report(diag::err_cannot_open_file)
4237 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004238 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004239 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004240
4241 llvm::LLVMContext C;
Peter Collingbourned9445c42016-11-13 07:00:17 +00004242 auto ME = expectedToErrorOrAndEmitErrors(
4243 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004244
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004245 if (auto EC = ME.getError()) {
4246 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4247 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'");
4248 CGM.getDiags().Report(DiagID)
4249 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004250 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004251 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004252
4253 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
4254 if (!MD)
4255 return;
4256
George Burgess IV00f70bd2018-03-01 05:43:23 +00004257 for (llvm::MDNode *MN : MD->operands()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004258 auto &&GetMDInt = [MN](unsigned Idx) {
4259 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004260 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
4261 };
4262
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004263 auto &&GetMDString = [MN](unsigned Idx) {
4264 auto *V = cast<llvm::MDString>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004265 return V->getString();
4266 };
4267
Alexey Bataev03f270c2018-03-30 18:31:07 +00004268 switch (GetMDInt(0)) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004269 default:
4270 llvm_unreachable("Unexpected metadata!");
4271 break;
4272 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
Alexey Bataev34f8a702018-03-28 14:28:54 +00004273 OffloadingEntryInfoTargetRegion:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004274 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
Alexey Bataev03f270c2018-03-30 18:31:07 +00004275 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2),
4276 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4),
4277 /*Order=*/GetMDInt(5));
4278 break;
4279 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
4280 OffloadingEntryInfoDeviceGlobalVar:
4281 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo(
4282 /*MangledName=*/GetMDString(1),
4283 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4284 /*Flags=*/GetMDInt(2)),
4285 /*Order=*/GetMDInt(3));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004286 break;
4287 }
4288 }
4289}
4290
Alexey Bataev62b63b12015-03-10 07:28:44 +00004291void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
4292 if (!KmpRoutineEntryPtrTy) {
4293 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004294 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004295 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
4296 FunctionProtoType::ExtProtoInfo EPI;
4297 KmpRoutineEntryPtrQTy = C.getPointerType(
4298 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
4299 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
4300 }
4301}
4302
Samuel Antaoee8fb302016-01-06 13:42:12 +00004303QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004304 // Make sure the type of the entry is already created. This is the type we
4305 // have to create:
4306 // struct __tgt_offload_entry{
4307 // void *addr; // Pointer to the offload entry info.
4308 // // (function or global)
4309 // char *name; // Name of the function or global.
4310 // size_t size; // Size of the entry info (0 if it a function).
Samuel Antaof83efdb2017-01-05 16:02:49 +00004311 // int32_t flags; // Flags associated with the entry, e.g. 'link'.
4312 // int32_t reserved; // Reserved, to use by the runtime library.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004313 // };
4314 if (TgtOffloadEntryQTy.isNull()) {
4315 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004316 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004317 RD->startDefinition();
4318 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4319 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
4320 addFieldToRecordDecl(C, RD, C.getSizeType());
Samuel Antaof83efdb2017-01-05 16:02:49 +00004321 addFieldToRecordDecl(
4322 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4323 addFieldToRecordDecl(
4324 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004325 RD->completeDefinition();
Jonas Hahnfeld5e4df282018-01-18 15:38:03 +00004326 RD->addAttr(PackedAttr::CreateImplicit(C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004327 TgtOffloadEntryQTy = C.getRecordType(RD);
4328 }
4329 return TgtOffloadEntryQTy;
4330}
4331
4332QualType CGOpenMPRuntime::getTgtDeviceImageQTy() {
4333 // These are the types we need to build:
4334 // struct __tgt_device_image{
4335 // void *ImageStart; // Pointer to the target code start.
4336 // void *ImageEnd; // Pointer to the target code end.
4337 // // We also add the host entries to the device image, as it may be useful
4338 // // for the target runtime to have access to that information.
4339 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all
4340 // // the entries.
4341 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
4342 // // entries (non inclusive).
4343 // };
4344 if (TgtDeviceImageQTy.isNull()) {
4345 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004346 RecordDecl *RD = C.buildImplicitRecord("__tgt_device_image");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004347 RD->startDefinition();
4348 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4349 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4350 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4351 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4352 RD->completeDefinition();
4353 TgtDeviceImageQTy = C.getRecordType(RD);
4354 }
4355 return TgtDeviceImageQTy;
4356}
4357
4358QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() {
4359 // struct __tgt_bin_desc{
4360 // int32_t NumDevices; // Number of devices supported.
4361 // __tgt_device_image *DeviceImages; // Arrays of device images
4362 // // (one per device).
4363 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the
4364 // // entries.
4365 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
4366 // // entries (non inclusive).
4367 // };
4368 if (TgtBinaryDescriptorQTy.isNull()) {
4369 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004370 RecordDecl *RD = C.buildImplicitRecord("__tgt_bin_desc");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004371 RD->startDefinition();
4372 addFieldToRecordDecl(
4373 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4374 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy()));
4375 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4376 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4377 RD->completeDefinition();
4378 TgtBinaryDescriptorQTy = C.getRecordType(RD);
4379 }
4380 return TgtBinaryDescriptorQTy;
4381}
4382
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004383namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00004384struct PrivateHelpersTy {
4385 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
4386 const VarDecl *PrivateElemInit)
4387 : Original(Original), PrivateCopy(PrivateCopy),
4388 PrivateElemInit(PrivateElemInit) {}
4389 const VarDecl *Original;
4390 const VarDecl *PrivateCopy;
4391 const VarDecl *PrivateElemInit;
4392};
4393typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Hans Wennborg7eb54642015-09-10 17:07:54 +00004394} // anonymous namespace
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004395
Alexey Bataev9e034042015-05-05 04:05:12 +00004396static RecordDecl *
Craig Topper8674c5c2015-09-29 04:30:07 +00004397createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004398 if (!Privates.empty()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004399 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004400 // Build struct .kmp_privates_t. {
4401 // /* private vars */
4402 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004403 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t");
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004404 RD->startDefinition();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004405 for (const auto &Pair : Privates) {
4406 const VarDecl *VD = Pair.second.Original;
4407 QualType Type = VD->getType().getNonReferenceType();
4408 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type);
Alexey Bataevc71a4092015-09-11 10:29:41 +00004409 if (VD->hasAttrs()) {
4410 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
4411 E(VD->getAttrs().end());
4412 I != E; ++I)
4413 FD->addAttr(*I);
4414 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004415 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004416 RD->completeDefinition();
4417 return RD;
4418 }
4419 return nullptr;
4420}
4421
Alexey Bataev9e034042015-05-05 04:05:12 +00004422static RecordDecl *
Alexey Bataev7292c292016-04-25 12:22:29 +00004423createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind,
4424 QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004425 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004426 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004427 // Build struct kmp_task_t {
4428 // void * shareds;
4429 // kmp_routine_entry_t routine;
4430 // kmp_int32 part_id;
Alexey Bataevad537bb2016-05-30 09:06:50 +00004431 // kmp_cmplrdata_t data1;
4432 // kmp_cmplrdata_t data2;
Alexey Bataev7292c292016-04-25 12:22:29 +00004433 // For taskloops additional fields:
4434 // kmp_uint64 lb;
4435 // kmp_uint64 ub;
4436 // kmp_int64 st;
4437 // kmp_int32 liter;
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004438 // void * reductions;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004439 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004440 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004441 UD->startDefinition();
4442 addFieldToRecordDecl(C, UD, KmpInt32Ty);
4443 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy);
4444 UD->completeDefinition();
4445 QualType KmpCmplrdataTy = C.getRecordType(UD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004446 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t");
Alexey Bataev62b63b12015-03-10 07:28:44 +00004447 RD->startDefinition();
4448 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4449 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
4450 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004451 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
4452 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004453 if (isOpenMPTaskLoopDirective(Kind)) {
4454 QualType KmpUInt64Ty =
4455 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
4456 QualType KmpInt64Ty =
4457 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
4458 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4459 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4460 addFieldToRecordDecl(C, RD, KmpInt64Ty);
4461 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004462 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004463 }
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004464 RD->completeDefinition();
4465 return RD;
4466}
4467
4468static RecordDecl *
4469createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004470 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004471 ASTContext &C = CGM.getContext();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004472 // Build struct kmp_task_t_with_privates {
4473 // kmp_task_t task_data;
4474 // .kmp_privates_t. privates;
4475 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004476 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004477 RD->startDefinition();
4478 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004479 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates))
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004480 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004481 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004482 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004483}
4484
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004485/// Emit a proxy function which accepts kmp_task_t as the second
Alexey Bataev62b63b12015-03-10 07:28:44 +00004486/// argument.
4487/// \code
4488/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00004489/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt,
Alexey Bataev7292c292016-04-25 12:22:29 +00004490/// For taskloops:
4491/// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004492/// tt->reductions, tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004493/// return 0;
4494/// }
4495/// \endcode
James Y Knight9871db02019-02-05 16:42:33 +00004496static llvm::Function *
Alexey Bataev62b63b12015-03-10 07:28:44 +00004497emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev7292c292016-04-25 12:22:29 +00004498 OpenMPDirectiveKind Kind, QualType KmpInt32Ty,
4499 QualType KmpTaskTWithPrivatesPtrQTy,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004500 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
James Y Knight9871db02019-02-05 16:42:33 +00004501 QualType SharedsPtrTy, llvm::Function *TaskFunction,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004502 llvm::Value *TaskPrivatesMap) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004503 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004504 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004505 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4506 ImplicitParamDecl::Other);
4507 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4508 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4509 ImplicitParamDecl::Other);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004510 Args.push_back(&GtidArg);
4511 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004512 const auto &TaskEntryFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004513 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004514 llvm::FunctionType *TaskEntryTy =
4515 CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004516 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""});
4517 auto *TaskEntry = llvm::Function::Create(
4518 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004519 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004520 TaskEntry->setDoesNotRecurse();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004521 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004522 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args,
4523 Loc, Loc);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004524
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004525 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
Alexey Bataev7292c292016-04-25 12:22:29 +00004526 // tt,
4527 // For taskloops:
4528 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
4529 // tt->task_data.shareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004530 llvm::Value *GtidParam = CGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00004531 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
Alexey Bataev31300ed2016-02-04 11:27:03 +00004532 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4533 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4534 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004535 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004536 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004537 LValue Base =
4538 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004539 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004540 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004541 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
4542 llvm::Value *PartidParam = PartIdLVal.getPointer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004543
4544 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004545 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
4546 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev1e491372018-01-23 18:44:14 +00004547 CGF.EmitLoadOfScalar(SharedsLVal, Loc),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004548 CGF.ConvertTypeForMem(SharedsPtrTy));
4549
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004550 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4551 llvm::Value *PrivatesParam;
4552 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004553 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004554 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00004555 PrivatesLVal.getPointer(), CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004556 } else {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004557 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004558 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004559
Alexey Bataev7292c292016-04-25 12:22:29 +00004560 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam,
4561 TaskPrivatesMap,
4562 CGF.Builder
4563 .CreatePointerBitCastOrAddrSpaceCast(
4564 TDBase.getAddress(), CGF.VoidPtrTy)
4565 .getPointer()};
4566 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs),
4567 std::end(CommonArgs));
4568 if (isOpenMPTaskLoopDirective(Kind)) {
4569 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004570 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI);
4571 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004572 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004573 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI);
4574 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004575 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004576 LValue StLVal = CGF.EmitLValueForField(Base, *StFI);
4577 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004578 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004579 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4580 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004581 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004582 LValue RLVal = CGF.EmitLValueForField(Base, *RFI);
4583 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004584 CallArgs.push_back(LBParam);
4585 CallArgs.push_back(UBParam);
4586 CallArgs.push_back(StParam);
4587 CallArgs.push_back(LIParam);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004588 CallArgs.push_back(RParam);
Alexey Bataev7292c292016-04-25 12:22:29 +00004589 }
4590 CallArgs.push_back(SharedsParam);
4591
Alexey Bataev3c595a62017-08-14 15:01:03 +00004592 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction,
4593 CallArgs);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004594 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)),
4595 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004596 CGF.FinishFunction();
4597 return TaskEntry;
4598}
4599
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004600static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
4601 SourceLocation Loc,
4602 QualType KmpInt32Ty,
4603 QualType KmpTaskTWithPrivatesPtrQTy,
4604 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004605 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004606 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004607 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4608 ImplicitParamDecl::Other);
4609 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4610 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4611 ImplicitParamDecl::Other);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004612 Args.push_back(&GtidArg);
4613 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004614 const auto &DestructorFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004615 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004616 llvm::FunctionType *DestructorFnTy =
4617 CGM.getTypes().GetFunctionType(DestructorFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004618 std::string Name =
4619 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""});
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004620 auto *DestructorFn =
4621 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00004622 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004623 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004624 DestructorFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004625 DestructorFn->setDoesNotRecurse();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004626 CodeGenFunction CGF(CGM);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004627 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004628 Args, Loc, Loc);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004629
Alexey Bataev31300ed2016-02-04 11:27:03 +00004630 LValue Base = CGF.EmitLoadOfPointerLValue(
4631 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4632 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004633 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004634 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
4635 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004636 Base = CGF.EmitLValueForField(Base, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004637 for (const auto *Field :
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004638 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004639 if (QualType::DestructionKind DtorKind =
4640 Field->getType().isDestructedType()) {
4641 LValue FieldLValue = CGF.EmitLValueForField(Base, Field);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004642 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
4643 }
4644 }
4645 CGF.FinishFunction();
4646 return DestructorFn;
4647}
4648
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004649/// Emit a privates mapping function for correct handling of private and
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004650/// firstprivate variables.
4651/// \code
4652/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
4653/// **noalias priv1,..., <tyn> **noalias privn) {
4654/// *priv1 = &.privates.priv1;
4655/// ...;
4656/// *privn = &.privates.privn;
4657/// }
4658/// \endcode
4659static llvm::Value *
4660emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Craig Topper8674c5c2015-09-29 04:30:07 +00004661 ArrayRef<const Expr *> PrivateVars,
4662 ArrayRef<const Expr *> FirstprivateVars,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004663 ArrayRef<const Expr *> LastprivateVars,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004664 QualType PrivatesQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004665 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004666 ASTContext &C = CGM.getContext();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004667 FunctionArgList Args;
4668 ImplicitParamDecl TaskPrivatesArg(
4669 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
Alexey Bataev56223232017-06-09 13:40:18 +00004670 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
4671 ImplicitParamDecl::Other);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004672 Args.push_back(&TaskPrivatesArg);
4673 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
4674 unsigned Counter = 1;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004675 for (const Expr *E : PrivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004676 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004677 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4678 C.getPointerType(C.getPointerType(E->getType()))
4679 .withConst()
4680 .withRestrict(),
4681 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004682 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004683 PrivateVarsPos[VD] = Counter;
4684 ++Counter;
4685 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004686 for (const Expr *E : FirstprivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004687 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004688 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4689 C.getPointerType(C.getPointerType(E->getType()))
4690 .withConst()
4691 .withRestrict(),
4692 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004693 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004694 PrivateVarsPos[VD] = Counter;
4695 ++Counter;
4696 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004697 for (const Expr *E : LastprivateVars) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004698 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004699 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4700 C.getPointerType(C.getPointerType(E->getType()))
4701 .withConst()
4702 .withRestrict(),
4703 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004704 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataevf93095a2016-05-05 08:46:22 +00004705 PrivateVarsPos[VD] = Counter;
4706 ++Counter;
4707 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004708 const auto &TaskPrivatesMapFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004709 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004710 llvm::FunctionType *TaskPrivatesMapTy =
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004711 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004712 std::string Name =
4713 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""});
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004714 auto *TaskPrivatesMap = llvm::Function::Create(
Alexey Bataev18fa2322018-05-02 14:20:50 +00004715 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
4716 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004717 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004718 TaskPrivatesMapFnInfo);
Alexey Bataev8c5555c2019-05-21 15:11:58 +00004719 if (CGM.getLangOpts().Optimize) {
4720 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
4721 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
4722 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
4723 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004724 CodeGenFunction CGF(CGM);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004725 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004726 TaskPrivatesMapFnInfo, Args, Loc, Loc);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004727
4728 // *privi = &.privates.privi;
Alexey Bataev31300ed2016-02-04 11:27:03 +00004729 LValue Base = CGF.EmitLoadOfPointerLValue(
4730 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
4731 TaskPrivatesArg.getType()->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004732 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004733 Counter = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004734 for (const FieldDecl *Field : PrivatesQTyRD->fields()) {
4735 LValue FieldLVal = CGF.EmitLValueForField(Base, Field);
4736 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
4737 LValue RefLVal =
4738 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
4739 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue(
Alexey Bataev31300ed2016-02-04 11:27:03 +00004740 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>());
Alexey Bataev2377fe92015-09-10 08:12:02 +00004741 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004742 ++Counter;
4743 }
4744 CGF.FinishFunction();
4745 return TaskPrivatesMap;
4746}
4747
Alexey Bataevf93095a2016-05-05 08:46:22 +00004748/// Emit initialization for private variables in task-based directives.
Alexey Bataev8a831592016-05-10 10:36:51 +00004749static void emitPrivatesInit(CodeGenFunction &CGF,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004750 const OMPExecutableDirective &D,
4751 Address KmpTaskSharedsPtr, LValue TDBase,
4752 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4753 QualType SharedsTy, QualType SharedsPtrTy,
4754 const OMPTaskDataTy &Data,
4755 ArrayRef<PrivateDataTy> Privates, bool ForDup) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004756 ASTContext &C = CGF.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004757 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
4758 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004759 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind())
4760 ? OMPD_taskloop
4761 : OMPD_task;
4762 const CapturedStmt &CS = *D.getCapturedStmt(Kind);
4763 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004764 LValue SrcBase;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004765 bool IsTargetTask =
4766 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) ||
4767 isOpenMPTargetExecutionDirective(D.getDirectiveKind());
4768 // For target-based directives skip 3 firstprivate arrays BasePointersArray,
4769 // PointersArray and SizesArray. The original variables for these arrays are
4770 // not captured and we get their addresses explicitly.
4771 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) ||
Alexey Bataev8451efa2018-01-15 19:06:12 +00004772 (IsTargetTask && KmpTaskSharedsPtr.isValid())) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004773 SrcBase = CGF.MakeAddrLValue(
4774 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4775 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
4776 SharedsTy);
4777 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004778 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004779 for (const PrivateDataTy &Pair : Privates) {
4780 const VarDecl *VD = Pair.second.PrivateCopy;
4781 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004782 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) &&
4783 !CGF.isTrivialInitializer(Init)))) {
Alexey Bataev8a831592016-05-10 10:36:51 +00004784 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004785 if (const VarDecl *Elem = Pair.second.PrivateElemInit) {
4786 const VarDecl *OriginalVD = Pair.second.Original;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004787 // Check if the variable is the target-based BasePointersArray,
4788 // PointersArray or SizesArray.
4789 LValue SharedRefLValue;
Alexey Bataevab41ea62019-03-13 20:46:28 +00004790 QualType Type = PrivateLValue.getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004791 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004792 if (IsTargetTask && !SharedField) {
4793 assert(isa<ImplicitParamDecl>(OriginalVD) &&
4794 isa<CapturedDecl>(OriginalVD->getDeclContext()) &&
4795 cast<CapturedDecl>(OriginalVD->getDeclContext())
4796 ->getNumParams() == 0 &&
4797 isa<TranslationUnitDecl>(
4798 cast<CapturedDecl>(OriginalVD->getDeclContext())
4799 ->getDeclContext()) &&
4800 "Expected artificial target data variable.");
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004801 SharedRefLValue =
4802 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type);
4803 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004804 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField);
4805 SharedRefLValue = CGF.MakeAddrLValue(
4806 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
4807 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl),
4808 SharedRefLValue.getTBAAInfo());
4809 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004810 if (Type->isArrayType()) {
4811 // Initialize firstprivate array.
4812 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) {
4813 // Perform simple memcpy.
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00004814 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004815 } else {
4816 // Initialize firstprivate array using element-by-element
Simon Pilgrim2c518802017-03-30 14:13:19 +00004817 // initialization.
Alexey Bataevf93095a2016-05-05 08:46:22 +00004818 CGF.EmitOMPAggregateAssign(
4819 PrivateLValue.getAddress(), SharedRefLValue.getAddress(), Type,
4820 [&CGF, Elem, Init, &CapturesInfo](Address DestElement,
4821 Address SrcElement) {
4822 // Clean up any temporaries needed by the initialization.
4823 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4824 InitScope.addPrivate(
4825 Elem, [SrcElement]() -> Address { return SrcElement; });
4826 (void)InitScope.Privatize();
4827 // Emit initialization for single element.
4828 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
4829 CGF, &CapturesInfo);
4830 CGF.EmitAnyExprToMem(Init, DestElement,
4831 Init->getType().getQualifiers(),
4832 /*IsInitializer=*/false);
4833 });
4834 }
4835 } else {
4836 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4837 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
4838 return SharedRefLValue.getAddress();
4839 });
4840 (void)InitScope.Privatize();
4841 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
4842 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
4843 /*capturedByInit=*/false);
4844 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004845 } else {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004846 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004847 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004848 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004849 ++FI;
4850 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004851}
4852
4853/// Check if duplication function is required for taskloops.
4854static bool checkInitIsRequired(CodeGenFunction &CGF,
4855 ArrayRef<PrivateDataTy> Privates) {
4856 bool InitRequired = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004857 for (const PrivateDataTy &Pair : Privates) {
4858 const VarDecl *VD = Pair.second.PrivateCopy;
4859 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004860 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) &&
4861 !CGF.isTrivialInitializer(Init));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004862 if (InitRequired)
4863 break;
Alexey Bataevf93095a2016-05-05 08:46:22 +00004864 }
4865 return InitRequired;
4866}
4867
4868
4869/// Emit task_dup function (for initialization of
4870/// private/firstprivate/lastprivate vars and last_iter flag)
4871/// \code
4872/// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int
4873/// lastpriv) {
4874/// // setup lastprivate flag
4875/// task_dst->last = lastpriv;
4876/// // could be constructor calls here...
4877/// }
4878/// \endcode
4879static llvm::Value *
4880emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
4881 const OMPExecutableDirective &D,
4882 QualType KmpTaskTWithPrivatesPtrQTy,
4883 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4884 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy,
4885 QualType SharedsPtrTy, const OMPTaskDataTy &Data,
4886 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004887 ASTContext &C = CGM.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004888 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004889 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4890 KmpTaskTWithPrivatesPtrQTy,
4891 ImplicitParamDecl::Other);
4892 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4893 KmpTaskTWithPrivatesPtrQTy,
4894 ImplicitParamDecl::Other);
4895 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy,
4896 ImplicitParamDecl::Other);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004897 Args.push_back(&DstArg);
4898 Args.push_back(&SrcArg);
4899 Args.push_back(&LastprivArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004900 const auto &TaskDupFnInfo =
Alexey Bataevf93095a2016-05-05 08:46:22 +00004901 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004902 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004903 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""});
4904 auto *TaskDup = llvm::Function::Create(
4905 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004906 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004907 TaskDup->setDoesNotRecurse();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004908 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004909 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc,
4910 Loc);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004911
4912 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4913 CGF.GetAddrOfLocalVar(&DstArg),
4914 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4915 // task_dst->liter = lastpriv;
4916 if (WithLastIter) {
4917 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
4918 LValue Base = CGF.EmitLValueForField(
4919 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4920 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4921 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar(
4922 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc);
4923 CGF.EmitStoreOfScalar(Lastpriv, LILVal);
4924 }
4925
4926 // Emit initial values for private copies (if any).
4927 assert(!Privates.empty());
4928 Address KmpTaskSharedsPtr = Address::invalid();
4929 if (!Data.FirstprivateVars.empty()) {
4930 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4931 CGF.GetAddrOfLocalVar(&SrcArg),
4932 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4933 LValue Base = CGF.EmitLValueForField(
4934 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4935 KmpTaskSharedsPtr = Address(
4936 CGF.EmitLoadOfScalar(CGF.EmitLValueForField(
4937 Base, *std::next(KmpTaskTQTyRD->field_begin(),
4938 KmpTaskTShareds)),
4939 Loc),
4940 CGF.getNaturalTypeAlignment(SharedsTy));
4941 }
Alexey Bataev8a831592016-05-10 10:36:51 +00004942 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
4943 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004944 CGF.FinishFunction();
4945 return TaskDup;
4946}
4947
Alexey Bataev8a831592016-05-10 10:36:51 +00004948/// Checks if destructor function is required to be generated.
4949/// \return true if cleanups are required, false otherwise.
4950static bool
4951checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) {
4952 bool NeedsCleanup = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004953 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4954 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl());
4955 for (const FieldDecl *FD : PrivateRD->fields()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00004956 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType();
4957 if (NeedsCleanup)
4958 break;
4959 }
4960 return NeedsCleanup;
4961}
4962
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004963CGOpenMPRuntime::TaskResultTy
4964CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
4965 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00004966 llvm::Function *TaskFunction, QualType SharedsTy,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004967 Address Shareds, const OMPTaskDataTy &Data) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004968 ASTContext &C = CGM.getContext();
Alexey Bataev7292c292016-04-25 12:22:29 +00004969 llvm::SmallVector<PrivateDataTy, 4> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004970 // Aggregate privates and sort them by the alignment.
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004971 auto I = Data.PrivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004972 for (const Expr *E : Data.PrivateVars) {
4973 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00004974 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00004975 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00004976 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00004977 /*PrivateElemInit=*/nullptr));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004978 ++I;
4979 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004980 I = Data.FirstprivateCopies.begin();
4981 auto IElemInitRef = Data.FirstprivateInits.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004982 for (const Expr *E : Data.FirstprivateVars) {
4983 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00004984 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00004985 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00004986 PrivateHelpersTy(
4987 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00004988 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())));
Richard Trieucc3949d2016-02-18 22:34:54 +00004989 ++I;
4990 ++IElemInitRef;
Alexey Bataev9e034042015-05-05 04:05:12 +00004991 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004992 I = Data.LastprivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004993 for (const Expr *E : Data.LastprivateVars) {
4994 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00004995 Privates.emplace_back(
Alexey Bataevf93095a2016-05-05 08:46:22 +00004996 C.getDeclAlign(VD),
4997 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00004998 /*PrivateElemInit=*/nullptr));
Alexey Bataevf93095a2016-05-05 08:46:22 +00004999 ++I;
5000 }
Fangrui Song899d1392019-04-24 14:43:05 +00005001 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) {
5002 return L.first > R.first;
5003 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005004 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005005 // Build type kmp_routine_entry_t (if not built yet).
5006 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005007 // Build type kmp_task_t (if not built yet).
Alexey Bataeve213f3e2017-10-11 15:29:40 +00005008 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) {
5009 if (SavedKmpTaskloopTQTy.isNull()) {
5010 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5011 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5012 }
5013 KmpTaskTQTy = SavedKmpTaskloopTQTy;
Alexey Bataev3a03a7f2017-10-11 15:56:38 +00005014 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00005015 assert((D.getDirectiveKind() == OMPD_task ||
5016 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) ||
5017 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) &&
5018 "Expected taskloop, task or target directive");
Alexey Bataeve213f3e2017-10-11 15:29:40 +00005019 if (SavedKmpTaskTQTy.isNull()) {
5020 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5021 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5022 }
5023 KmpTaskTQTy = SavedKmpTaskTQTy;
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005024 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005025 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005026 // Build particular struct kmp_task_t for the given task.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005027 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005028 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005029 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005030 QualType KmpTaskTWithPrivatesPtrQTy =
5031 C.getPointerType(KmpTaskTWithPrivatesQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005032 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
5033 llvm::Type *KmpTaskTWithPrivatesPtrTy =
5034 KmpTaskTWithPrivatesTy->getPointerTo();
5035 llvm::Value *KmpTaskTWithPrivatesTySize =
5036 CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005037 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
5038
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005039 // Emit initial values for private copies (if any).
5040 llvm::Value *TaskPrivatesMap = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005041 llvm::Type *TaskPrivatesMapTy =
James Y Knight9871db02019-02-05 16:42:33 +00005042 std::next(TaskFunction->arg_begin(), 3)->getType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005043 if (!Privates.empty()) {
5044 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataevf93095a2016-05-05 08:46:22 +00005045 TaskPrivatesMap = emitTaskPrivateMappingFunction(
5046 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars,
5047 FI->getType(), Privates);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005048 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5049 TaskPrivatesMap, TaskPrivatesMapTy);
5050 } else {
5051 TaskPrivatesMap = llvm::ConstantPointerNull::get(
5052 cast<llvm::PointerType>(TaskPrivatesMapTy));
5053 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005054 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
5055 // kmp_task_t *tt);
James Y Knight9871db02019-02-05 16:42:33 +00005056 llvm::Function *TaskEntry = emitProxyTaskFunction(
Alexey Bataev7292c292016-04-25 12:22:29 +00005057 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5058 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction,
5059 TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005060
5061 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
5062 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
5063 // kmp_routine_entry_t *task_entry);
5064 // Task flags. Format is taken from
James Y Knight5d71fc52019-01-29 16:37:27 +00005065 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h,
Alexey Bataev62b63b12015-03-10 07:28:44 +00005066 // description of kmp_tasking_flags struct.
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005067 enum {
5068 TiedFlag = 0x1,
5069 FinalFlag = 0x2,
5070 DestructorsFlag = 0x8,
5071 PriorityFlag = 0x20
5072 };
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005073 unsigned Flags = Data.Tied ? TiedFlag : 0;
Alexey Bataev8a831592016-05-10 10:36:51 +00005074 bool NeedsCleanup = false;
5075 if (!Privates.empty()) {
5076 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD);
5077 if (NeedsCleanup)
5078 Flags = Flags | DestructorsFlag;
5079 }
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005080 if (Data.Priority.getInt())
5081 Flags = Flags | PriorityFlag;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005082 llvm::Value *TaskFlags =
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005083 Data.Final.getPointer()
5084 ? CGF.Builder.CreateSelect(Data.Final.getPointer(),
Alexey Bataev62b63b12015-03-10 07:28:44 +00005085 CGF.Builder.getInt32(FinalFlag),
5086 CGF.Builder.getInt32(/*C=*/0))
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005087 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005088 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005089 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00005090 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc),
5091 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
5092 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5093 TaskEntry, KmpRoutineEntryPtrTy)};
5094 llvm::Value *NewTask;
5095 if (D.hasClausesOfKind<OMPNowaitClause>()) {
5096 // Check if we have any device clause associated with the directive.
5097 const Expr *Device = nullptr;
5098 if (auto *C = D.getSingleClause<OMPDeviceClause>())
5099 Device = C->getDevice();
5100 // Emit device ID if any otherwise use default value.
5101 llvm::Value *DeviceID;
5102 if (Device)
5103 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
5104 CGF.Int64Ty, /*isSigned=*/true);
5105 else
5106 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
5107 AllocArgs.push_back(DeviceID);
5108 NewTask = CGF.EmitRuntimeCall(
5109 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs);
5110 } else {
5111 NewTask = CGF.EmitRuntimeCall(
Alexey Bataev62b63b12015-03-10 07:28:44 +00005112 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00005113 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005114 llvm::Value *NewTaskNewTaskTTy =
5115 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5116 NewTask, KmpTaskTWithPrivatesPtrTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005117 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
5118 KmpTaskTWithPrivatesQTy);
5119 LValue TDBase =
5120 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005121 // Fill the data in the resulting kmp_task_t record.
5122 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00005123 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005124 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00005125 KmpTaskSharedsPtr =
5126 Address(CGF.EmitLoadOfScalar(
5127 CGF.EmitLValueForField(
5128 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
5129 KmpTaskTShareds)),
5130 Loc),
5131 CGF.getNaturalTypeAlignment(SharedsTy));
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00005132 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy);
5133 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy);
Richard Smithe78fac52018-04-05 20:52:58 +00005134 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005135 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005136 // Emit initial values for private copies (if any).
Alexey Bataevf93095a2016-05-05 08:46:22 +00005137 TaskResultTy Result;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005138 if (!Privates.empty()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00005139 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD,
5140 SharedsTy, SharedsPtrTy, Data, Privates,
5141 /*ForDup=*/false);
Alexey Bataevf93095a2016-05-05 08:46:22 +00005142 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
5143 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) {
5144 Result.TaskDupFn = emitTaskDupFunction(
5145 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
5146 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates,
5147 /*WithLastIter=*/!Data.LastprivateVars.empty());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005148 }
5149 }
Alexey Bataevad537bb2016-05-30 09:06:50 +00005150 // Fields of union "kmp_cmplrdata_t" for destructors and priority.
5151 enum { Priority = 0, Destructors = 1 };
Alexey Bataev62b63b12015-03-10 07:28:44 +00005152 // Provide pointer to function with destructors for privates.
Alexey Bataevad537bb2016-05-30 09:06:50 +00005153 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005154 const RecordDecl *KmpCmplrdataUD =
5155 (*FI)->getType()->getAsUnionType()->getDecl();
Alexey Bataevad537bb2016-05-30 09:06:50 +00005156 if (NeedsCleanup) {
5157 llvm::Value *DestructorFn = emitDestructorsFunction(
5158 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5159 KmpTaskTWithPrivatesQTy);
5160 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI);
5161 LValue DestructorsLV = CGF.EmitLValueForField(
5162 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
5163 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5164 DestructorFn, KmpRoutineEntryPtrTy),
5165 DestructorsLV);
5166 }
5167 // Set priority.
5168 if (Data.Priority.getInt()) {
5169 LValue Data2LV = CGF.EmitLValueForField(
5170 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
5171 LValue PriorityLV = CGF.EmitLValueForField(
5172 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
5173 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV);
5174 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005175 Result.NewTask = NewTask;
5176 Result.TaskEntry = TaskEntry;
5177 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
5178 Result.TDBase = TDBase;
5179 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
5180 return Result;
Alexey Bataev7292c292016-04-25 12:22:29 +00005181}
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005182
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005183void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
5184 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005185 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005186 QualType SharedsTy, Address Shareds,
5187 const Expr *IfCond,
5188 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005189 if (!CGF.HaveInsertPoint())
5190 return;
5191
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005192 TaskResultTy Result =
5193 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
5194 llvm::Value *NewTask = Result.NewTask;
James Y Knight9871db02019-02-05 16:42:33 +00005195 llvm::Function *TaskEntry = Result.TaskEntry;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005196 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy;
5197 LValue TDBase = Result.TDBase;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005198 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD;
5199 ASTContext &C = CGM.getContext();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005200 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00005201 Address DependenciesArray = Address::invalid();
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005202 unsigned NumDependencies = Data.Dependences.size();
John McCall7f416cc2015-09-08 08:05:57 +00005203 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005204 // Dependence kind for RTL.
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005205 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 };
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005206 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
5207 RecordDecl *KmpDependInfoRD;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005208 QualType FlagsTy =
5209 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005210 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
5211 if (KmpDependInfoTy.isNull()) {
5212 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
5213 KmpDependInfoRD->startDefinition();
5214 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
5215 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
5216 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
5217 KmpDependInfoRD->completeDefinition();
5218 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005219 } else {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005220 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005221 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005222 // Define type kmp_depend_info[<Dependences.size()>];
5223 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00005224 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Richard Smith772e2662019-10-04 01:25:59 +00005225 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005226 // kmp_depend_info[<Dependences.size()>] deps;
Alexey Bataev48591dd2016-04-20 04:01:36 +00005227 DependenciesArray =
5228 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005229 for (unsigned I = 0; I < NumDependencies; ++I) {
5230 const Expr *E = Data.Dependences[I].second;
5231 LValue Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005232 llvm::Value *Size;
5233 QualType Ty = E->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005234 if (const auto *ASE =
5235 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005236 LValue UpAddrLVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005237 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005238 llvm::Value *UpAddr =
John McCall7f416cc2015-09-08 08:05:57 +00005239 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005240 llvm::Value *LowIntPtr =
John McCall7f416cc2015-09-08 08:05:57 +00005241 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005242 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
5243 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005244 } else {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005245 Size = CGF.getTypeSize(Ty);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005246 }
5247 LValue Base = CGF.MakeAddrLValue(
James Y Knight751fe282019-02-09 22:22:28 +00005248 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005249 KmpDependInfoTy);
5250 // deps[i].base_addr = &<Dependences[i].second>;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005251 LValue BaseAddrLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005252 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00005253 CGF.EmitStoreOfScalar(
5254 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy),
5255 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005256 // deps[i].len = sizeof(<Dependences[i].second>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005257 LValue LenLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005258 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
5259 CGF.EmitStoreOfScalar(Size, LenLVal);
5260 // deps[i].flags = <Dependences[i].first>;
5261 RTLDependenceKindTy DepKind;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005262 switch (Data.Dependences[I].first) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005263 case OMPC_DEPEND_in:
5264 DepKind = DepIn;
5265 break;
Alexey Bataev92e82f92015-11-23 13:33:42 +00005266 // Out and InOut dependencies must use the same code.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005267 case OMPC_DEPEND_out:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005268 case OMPC_DEPEND_inout:
5269 DepKind = DepInOut;
5270 break;
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005271 case OMPC_DEPEND_mutexinoutset:
5272 DepKind = DepMutexInOutSet;
5273 break;
Alexey Bataeveb482352015-12-18 05:05:56 +00005274 case OMPC_DEPEND_source:
Alexey Bataeva636c7f2015-12-23 10:27:45 +00005275 case OMPC_DEPEND_sink:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005276 case OMPC_DEPEND_unknown:
5277 llvm_unreachable("Unknown task dependence type");
5278 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005279 LValue FlagsLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005280 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
5281 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
5282 FlagsLVal);
5283 }
John McCall7f416cc2015-09-08 08:05:57 +00005284 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knightf5f1b0e2019-02-08 15:34:12 +00005285 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005286 }
5287
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005288 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev62b63b12015-03-10 07:28:44 +00005289 // libcall.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005290 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
5291 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
5292 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
5293 // list is not empty
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005294 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5295 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00005296 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
5297 llvm::Value *DepTaskArgs[7];
5298 if (NumDependencies) {
5299 DepTaskArgs[0] = UpLoc;
5300 DepTaskArgs[1] = ThreadID;
5301 DepTaskArgs[2] = NewTask;
5302 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
5303 DepTaskArgs[4] = DependenciesArray.getPointer();
5304 DepTaskArgs[5] = CGF.Builder.getInt32(0);
5305 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5306 }
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005307 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies,
5308 &TaskArgs,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005309 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005310 if (!Data.Tied) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005311 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005312 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
Alexey Bataev48591dd2016-04-20 04:01:36 +00005313 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
5314 }
John McCall7f416cc2015-09-08 08:05:57 +00005315 if (NumDependencies) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005316 CGF.EmitRuntimeCall(
Alexey Bataev48591dd2016-04-20 04:01:36 +00005317 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs);
John McCall7f416cc2015-09-08 08:05:57 +00005318 } else {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005319 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
John McCall7f416cc2015-09-08 08:05:57 +00005320 TaskArgs);
5321 }
Alexey Bataev48591dd2016-04-20 04:01:36 +00005322 // Check if parent region is untied and build return for untied task;
5323 if (auto *Region =
5324 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
5325 Region->emitUntiedSwitch(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00005326 };
John McCall7f416cc2015-09-08 08:05:57 +00005327
5328 llvm::Value *DepWaitTaskArgs[6];
5329 if (NumDependencies) {
5330 DepWaitTaskArgs[0] = UpLoc;
5331 DepWaitTaskArgs[1] = ThreadID;
5332 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
5333 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
5334 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
5335 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5336 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005337 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
Alexey Bataev3c595a62017-08-14 15:01:03 +00005338 NumDependencies, &DepWaitTaskArgs,
5339 Loc](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005340 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005341 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
5342 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
5343 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
5344 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
5345 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00005346 if (NumDependencies)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005347 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005348 DepWaitTaskArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005349 // Call proxy_task_entry(gtid, new_task);
Alexey Bataev3c595a62017-08-14 15:01:03 +00005350 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
5351 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005352 Action.Enter(CGF);
5353 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
Alexey Bataev3c595a62017-08-14 15:01:03 +00005354 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
Alexey Bataev2c7eee52017-08-04 19:10:54 +00005355 OutlinedFnArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005356 };
5357
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005358 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
5359 // kmp_task_t *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005360 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
5361 // kmp_task_t *new_task);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005362 RegionCodeGenTy RCG(CodeGen);
5363 CommonActionTy Action(
5364 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs,
5365 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs);
5366 RCG.setAction(Action);
5367 RCG(CGF);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005368 };
John McCall7f416cc2015-09-08 08:05:57 +00005369
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005370 if (IfCond) {
Alexey Bataev1d677132015-04-22 13:57:31 +00005371 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005372 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005373 RegionCodeGenTy ThenRCG(ThenCodeGen);
5374 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00005375 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005376}
5377
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005378void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
5379 const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005380 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005381 QualType SharedsTy, Address Shareds,
5382 const Expr *IfCond,
5383 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005384 if (!CGF.HaveInsertPoint())
5385 return;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005386 TaskResultTy Result =
5387 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005388 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev7292c292016-04-25 12:22:29 +00005389 // libcall.
5390 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
5391 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
5392 // sched, kmp_uint64 grainsize, void *task_dup);
5393 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5394 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
5395 llvm::Value *IfVal;
5396 if (IfCond) {
5397 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy,
5398 /*isSigned=*/true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005399 } else {
Alexey Bataev7292c292016-04-25 12:22:29 +00005400 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005401 }
Alexey Bataev7292c292016-04-25 12:22:29 +00005402
5403 LValue LBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005404 Result.TDBase,
5405 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005406 const auto *LBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005407 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl());
5408 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(),
5409 /*IsInitializer=*/true);
5410 LValue UBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005411 Result.TDBase,
5412 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005413 const auto *UBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005414 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl());
5415 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(),
5416 /*IsInitializer=*/true);
5417 LValue StLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005418 Result.TDBase,
5419 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005420 const auto *StVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005421 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl());
5422 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(),
5423 /*IsInitializer=*/true);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005424 // Store reductions address.
5425 LValue RedLVal = CGF.EmitLValueForField(
5426 Result.TDBase,
5427 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005428 if (Data.Reductions) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005429 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005430 } else {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005431 CGF.EmitNullInitialization(RedLVal.getAddress(),
5432 CGF.getContext().VoidPtrTy);
5433 }
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005434 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
Alexey Bataev7292c292016-04-25 12:22:29 +00005435 llvm::Value *TaskArgs[] = {
Alexey Bataev33446032017-07-12 18:09:32 +00005436 UpLoc,
5437 ThreadID,
5438 Result.NewTask,
5439 IfVal,
5440 LBLVal.getPointer(),
5441 UBLVal.getPointer(),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00005442 CGF.EmitLoadOfScalar(StLVal, Loc),
Alexey Bataevac6e4de2018-10-24 19:06:37 +00005443 llvm::ConstantInt::getSigned(
5444 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005445 llvm::ConstantInt::getSigned(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005446 CGF.IntTy, Data.Schedule.getPointer()
5447 ? Data.Schedule.getInt() ? NumTasks : Grainsize
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005448 : NoSchedule),
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005449 Data.Schedule.getPointer()
5450 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty,
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005451 /*isSigned=*/false)
5452 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0),
Alexey Bataev33446032017-07-12 18:09:32 +00005453 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5454 Result.TaskDupFn, CGF.VoidPtrTy)
5455 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)};
Alexey Bataev7292c292016-04-25 12:22:29 +00005456 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs);
5457}
5458
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005459/// Emit reduction operation for each element of array (required for
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005460/// array sections) LHS op = RHS.
5461/// \param Type Type of array.
5462/// \param LHSVar Variable on the left side of the reduction operation
5463/// (references element of array in original variable).
5464/// \param RHSVar Variable on the right side of the reduction operation
5465/// (references element of array in original variable).
5466/// \param RedOpGen Generator of reduction operation with use of LHSVar and
5467/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00005468static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005469 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
5470 const VarDecl *RHSVar,
5471 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
5472 const Expr *, const Expr *)> &RedOpGen,
5473 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
5474 const Expr *UpExpr = nullptr) {
5475 // Perform element-by-element initialization.
5476 QualType ElementTy;
5477 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
5478 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
5479
5480 // Drill down to the base element type on both arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005481 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
5482 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005483
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005484 llvm::Value *RHSBegin = RHSAddr.getPointer();
5485 llvm::Value *LHSBegin = LHSAddr.getPointer();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005486 // Cast from pointer to array type to pointer to single element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005487 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005488 // The basic structure here is a while-do loop.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005489 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
5490 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
5491 llvm::Value *IsEmpty =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005492 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
5493 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
5494
5495 // Enter the loop body, making that address the current address.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005496 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005497 CGF.EmitBlock(BodyBB);
5498
5499 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
5500
5501 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
5502 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
5503 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
5504 Address RHSElementCurrent =
5505 Address(RHSElementPHI,
5506 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5507
5508 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
5509 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
5510 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
5511 Address LHSElementCurrent =
5512 Address(LHSElementPHI,
5513 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5514
5515 // Emit copy.
5516 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005517 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; });
5518 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005519 Scope.Privatize();
5520 RedOpGen(CGF, XExpr, EExpr, UpExpr);
5521 Scope.ForceCleanup();
5522
5523 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005524 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005525 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005526 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005527 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
5528 // Check whether we've reached the end.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005529 llvm::Value *Done =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005530 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
5531 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
5532 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
5533 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
5534
5535 // Done.
5536 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
5537}
5538
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005539/// Emit reduction combiner. If the combiner is a simple expression emit it as
5540/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
5541/// UDR combiner function.
5542static void emitReductionCombiner(CodeGenFunction &CGF,
5543 const Expr *ReductionOp) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005544 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
5545 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
5546 if (const auto *DRE =
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005547 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005548 if (const auto *DRD =
5549 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005550 std::pair<llvm::Function *, llvm::Function *> Reduction =
5551 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
5552 RValue Func = RValue::get(Reduction.first);
5553 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
5554 CGF.EmitIgnoredExpr(ReductionOp);
5555 return;
5556 }
5557 CGF.EmitIgnoredExpr(ReductionOp);
5558}
5559
James Y Knight9871db02019-02-05 16:42:33 +00005560llvm::Function *CGOpenMPRuntime::emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005561 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates,
5562 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
5563 ArrayRef<const Expr *> ReductionOps) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005564 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005565
5566 // void reduction_func(void *LHSArg, void *RHSArg);
5567 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005568 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5569 ImplicitParamDecl::Other);
5570 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5571 ImplicitParamDecl::Other);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005572 Args.push_back(&LHSArg);
5573 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005574 const auto &CGFI =
5575 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00005576 std::string Name = getName({"omp", "reduction", "reduction_func"});
5577 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
5578 llvm::GlobalValue::InternalLinkage, Name,
5579 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00005580 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00005581 Fn->setDoesNotRecurse();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005582 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005583 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005584
5585 // Dst = (void*[n])(LHSArg);
5586 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00005587 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5588 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
5589 ArgsType), CGF.getPointerAlign());
5590 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5591 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
5592 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005593
5594 // ...
5595 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
5596 // ...
5597 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005598 auto IPriv = Privates.begin();
5599 unsigned Idx = 0;
5600 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005601 const auto *RHSVar =
5602 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
5603 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005604 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005605 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005606 const auto *LHSVar =
5607 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
5608 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005609 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005610 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005611 QualType PrivTy = (*IPriv)->getType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00005612 if (PrivTy->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005613 // Get array size and emit VLA type.
5614 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005615 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005616 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005617 const VariableArrayType *VLA =
5618 CGF.getContext().getAsVariableArrayType(PrivTy);
5619 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005620 CodeGenFunction::OpaqueValueMapping OpaqueMap(
Alexey Bataev1189bd02016-01-26 12:20:39 +00005621 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005622 CGF.EmitVariablyModifiedType(PrivTy);
5623 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005624 }
5625 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005626 IPriv = Privates.begin();
5627 auto ILHS = LHSExprs.begin();
5628 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005629 for (const Expr *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005630 if ((*IPriv)->getType()->isArrayType()) {
5631 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005632 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5633 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005634 EmitOMPAggregateReduction(
5635 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5636 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5637 emitReductionCombiner(CGF, E);
5638 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005639 } else {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005640 // Emit reduction for array subscript or single variable.
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005641 emitReductionCombiner(CGF, E);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005642 }
Richard Trieucc3949d2016-02-18 22:34:54 +00005643 ++IPriv;
5644 ++ILHS;
5645 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005646 }
5647 Scope.ForceCleanup();
5648 CGF.FinishFunction();
5649 return Fn;
5650}
5651
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005652void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF,
5653 const Expr *ReductionOp,
5654 const Expr *PrivateRef,
5655 const DeclRefExpr *LHS,
5656 const DeclRefExpr *RHS) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005657 if (PrivateRef->getType()->isArrayType()) {
5658 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005659 const auto *LHSVar = cast<VarDecl>(LHS->getDecl());
5660 const auto *RHSVar = cast<VarDecl>(RHS->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005661 EmitOMPAggregateReduction(
5662 CGF, PrivateRef->getType(), LHSVar, RHSVar,
5663 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5664 emitReductionCombiner(CGF, ReductionOp);
5665 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005666 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005667 // Emit reduction for array subscript or single variable.
5668 emitReductionCombiner(CGF, ReductionOp);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005669 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005670}
5671
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005672void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005673 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005674 ArrayRef<const Expr *> LHSExprs,
5675 ArrayRef<const Expr *> RHSExprs,
5676 ArrayRef<const Expr *> ReductionOps,
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005677 ReductionOptionsTy Options) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00005678 if (!CGF.HaveInsertPoint())
5679 return;
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005680
5681 bool WithNowait = Options.WithNowait;
5682 bool SimpleReduction = Options.SimpleReduction;
5683
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005684 // Next code should be emitted for reduction:
5685 //
5686 // static kmp_critical_name lock = { 0 };
5687 //
5688 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
5689 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
5690 // ...
5691 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
5692 // *(Type<n>-1*)rhs[<n>-1]);
5693 // }
5694 //
5695 // ...
5696 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
5697 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5698 // RedList, reduce_func, &<lock>)) {
5699 // case 1:
5700 // ...
5701 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5702 // ...
5703 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5704 // break;
5705 // case 2:
5706 // ...
5707 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5708 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00005709 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005710 // break;
5711 // default:;
5712 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005713 //
5714 // if SimpleReduction is true, only the next code is generated:
5715 // ...
5716 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5717 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005718
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005719 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005720
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005721 if (SimpleReduction) {
5722 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005723 auto IPriv = Privates.begin();
5724 auto ILHS = LHSExprs.begin();
5725 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005726 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005727 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5728 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005729 ++IPriv;
5730 ++ILHS;
5731 ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005732 }
5733 return;
5734 }
5735
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005736 // 1. Build a list of reduction variables.
5737 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005738 auto Size = RHSExprs.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005739 for (const Expr *E : Privates) {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005740 if (E->getType()->isVariablyModifiedType())
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005741 // Reserve place for array size.
5742 ++Size;
5743 }
5744 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005745 QualType ReductionArrayTy =
Richard Smith772e2662019-10-04 01:25:59 +00005746 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005747 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00005748 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005749 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005750 auto IPriv = Privates.begin();
5751 unsigned Idx = 0;
5752 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
James Y Knight751fe282019-02-09 22:22:28 +00005753 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
John McCall7f416cc2015-09-08 08:05:57 +00005754 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005755 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00005756 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
5757 Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005758 if ((*IPriv)->getType()->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005759 // Store array size.
5760 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005761 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005762 llvm::Value *Size = CGF.Builder.CreateIntCast(
5763 CGF.getVLASize(
5764 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
Sander de Smalen891af03a2018-02-03 13:55:59 +00005765 .NumElts,
Alexey Bataev1189bd02016-01-26 12:20:39 +00005766 CGF.SizeTy, /*isSigned=*/false);
5767 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
5768 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005769 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005770 }
5771
5772 // 2. Emit reduce_func().
James Y Knight9871db02019-02-05 16:42:33 +00005773 llvm::Function *ReductionFn = emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005774 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
5775 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005776
5777 // 3. Create static kmp_critical_name lock = { 0 };
Alexey Bataev18fa2322018-05-02 14:20:50 +00005778 std::string Name = getName({"reduction"});
5779 llvm::Value *Lock = getCriticalRegionLock(Name);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005780
5781 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5782 // RedList, reduce_func, &<lock>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005783 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
5784 llvm::Value *ThreadId = getThreadID(CGF, Loc);
5785 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
5786 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Samuel Antao4c8035b2016-12-12 18:00:20 +00005787 ReductionList.getPointer(), CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005788 llvm::Value *Args[] = {
5789 IdentTLoc, // ident_t *<loc>
5790 ThreadId, // i32 <gtid>
5791 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
5792 ReductionArrayTySize, // size_type sizeof(RedList)
5793 RL, // void *RedList
5794 ReductionFn, // void (*) (void *, void *) <reduce_func>
5795 Lock // kmp_critical_name *&<lock>
5796 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005797 llvm::Value *Res = CGF.EmitRuntimeCall(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005798 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
5799 : OMPRTL__kmpc_reduce),
5800 Args);
5801
5802 // 5. Build switch(res)
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005803 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
5804 llvm::SwitchInst *SwInst =
5805 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005806
5807 // 6. Build case 1:
5808 // ...
5809 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5810 // ...
5811 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5812 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005813 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005814 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
5815 CGF.EmitBlock(Case1BB);
5816
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005817 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5818 llvm::Value *EndArgs[] = {
5819 IdentTLoc, // ident_t *<loc>
5820 ThreadId, // i32 <gtid>
5821 Lock // kmp_critical_name *&<lock>
5822 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005823 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5824 CodeGenFunction &CGF, PrePostActionTy &Action) {
5825 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005826 auto IPriv = Privates.begin();
5827 auto ILHS = LHSExprs.begin();
5828 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005829 for (const Expr *E : ReductionOps) {
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005830 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5831 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005832 ++IPriv;
5833 ++ILHS;
5834 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005835 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005836 };
5837 RegionCodeGenTy RCG(CodeGen);
5838 CommonActionTy Action(
5839 nullptr, llvm::None,
5840 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
5841 : OMPRTL__kmpc_end_reduce),
5842 EndArgs);
5843 RCG.setAction(Action);
5844 RCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005845
5846 CGF.EmitBranch(DefaultBB);
5847
5848 // 7. Build case 2:
5849 // ...
5850 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5851 // ...
5852 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005853 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005854 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
5855 CGF.EmitBlock(Case2BB);
5856
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005857 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
5858 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005859 auto ILHS = LHSExprs.begin();
5860 auto IRHS = RHSExprs.begin();
5861 auto IPriv = Privates.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005862 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005863 const Expr *XExpr = nullptr;
5864 const Expr *EExpr = nullptr;
5865 const Expr *UpExpr = nullptr;
5866 BinaryOperatorKind BO = BO_Comma;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005867 if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005868 if (BO->getOpcode() == BO_Assign) {
5869 XExpr = BO->getLHS();
5870 UpExpr = BO->getRHS();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005871 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005872 }
5873 // Try to emit update expression as a simple atomic.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005874 const Expr *RHSExpr = UpExpr;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005875 if (RHSExpr) {
5876 // Analyze RHS part of the whole expression.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005877 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005878 RHSExpr->IgnoreParenImpCasts())) {
5879 // If this is a conditional operator, analyze its condition for
5880 // min/max reduction operator.
5881 RHSExpr = ACO->getCond();
Alexey Bataev69a47792015-05-07 03:54:03 +00005882 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005883 if (const auto *BORHS =
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005884 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
5885 EExpr = BORHS->getRHS();
5886 BO = BORHS->getOpcode();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005887 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005888 }
5889 if (XExpr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005890 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005891 auto &&AtomicRedGen = [BO, VD,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005892 Loc](CodeGenFunction &CGF, const Expr *XExpr,
5893 const Expr *EExpr, const Expr *UpExpr) {
5894 LValue X = CGF.EmitLValue(XExpr);
5895 RValue E;
5896 if (EExpr)
5897 E = CGF.EmitAnyExpr(EExpr);
5898 CGF.EmitOMPAtomicSimpleUpdateExpr(
JF Bastien92f4ef12016-04-06 17:26:42 +00005899 X, E, BO, /*IsXLHSInRHSPart=*/true,
5900 llvm::AtomicOrdering::Monotonic, Loc,
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005901 [&CGF, UpExpr, VD, Loc](RValue XRValue) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005902 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5903 PrivateScope.addPrivate(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005904 VD, [&CGF, VD, XRValue, Loc]() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005905 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5906 CGF.emitOMPSimpleStore(
5907 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
5908 VD->getType().getNonReferenceType(), Loc);
5909 return LHSTemp;
5910 });
5911 (void)PrivateScope.Privatize();
5912 return CGF.EmitAnyExpr(UpExpr);
5913 });
5914 };
5915 if ((*IPriv)->getType()->isArrayType()) {
5916 // Emit atomic reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005917 const auto *RHSVar =
5918 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005919 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
5920 AtomicRedGen, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005921 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005922 // Emit atomic reduction for array subscript or single variable.
5923 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005924 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005925 } else {
5926 // Emit as a critical region.
5927 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
Alexey Bataev18fa2322018-05-02 14:20:50 +00005928 const Expr *, const Expr *) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005929 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev18fa2322018-05-02 14:20:50 +00005930 std::string Name = RT.getName({"atomic_reduction"});
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005931 RT.emitCriticalRegion(
Alexey Bataev18fa2322018-05-02 14:20:50 +00005932 CGF, Name,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005933 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
5934 Action.Enter(CGF);
5935 emitReductionCombiner(CGF, E);
5936 },
5937 Loc);
5938 };
5939 if ((*IPriv)->getType()->isArrayType()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005940 const auto *LHSVar =
5941 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5942 const auto *RHSVar =
5943 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005944 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5945 CritRedGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005946 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005947 CritRedGen(CGF, nullptr, nullptr, nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005948 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005949 }
Richard Trieucc3949d2016-02-18 22:34:54 +00005950 ++ILHS;
5951 ++IRHS;
5952 ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005953 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005954 };
5955 RegionCodeGenTy AtomicRCG(AtomicCodeGen);
5956 if (!WithNowait) {
5957 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
5958 llvm::Value *EndArgs[] = {
5959 IdentTLoc, // ident_t *<loc>
5960 ThreadId, // i32 <gtid>
5961 Lock // kmp_critical_name *&<lock>
5962 };
5963 CommonActionTy Action(nullptr, llvm::None,
5964 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
5965 EndArgs);
5966 AtomicRCG.setAction(Action);
5967 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005968 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005969 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005970 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005971
5972 CGF.EmitBranch(DefaultBB);
5973 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
5974}
5975
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005976/// Generates unique name for artificial threadprivate variables.
Alexey Bataev1c44e152018-03-06 18:59:43 +00005977/// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>"
5978static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix,
5979 const Expr *Ref) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005980 SmallString<256> Buffer;
5981 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev1c44e152018-03-06 18:59:43 +00005982 const clang::DeclRefExpr *DE;
5983 const VarDecl *D = ::getBaseDecl(Ref, DE);
5984 if (!D)
5985 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl());
5986 D = D->getCanonicalDecl();
Alexey Bataev18fa2322018-05-02 14:20:50 +00005987 std::string Name = CGM.getOpenMPRuntime().getName(
5988 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)});
5989 Out << Prefix << Name << "_"
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005990 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005991 return Out.str();
5992}
5993
5994/// Emits reduction initializer function:
5995/// \code
5996/// void @.red_init(void* %arg) {
5997/// %0 = bitcast void* %arg to <type>*
5998/// store <type> <init>, <type>* %0
5999/// ret void
6000/// }
6001/// \endcode
6002static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM,
6003 SourceLocation Loc,
6004 ReductionCodeGen &RCG, unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006005 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006006 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006007 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6008 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006009 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006010 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006011 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006012 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006013 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006014 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006015 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006016 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006017 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006018 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006019 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006020 Address PrivateAddr = CGF.EmitLoadOfPointer(
6021 CGF.GetAddrOfLocalVar(&Param),
6022 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6023 llvm::Value *Size = nullptr;
6024 // If the size of the reduction item is non-constant, load it from global
6025 // threadprivate variable.
6026 if (RCG.getSizes(N).second) {
6027 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6028 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006029 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006030 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6031 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006032 }
6033 RCG.emitAggregateType(CGF, N, Size);
6034 LValue SharedLVal;
6035 // If initializer uses initializer from declare reduction construct, emit a
6036 // pointer to the address of the original reduction item (reuired by reduction
6037 // initializer)
6038 if (RCG.usesReductionInitializer(N)) {
6039 Address SharedAddr =
6040 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6041 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006042 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataev21dab122018-03-09 15:20:30 +00006043 SharedAddr = CGF.EmitLoadOfPointer(
6044 SharedAddr,
6045 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006046 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy);
6047 } else {
6048 SharedLVal = CGF.MakeNaturalAlignAddrLValue(
6049 llvm::ConstantPointerNull::get(CGM.VoidPtrTy),
6050 CGM.getContext().VoidPtrTy);
6051 }
6052 // Emit the initializer:
6053 // %0 = bitcast void* %arg to <type>*
6054 // store <type> <init>, <type>* %0
6055 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal,
6056 [](CodeGenFunction &) { return false; });
6057 CGF.FinishFunction();
6058 return Fn;
6059}
6060
6061/// Emits reduction combiner function:
6062/// \code
6063/// void @.red_comb(void* %arg0, void* %arg1) {
6064/// %lhs = bitcast void* %arg0 to <type>*
6065/// %rhs = bitcast void* %arg1 to <type>*
6066/// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs)
6067/// store <type> %2, <type>* %lhs
6068/// ret void
6069/// }
6070/// \endcode
6071static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM,
6072 SourceLocation Loc,
6073 ReductionCodeGen &RCG, unsigned N,
6074 const Expr *ReductionOp,
6075 const Expr *LHS, const Expr *RHS,
6076 const Expr *PrivateRef) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006077 ASTContext &C = CGM.getContext();
6078 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl());
6079 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006080 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006081 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
6082 C.VoidPtrTy, ImplicitParamDecl::Other);
6083 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6084 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006085 Args.emplace_back(&ParamInOut);
6086 Args.emplace_back(&ParamIn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006087 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006088 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006089 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006090 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006091 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006092 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006093 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006094 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006095 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006096 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006097 llvm::Value *Size = nullptr;
6098 // If the size of the reduction item is non-constant, load it from global
6099 // threadprivate variable.
6100 if (RCG.getSizes(N).second) {
6101 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6102 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006103 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006104 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6105 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006106 }
6107 RCG.emitAggregateType(CGF, N, Size);
6108 // Remap lhs and rhs variables to the addresses of the function arguments.
6109 // %lhs = bitcast void* %arg0 to <type>*
6110 // %rhs = bitcast void* %arg1 to <type>*
6111 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006112 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006113 // Pull out the pointer to the variable.
6114 Address PtrAddr = CGF.EmitLoadOfPointer(
6115 CGF.GetAddrOfLocalVar(&ParamInOut),
6116 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6117 return CGF.Builder.CreateElementBitCast(
6118 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType()));
6119 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006120 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006121 // Pull out the pointer to the variable.
6122 Address PtrAddr = CGF.EmitLoadOfPointer(
6123 CGF.GetAddrOfLocalVar(&ParamIn),
6124 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6125 return CGF.Builder.CreateElementBitCast(
6126 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType()));
6127 });
6128 PrivateScope.Privatize();
6129 // Emit the combiner body:
6130 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs)
6131 // store <type> %2, <type>* %lhs
6132 CGM.getOpenMPRuntime().emitSingleReductionCombiner(
6133 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS),
6134 cast<DeclRefExpr>(RHS));
6135 CGF.FinishFunction();
6136 return Fn;
6137}
6138
6139/// Emits reduction finalizer function:
6140/// \code
6141/// void @.red_fini(void* %arg) {
6142/// %0 = bitcast void* %arg to <type>*
6143/// <destroy>(<type>* %0)
6144/// ret void
6145/// }
6146/// \endcode
6147static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM,
6148 SourceLocation Loc,
6149 ReductionCodeGen &RCG, unsigned N) {
6150 if (!RCG.needCleanups(N))
6151 return nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006152 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006153 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006154 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6155 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006156 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006157 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006158 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006159 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006160 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006161 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006162 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006163 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006164 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006165 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006166 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006167 Address PrivateAddr = CGF.EmitLoadOfPointer(
6168 CGF.GetAddrOfLocalVar(&Param),
6169 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6170 llvm::Value *Size = nullptr;
6171 // If the size of the reduction item is non-constant, load it from global
6172 // threadprivate variable.
6173 if (RCG.getSizes(N).second) {
6174 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6175 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006176 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006177 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6178 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006179 }
6180 RCG.emitAggregateType(CGF, N, Size);
6181 // Emit the finalizer body:
6182 // <destroy>(<type>* %0)
6183 RCG.emitCleanups(CGF, N, PrivateAddr);
6184 CGF.FinishFunction();
6185 return Fn;
6186}
6187
6188llvm::Value *CGOpenMPRuntime::emitTaskReductionInit(
6189 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
6190 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
6191 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty())
6192 return nullptr;
6193
6194 // Build typedef struct:
6195 // kmp_task_red_input {
6196 // void *reduce_shar; // shared reduction item
6197 // size_t reduce_size; // size of data item
6198 // void *reduce_init; // data initialization routine
6199 // void *reduce_fini; // data finalization routine
6200 // void *reduce_comb; // data combiner routine
6201 // kmp_task_red_flags_t flags; // flags for additional info from compiler
6202 // } kmp_task_red_input_t;
6203 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006204 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t");
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006205 RD->startDefinition();
6206 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6207 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType());
6208 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6209 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6210 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6211 const FieldDecl *FlagsFD = addFieldToRecordDecl(
6212 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false));
6213 RD->completeDefinition();
6214 QualType RDType = C.getRecordType(RD);
6215 unsigned Size = Data.ReductionVars.size();
6216 llvm::APInt ArraySize(/*numBits=*/64, Size);
6217 QualType ArrayRDType = C.getConstantArrayType(
Richard Smith772e2662019-10-04 01:25:59 +00006218 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006219 // kmp_task_red_input_t .rd_input.[Size];
6220 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input.");
6221 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies,
6222 Data.ReductionOps);
6223 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) {
6224 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt];
6225 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0),
6226 llvm::ConstantInt::get(CGM.SizeTy, Cnt)};
6227 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP(
6228 TaskRedInput.getPointer(), Idxs,
6229 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc,
6230 ".rd_input.gep.");
6231 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType);
6232 // ElemLVal.reduce_shar = &Shareds[Cnt];
6233 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD);
6234 RCG.emitSharedLValue(CGF, Cnt);
6235 llvm::Value *CastedShared =
6236 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer());
6237 CGF.EmitStoreOfScalar(CastedShared, SharedLVal);
6238 RCG.emitAggregateType(CGF, Cnt);
6239 llvm::Value *SizeValInChars;
6240 llvm::Value *SizeVal;
6241 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt);
6242 // We use delayed creation/initialization for VLAs, array sections and
6243 // custom reduction initializations. It is required because runtime does not
6244 // provide the way to pass the sizes of VLAs/array sections to
6245 // initializer/combiner/finalizer functions and does not pass the pointer to
6246 // original reduction item to the initializer. Instead threadprivate global
6247 // variables are used to store these values and use them in the functions.
6248 bool DelayedCreation = !!SizeVal;
6249 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy,
6250 /*isSigned=*/false);
6251 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD);
6252 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal);
6253 // ElemLVal.reduce_init = init;
6254 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD);
6255 llvm::Value *InitAddr =
6256 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt));
6257 CGF.EmitStoreOfScalar(InitAddr, InitLVal);
6258 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt);
6259 // ElemLVal.reduce_fini = fini;
6260 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD);
6261 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt);
6262 llvm::Value *FiniAddr = Fini
6263 ? CGF.EmitCastToVoidPtr(Fini)
6264 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy);
6265 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal);
6266 // ElemLVal.reduce_comb = comb;
6267 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD);
6268 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction(
6269 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt],
6270 RHSExprs[Cnt], Data.ReductionCopies[Cnt]));
6271 CGF.EmitStoreOfScalar(CombAddr, CombLVal);
6272 // ElemLVal.flags = 0;
6273 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD);
6274 if (DelayedCreation) {
6275 CGF.EmitStoreOfScalar(
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006276 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006277 FlagsLVal);
6278 } else
6279 CGF.EmitNullInitialization(FlagsLVal.getAddress(), FlagsLVal.getType());
6280 }
6281 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void
6282 // *data);
6283 llvm::Value *Args[] = {
6284 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6285 /*isSigned=*/true),
6286 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true),
6287 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(),
6288 CGM.VoidPtrTy)};
6289 return CGF.EmitRuntimeCall(
6290 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args);
6291}
6292
6293void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
6294 SourceLocation Loc,
6295 ReductionCodeGen &RCG,
6296 unsigned N) {
6297 auto Sizes = RCG.getSizes(N);
6298 // Emit threadprivate global variable if the type is non-constant
6299 // (Sizes.second = nullptr).
6300 if (Sizes.second) {
6301 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy,
6302 /*isSigned=*/false);
6303 Address SizeAddr = getAddrOfArtificialThreadPrivate(
6304 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006305 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006306 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false);
6307 }
6308 // Store address of the original reduction item if custom initializer is used.
6309 if (RCG.usesReductionInitializer(N)) {
6310 Address SharedAddr = getAddrOfArtificialThreadPrivate(
6311 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006312 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006313 CGF.Builder.CreateStore(
6314 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6315 RCG.getSharedLValue(N).getPointer(), CGM.VoidPtrTy),
6316 SharedAddr, /*IsVolatile=*/false);
6317 }
6318}
6319
6320Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF,
6321 SourceLocation Loc,
6322 llvm::Value *ReductionsPtr,
6323 LValue SharedLVal) {
6324 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
6325 // *d);
6326 llvm::Value *Args[] = {
6327 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6328 /*isSigned=*/true),
6329 ReductionsPtr,
6330 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(SharedLVal.getPointer(),
6331 CGM.VoidPtrTy)};
6332 return Address(
6333 CGF.EmitRuntimeCall(
6334 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args),
6335 SharedLVal.getAlignment());
6336}
6337
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006338void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
6339 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006340 if (!CGF.HaveInsertPoint())
6341 return;
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006342 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
6343 // global_tid);
6344 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
6345 // Ignore return result until untied tasks are supported.
6346 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00006347 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
6348 Region->emitUntiedSwitch(CGF);
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006349}
6350
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006351void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006352 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00006353 const RegionCodeGenTy &CodeGen,
6354 bool HasCancel) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006355 if (!CGF.HaveInsertPoint())
6356 return;
Alexey Bataev25e5b442015-09-15 12:52:43 +00006357 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006358 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00006359}
6360
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006361namespace {
6362enum RTCancelKind {
6363 CancelNoreq = 0,
6364 CancelParallel = 1,
6365 CancelLoop = 2,
6366 CancelSections = 3,
6367 CancelTaskgroup = 4
6368};
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00006369} // anonymous namespace
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006370
6371static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
6372 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00006373 if (CancelRegion == OMPD_parallel)
6374 CancelKind = CancelParallel;
6375 else if (CancelRegion == OMPD_for)
6376 CancelKind = CancelLoop;
6377 else if (CancelRegion == OMPD_sections)
6378 CancelKind = CancelSections;
6379 else {
6380 assert(CancelRegion == OMPD_taskgroup);
6381 CancelKind = CancelTaskgroup;
6382 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006383 return CancelKind;
6384}
6385
6386void CGOpenMPRuntime::emitCancellationPointCall(
6387 CodeGenFunction &CGF, SourceLocation Loc,
6388 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006389 if (!CGF.HaveInsertPoint())
6390 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006391 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
6392 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006393 if (auto *OMPRegionInfo =
6394 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Jonas Hahnfeldb07931f2017-02-17 18:32:58 +00006395 // For 'cancellation point taskgroup', the task region info may not have a
6396 // cancel. This may instead happen in another adjacent task.
6397 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006398 llvm::Value *Args[] = {
6399 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
6400 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006401 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006402 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006403 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
6404 // if (__kmpc_cancellationpoint()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006405 // exit from construct;
6406 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006407 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6408 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6409 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006410 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6411 CGF.EmitBlock(ExitBB);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006412 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006413 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev25e5b442015-09-15 12:52:43 +00006414 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006415 CGF.EmitBranchThroughCleanup(CancelDest);
6416 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6417 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006418 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006419}
6420
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006421void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00006422 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006423 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006424 if (!CGF.HaveInsertPoint())
6425 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006426 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
6427 // kmp_int32 cncl_kind);
6428 if (auto *OMPRegionInfo =
6429 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006430 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF,
6431 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006432 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev87933c72015-09-18 08:07:34 +00006433 llvm::Value *Args[] = {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006434 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
Alexey Bataev87933c72015-09-18 08:07:34 +00006435 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
6436 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006437 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006438 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
Alexey Bataev87933c72015-09-18 08:07:34 +00006439 // if (__kmpc_cancel()) {
Alexey Bataev87933c72015-09-18 08:07:34 +00006440 // exit from construct;
6441 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006442 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6443 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6444 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev87933c72015-09-18 08:07:34 +00006445 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6446 CGF.EmitBlock(ExitBB);
Alexey Bataev87933c72015-09-18 08:07:34 +00006447 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006448 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev87933c72015-09-18 08:07:34 +00006449 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6450 CGF.EmitBranchThroughCleanup(CancelDest);
6451 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6452 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006453 if (IfCond) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006454 emitOMPIfClause(CGF, IfCond, ThenGen,
6455 [](CodeGenFunction &, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006456 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006457 RegionCodeGenTy ThenRCG(ThenGen);
6458 ThenRCG(CGF);
6459 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006460 }
6461}
Samuel Antaobed3c462015-10-02 16:14:20 +00006462
Samuel Antaoee8fb302016-01-06 13:42:12 +00006463void CGOpenMPRuntime::emitTargetOutlinedFunction(
6464 const OMPExecutableDirective &D, StringRef ParentName,
6465 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006466 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00006467 assert(!ParentName.empty() && "Invalid target region parent name!");
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00006468 HasEmittedTargetRegion = true;
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006469 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
6470 IsOffloadEntry, CodeGen);
6471}
6472
6473void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
6474 const OMPExecutableDirective &D, StringRef ParentName,
6475 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6476 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antao2de62b02016-02-13 23:35:10 +00006477 // Create a unique name for the entry function using the source location
6478 // information of the current target region. The name will be something like:
Samuel Antaoee8fb302016-01-06 13:42:12 +00006479 //
Samuel Antao2de62b02016-02-13 23:35:10 +00006480 // __omp_offloading_DD_FFFF_PP_lBB
Samuel Antaoee8fb302016-01-06 13:42:12 +00006481 //
6482 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
Samuel Antao2de62b02016-02-13 23:35:10 +00006483 // mangled name of the function that encloses the target region and BB is the
6484 // line number of the target region.
Samuel Antaoee8fb302016-01-06 13:42:12 +00006485
6486 unsigned DeviceID;
6487 unsigned FileID;
6488 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00006489 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00006490 Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006491 SmallString<64> EntryFnName;
6492 {
6493 llvm::raw_svector_ostream OS(EntryFnName);
Samuel Antao2de62b02016-02-13 23:35:10 +00006494 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
6495 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00006496 }
6497
Alexey Bataev475a7442018-01-12 19:39:11 +00006498 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006499
Samuel Antaobed3c462015-10-02 16:14:20 +00006500 CodeGenFunction CGF(CGM, true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006501 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
Samuel Antaobed3c462015-10-02 16:14:20 +00006502 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006503
Samuel Antao6d004262016-06-16 18:39:34 +00006504 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006505
6506 // If this target outline function is not an offload entry, we don't need to
6507 // register it.
6508 if (!IsOffloadEntry)
6509 return;
6510
6511 // The target region ID is used by the runtime library to identify the current
6512 // target region, so it only has to be unique and not necessarily point to
6513 // anything. It could be the pointer to the outlined function that implements
6514 // the target region, but we aren't using that so that the compiler doesn't
6515 // need to keep that, and could therefore inline the host function if proven
6516 // worthwhile during optimization. In the other hand, if emitting code for the
6517 // device, the ID has to be the function address so that it can retrieved from
6518 // the offloading entry and launched by the runtime library. We also mark the
6519 // outlined function to have external linkage in case we are emitting code for
6520 // the device, because these functions will be entry points to the device.
6521
6522 if (CGM.getLangOpts().OpenMPIsDevice) {
6523 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
Alexey Bataev9a700172018-05-08 14:16:57 +00006524 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Rafael Espindolacbca4872018-01-11 22:15:12 +00006525 OutlinedFn->setDSOLocal(false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006526 } else {
Alexey Bataevc15ea702018-05-09 18:02:37 +00006527 std::string Name = getName({EntryFnName, "region_id"});
Samuel Antaoee8fb302016-01-06 13:42:12 +00006528 OutlinedFnID = new llvm::GlobalVariable(
6529 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
Alexey Bataev9a700172018-05-08 14:16:57 +00006530 llvm::GlobalValue::WeakAnyLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006531 llvm::Constant::getNullValue(CGM.Int8Ty), Name);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006532 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00006533
6534 // Register the information for the entry associated with this target region.
6535 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
Samuel Antaof83efdb2017-01-05 16:02:49 +00006536 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID,
Alexey Bataev03f270c2018-03-30 18:31:07 +00006537 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion);
Samuel Antaobed3c462015-10-02 16:14:20 +00006538}
6539
Alexey Bataev5c427362019-04-10 19:11:33 +00006540/// Checks if the expression is constant or does not have non-trivial function
6541/// calls.
6542static bool isTrivial(ASTContext &Ctx, const Expr * E) {
6543 // We can skip constant expressions.
6544 // We can skip expressions with trivial calls or simple expressions.
6545 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) ||
6546 !E->hasNonTrivialCall(Ctx)) &&
6547 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true);
6548}
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006549
Alexey Bataev5c427362019-04-10 19:11:33 +00006550const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx,
6551 const Stmt *Body) {
6552 const Stmt *Child = Body->IgnoreContainers();
6553 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) {
6554 Child = nullptr;
6555 for (const Stmt *S : C->body()) {
6556 if (const auto *E = dyn_cast<Expr>(S)) {
6557 if (isTrivial(Ctx, E))
6558 continue;
6559 }
6560 // Some of the statements can be ignored.
6561 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) ||
6562 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S))
6563 continue;
6564 // Analyze declarations.
6565 if (const auto *DS = dyn_cast<DeclStmt>(S)) {
6566 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) {
6567 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6568 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6569 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6570 isa<UsingDirectiveDecl>(D) ||
6571 isa<OMPDeclareReductionDecl>(D) ||
6572 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6573 return true;
6574 const auto *VD = dyn_cast<VarDecl>(D);
6575 if (!VD)
6576 return false;
6577 return VD->isConstexpr() ||
6578 ((VD->getType().isTrivialType(Ctx) ||
6579 VD->getType()->isReferenceType()) &&
6580 (!VD->hasInit() || isTrivial(Ctx, VD->getInit())));
6581 }))
6582 continue;
6583 }
6584 // Found multiple children - cannot get the one child only.
6585 if (Child)
6586 return nullptr;
6587 Child = S;
6588 }
6589 if (Child)
6590 Child = Child->IgnoreContainers();
6591 }
6592 return Child;
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006593}
6594
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006595/// Emit the number of teams for a target directive. Inspect the num_teams
6596/// clause associated with a teams construct combined or closely nested
6597/// with the target directive.
6598///
6599/// Emit a team of size one for directives such as 'target parallel' that
6600/// have no associated teams construct.
6601///
6602/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006603static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006604emitNumTeamsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006605 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006606 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6607 "Clauses associated with the teams directive expected to be emitted "
6608 "only for the host!");
6609 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6610 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6611 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006612 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006613 switch (DirectiveKind) {
6614 case OMPD_target: {
6615 const auto *CS = D.getInnermostCapturedStmt();
6616 const auto *Body =
6617 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
6618 const Stmt *ChildStmt =
6619 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body);
6620 if (const auto *NestedDir =
6621 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6622 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) {
6623 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) {
6624 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6625 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6626 const Expr *NumTeams =
6627 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6628 llvm::Value *NumTeamsVal =
6629 CGF.EmitScalarExpr(NumTeams,
6630 /*IgnoreResultAssign*/ true);
6631 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006632 /*isSigned=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00006633 }
6634 return Bld.getInt32(0);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006635 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006636 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) ||
6637 isOpenMPSimdDirective(NestedDir->getDirectiveKind()))
6638 return Bld.getInt32(1);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006639 return Bld.getInt32(0);
6640 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006641 return nullptr;
Samuel Antaob68e2db2016-03-03 16:20:23 +00006642 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006643 case OMPD_target_teams:
6644 case OMPD_target_teams_distribute:
6645 case OMPD_target_teams_distribute_simd:
6646 case OMPD_target_teams_distribute_parallel_for:
6647 case OMPD_target_teams_distribute_parallel_for_simd: {
6648 if (D.hasClausesOfKind<OMPNumTeamsClause>()) {
6649 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF);
6650 const Expr *NumTeams =
6651 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6652 llvm::Value *NumTeamsVal =
6653 CGF.EmitScalarExpr(NumTeams,
6654 /*IgnoreResultAssign*/ true);
6655 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006656 /*isSigned=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00006657 }
6658 return Bld.getInt32(0);
6659 }
6660 case OMPD_target_parallel:
6661 case OMPD_target_parallel_for:
6662 case OMPD_target_parallel_for_simd:
6663 case OMPD_target_simd:
6664 return Bld.getInt32(1);
6665 case OMPD_parallel:
6666 case OMPD_for:
6667 case OMPD_parallel_for:
6668 case OMPD_parallel_sections:
6669 case OMPD_for_simd:
6670 case OMPD_parallel_for_simd:
6671 case OMPD_cancel:
6672 case OMPD_cancellation_point:
6673 case OMPD_ordered:
6674 case OMPD_threadprivate:
6675 case OMPD_allocate:
6676 case OMPD_task:
6677 case OMPD_simd:
6678 case OMPD_sections:
6679 case OMPD_section:
6680 case OMPD_single:
6681 case OMPD_master:
6682 case OMPD_critical:
6683 case OMPD_taskyield:
6684 case OMPD_barrier:
6685 case OMPD_taskwait:
6686 case OMPD_taskgroup:
6687 case OMPD_atomic:
6688 case OMPD_flush:
6689 case OMPD_teams:
6690 case OMPD_target_data:
6691 case OMPD_target_exit_data:
6692 case OMPD_target_enter_data:
6693 case OMPD_distribute:
6694 case OMPD_distribute_simd:
6695 case OMPD_distribute_parallel_for:
6696 case OMPD_distribute_parallel_for_simd:
6697 case OMPD_teams_distribute:
6698 case OMPD_teams_distribute_simd:
6699 case OMPD_teams_distribute_parallel_for:
6700 case OMPD_teams_distribute_parallel_for_simd:
6701 case OMPD_target_update:
6702 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00006703 case OMPD_declare_variant:
Alexey Bataev5c427362019-04-10 19:11:33 +00006704 case OMPD_declare_target:
6705 case OMPD_end_declare_target:
6706 case OMPD_declare_reduction:
6707 case OMPD_declare_mapper:
6708 case OMPD_taskloop:
6709 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00006710 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00006711 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00006712 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04006713 case OMPD_parallel_master_taskloop_simd:
Alexey Bataev5c427362019-04-10 19:11:33 +00006714 case OMPD_requires:
6715 case OMPD_unknown:
6716 break;
6717 }
6718 llvm_unreachable("Unexpected directive kind.");
6719}
Samuel Antaob68e2db2016-03-03 16:20:23 +00006720
Alexey Bataev5c427362019-04-10 19:11:33 +00006721static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS,
6722 llvm::Value *DefaultThreadLimitVal) {
6723 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6724 CGF.getContext(), CS->getCapturedStmt());
6725 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6726 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) {
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006727 llvm::Value *NumThreads = nullptr;
6728 llvm::Value *CondVal = nullptr;
6729 // Handle if clause. If if clause present, the number of threads is
6730 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6731 if (Dir->hasClausesOfKind<OMPIfClause>()) {
6732 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6733 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6734 const OMPIfClause *IfClause = nullptr;
6735 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) {
6736 if (C->getNameModifier() == OMPD_unknown ||
6737 C->getNameModifier() == OMPD_parallel) {
6738 IfClause = C;
6739 break;
6740 }
6741 }
6742 if (IfClause) {
6743 const Expr *Cond = IfClause->getCondition();
6744 bool Result;
6745 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6746 if (!Result)
6747 return CGF.Builder.getInt32(1);
6748 } else {
6749 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange());
6750 if (const auto *PreInit =
6751 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) {
6752 for (const auto *I : PreInit->decls()) {
6753 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6754 CGF.EmitVarDecl(cast<VarDecl>(*I));
6755 } else {
6756 CodeGenFunction::AutoVarEmission Emission =
6757 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6758 CGF.EmitAutoVarCleanups(Emission);
6759 }
6760 }
6761 }
6762 CondVal = CGF.EvaluateExprAsBool(Cond);
6763 }
6764 }
6765 }
6766 // Check the value of num_threads clause iff if clause was not specified
6767 // or is not evaluated to false.
Alexey Bataev5c427362019-04-10 19:11:33 +00006768 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) {
6769 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6770 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6771 const auto *NumThreadsClause =
6772 Dir->getSingleClause<OMPNumThreadsClause>();
6773 CodeGenFunction::LexicalScope Scope(
6774 CGF, NumThreadsClause->getNumThreads()->getSourceRange());
6775 if (const auto *PreInit =
6776 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6777 for (const auto *I : PreInit->decls()) {
6778 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6779 CGF.EmitVarDecl(cast<VarDecl>(*I));
6780 } else {
6781 CodeGenFunction::AutoVarEmission Emission =
6782 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6783 CGF.EmitAutoVarCleanups(Emission);
6784 }
6785 }
6786 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006787 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads());
Alexey Bataev5c427362019-04-10 19:11:33 +00006788 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006789 /*isSigned=*/false);
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006790 if (DefaultThreadLimitVal)
6791 NumThreads = CGF.Builder.CreateSelect(
6792 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads),
6793 DefaultThreadLimitVal, NumThreads);
6794 } else {
6795 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal
6796 : CGF.Builder.getInt32(0);
Alexey Bataev5c427362019-04-10 19:11:33 +00006797 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006798 // Process condition of the if clause.
6799 if (CondVal) {
6800 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads,
6801 CGF.Builder.getInt32(1));
6802 }
6803 return NumThreads;
Alexey Bataev5c427362019-04-10 19:11:33 +00006804 }
6805 if (isOpenMPSimdDirective(Dir->getDirectiveKind()))
6806 return CGF.Builder.getInt32(1);
6807 return DefaultThreadLimitVal;
6808 }
6809 return DefaultThreadLimitVal ? DefaultThreadLimitVal
6810 : CGF.Builder.getInt32(0);
Samuel Antaob68e2db2016-03-03 16:20:23 +00006811}
6812
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006813/// Emit the number of threads for a target directive. Inspect the
6814/// thread_limit clause associated with a teams construct combined or closely
6815/// nested with the target directive.
6816///
6817/// Emit the num_threads clause for directives such as 'target parallel' that
6818/// have no associated teams construct.
6819///
6820/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006821static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006822emitNumThreadsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006823 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006824 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6825 "Clauses associated with the teams directive expected to be emitted "
6826 "only for the host!");
6827 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6828 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6829 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006830 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006831 llvm::Value *ThreadLimitVal = nullptr;
6832 llvm::Value *NumThreadsVal = nullptr;
6833 switch (DirectiveKind) {
6834 case OMPD_target: {
6835 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6836 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6837 return NumThreads;
6838 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6839 CGF.getContext(), CS->getCapturedStmt());
6840 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6841 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) {
6842 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6843 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6844 const auto *ThreadLimitClause =
6845 Dir->getSingleClause<OMPThreadLimitClause>();
6846 CodeGenFunction::LexicalScope Scope(
6847 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange());
6848 if (const auto *PreInit =
6849 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6850 for (const auto *I : PreInit->decls()) {
6851 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6852 CGF.EmitVarDecl(cast<VarDecl>(*I));
6853 } else {
6854 CodeGenFunction::AutoVarEmission Emission =
6855 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6856 CGF.EmitAutoVarCleanups(Emission);
6857 }
6858 }
6859 }
6860 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6861 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6862 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006863 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006864 }
6865 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) &&
6866 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) {
6867 CS = Dir->getInnermostCapturedStmt();
6868 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6869 CGF.getContext(), CS->getCapturedStmt());
6870 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6871 }
6872 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) &&
6873 !isOpenMPSimdDirective(Dir->getDirectiveKind())) {
6874 CS = Dir->getInnermostCapturedStmt();
6875 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6876 return NumThreads;
6877 }
6878 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind()))
6879 return Bld.getInt32(1);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006880 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006881 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6882 }
6883 case OMPD_target_teams: {
6884 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6885 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6886 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6887 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6888 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6889 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006890 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006891 }
6892 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6893 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6894 return NumThreads;
6895 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6896 CGF.getContext(), CS->getCapturedStmt());
6897 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6898 if (Dir->getDirectiveKind() == OMPD_distribute) {
6899 CS = Dir->getInnermostCapturedStmt();
6900 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6901 return NumThreads;
6902 }
6903 }
6904 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6905 }
6906 case OMPD_target_teams_distribute:
6907 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6908 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6909 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6910 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6911 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6912 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006913 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006914 }
6915 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal);
6916 case OMPD_target_parallel:
6917 case OMPD_target_parallel_for:
6918 case OMPD_target_parallel_for_simd:
6919 case OMPD_target_teams_distribute_parallel_for:
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006920 case OMPD_target_teams_distribute_parallel_for_simd: {
6921 llvm::Value *CondVal = nullptr;
6922 // Handle if clause. If if clause present, the number of threads is
6923 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6924 if (D.hasClausesOfKind<OMPIfClause>()) {
6925 const OMPIfClause *IfClause = nullptr;
6926 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) {
6927 if (C->getNameModifier() == OMPD_unknown ||
6928 C->getNameModifier() == OMPD_parallel) {
6929 IfClause = C;
6930 break;
6931 }
6932 }
6933 if (IfClause) {
6934 const Expr *Cond = IfClause->getCondition();
6935 bool Result;
6936 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6937 if (!Result)
6938 return Bld.getInt32(1);
6939 } else {
6940 CodeGenFunction::RunCleanupsScope Scope(CGF);
6941 CondVal = CGF.EvaluateExprAsBool(Cond);
6942 }
6943 }
6944 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006945 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6946 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6947 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6948 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6949 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6950 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006951 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006952 }
6953 if (D.hasClausesOfKind<OMPNumThreadsClause>()) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006954 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
Alexey Bataev5c427362019-04-10 19:11:33 +00006955 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>();
6956 llvm::Value *NumThreads = CGF.EmitScalarExpr(
6957 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true);
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006958 NumThreadsVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006959 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006960 ThreadLimitVal = ThreadLimitVal
Alexey Bataev5c427362019-04-10 19:11:33 +00006961 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal,
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006962 ThreadLimitVal),
6963 NumThreadsVal, ThreadLimitVal)
6964 : NumThreadsVal;
Alexey Bataev50a1c782017-12-01 21:31:08 +00006965 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006966 if (!ThreadLimitVal)
6967 ThreadLimitVal = Bld.getInt32(0);
6968 if (CondVal)
6969 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1));
6970 return ThreadLimitVal;
6971 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006972 case OMPD_target_teams_distribute_simd:
6973 case OMPD_target_simd:
6974 return Bld.getInt32(1);
6975 case OMPD_parallel:
6976 case OMPD_for:
6977 case OMPD_parallel_for:
6978 case OMPD_parallel_sections:
6979 case OMPD_for_simd:
6980 case OMPD_parallel_for_simd:
6981 case OMPD_cancel:
6982 case OMPD_cancellation_point:
6983 case OMPD_ordered:
6984 case OMPD_threadprivate:
6985 case OMPD_allocate:
6986 case OMPD_task:
6987 case OMPD_simd:
6988 case OMPD_sections:
6989 case OMPD_section:
6990 case OMPD_single:
6991 case OMPD_master:
6992 case OMPD_critical:
6993 case OMPD_taskyield:
6994 case OMPD_barrier:
6995 case OMPD_taskwait:
6996 case OMPD_taskgroup:
6997 case OMPD_atomic:
6998 case OMPD_flush:
6999 case OMPD_teams:
7000 case OMPD_target_data:
7001 case OMPD_target_exit_data:
7002 case OMPD_target_enter_data:
7003 case OMPD_distribute:
7004 case OMPD_distribute_simd:
7005 case OMPD_distribute_parallel_for:
7006 case OMPD_distribute_parallel_for_simd:
7007 case OMPD_teams_distribute:
7008 case OMPD_teams_distribute_simd:
7009 case OMPD_teams_distribute_parallel_for:
7010 case OMPD_teams_distribute_parallel_for_simd:
7011 case OMPD_target_update:
7012 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00007013 case OMPD_declare_variant:
Alexey Bataev5c427362019-04-10 19:11:33 +00007014 case OMPD_declare_target:
7015 case OMPD_end_declare_target:
7016 case OMPD_declare_reduction:
7017 case OMPD_declare_mapper:
7018 case OMPD_taskloop:
7019 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00007020 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00007021 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00007022 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04007023 case OMPD_parallel_master_taskloop_simd:
Alexey Bataev5c427362019-04-10 19:11:33 +00007024 case OMPD_requires:
7025 case OMPD_unknown:
7026 break;
Samuel Antaob68e2db2016-03-03 16:20:23 +00007027 }
Alexey Bataev5c427362019-04-10 19:11:33 +00007028 llvm_unreachable("Unsupported directive kind.");
Samuel Antaob68e2db2016-03-03 16:20:23 +00007029}
7030
Samuel Antao86ace552016-04-27 22:40:57 +00007031namespace {
Alexey Bataevb3638132018-07-19 16:34:13 +00007032LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
7033
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007034// Utility to handle information from clauses associated with a given
Samuel Antao86ace552016-04-27 22:40:57 +00007035// construct that use mappable expressions (e.g. 'map' clause, 'to' clause).
7036// It provides a convenient interface to obtain the information and generate
7037// code for that information.
7038class MappableExprsHandler {
7039public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007040 /// Values for bit flags used to specify the mapping type for
Samuel Antao86ace552016-04-27 22:40:57 +00007041 /// offloading.
Alexey Bataevb3638132018-07-19 16:34:13 +00007042 enum OpenMPOffloadMappingFlags : uint64_t {
7043 /// No flags
7044 OMP_MAP_NONE = 0x0,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007045 /// Allocate memory on the device and move data from host to device.
Samuel Antao86ace552016-04-27 22:40:57 +00007046 OMP_MAP_TO = 0x01,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007047 /// Allocate memory on the device and move data from device to host.
Samuel Antao86ace552016-04-27 22:40:57 +00007048 OMP_MAP_FROM = 0x02,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007049 /// Always perform the requested mapping action on the element, even
Samuel Antao86ace552016-04-27 22:40:57 +00007050 /// if it was already mapped before.
7051 OMP_MAP_ALWAYS = 0x04,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007052 /// Delete the element from the device environment, ignoring the
Samuel Antao86ace552016-04-27 22:40:57 +00007053 /// current reference count associated with the element.
Samuel Antao6782e942016-05-26 16:48:10 +00007054 OMP_MAP_DELETE = 0x08,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007055 /// The element being mapped is a pointer-pointee pair; both the
George Rokos065755d2017-11-07 18:27:04 +00007056 /// pointer and the pointee should be mapped.
7057 OMP_MAP_PTR_AND_OBJ = 0x10,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007058 /// This flags signals that the base address of an entry should be
George Rokos065755d2017-11-07 18:27:04 +00007059 /// passed to the target kernel as an argument.
7060 OMP_MAP_TARGET_PARAM = 0x20,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007061 /// Signal that the runtime library has to return the device pointer
George Rokos065755d2017-11-07 18:27:04 +00007062 /// in the current position for the data being mapped. Used when we have the
7063 /// use_device_ptr clause.
7064 OMP_MAP_RETURN_PARAM = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007065 /// This flag signals that the reference being passed is a pointer to
Samuel Antaod486f842016-05-26 16:53:38 +00007066 /// private data.
George Rokos065755d2017-11-07 18:27:04 +00007067 OMP_MAP_PRIVATE = 0x80,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007068 /// Pass the element to the device by value.
George Rokos065755d2017-11-07 18:27:04 +00007069 OMP_MAP_LITERAL = 0x100,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007070 /// Implicit map
7071 OMP_MAP_IMPLICIT = 0x200,
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007072 /// Close is a hint to the runtime to allocate memory close to
7073 /// the target device.
7074 OMP_MAP_CLOSE = 0x400,
Alexey Bataevb3638132018-07-19 16:34:13 +00007075 /// The 16 MSBs of the flags indicate whether the entry is member of some
7076 /// struct/class.
7077 OMP_MAP_MEMBER_OF = 0xffff000000000000,
7078 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF),
Samuel Antao86ace552016-04-27 22:40:57 +00007079 };
7080
Michael Krused47b9432019-08-05 18:43:21 +00007081 /// Get the offset of the OMP_MAP_MEMBER_OF field.
7082 static unsigned getFlagMemberOffset() {
7083 unsigned Offset = 0;
7084 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1);
7085 Remain = Remain >> 1)
7086 Offset++;
7087 return Offset;
7088 }
7089
Samuel Antaocc10b852016-07-28 14:23:26 +00007090 /// Class that associates information with a base pointer to be passed to the
7091 /// runtime library.
7092 class BasePointerInfo {
7093 /// The base pointer.
7094 llvm::Value *Ptr = nullptr;
7095 /// The base declaration that refers to this device pointer, or null if
7096 /// there is none.
7097 const ValueDecl *DevPtrDecl = nullptr;
7098
7099 public:
7100 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr)
7101 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {}
7102 llvm::Value *operator*() const { return Ptr; }
7103 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; }
7104 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; }
7105 };
7106
Alexey Bataevb3638132018-07-19 16:34:13 +00007107 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>;
7108 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>;
7109 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>;
7110
7111 /// Map between a struct and the its lowest & highest elements which have been
7112 /// mapped.
7113 /// [ValueDecl *] --> {LE(FieldIndex, Pointer),
7114 /// HE(FieldIndex, Pointer)}
7115 struct StructRangeInfoTy {
7116 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = {
7117 0, Address::invalid()};
7118 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = {
7119 0, Address::invalid()};
7120 Address Base = Address::invalid();
7121 };
Samuel Antao86ace552016-04-27 22:40:57 +00007122
7123private:
Alexey Bataevb3638132018-07-19 16:34:13 +00007124 /// Kind that defines how a device pointer has to be returned.
7125 struct MapInfo {
7126 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
7127 OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
Kelvin Lief579432018-12-18 22:18:41 +00007128 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataevb3638132018-07-19 16:34:13 +00007129 bool ReturnDevicePointer = false;
7130 bool IsImplicit = false;
7131
7132 MapInfo() = default;
7133 MapInfo(
7134 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Kelvin Lief579432018-12-18 22:18:41 +00007135 OpenMPMapClauseKind MapType,
7136 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007137 bool ReturnDevicePointer, bool IsImplicit)
Kelvin Lief579432018-12-18 22:18:41 +00007138 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
Alexey Bataevb3638132018-07-19 16:34:13 +00007139 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {}
7140 };
7141
7142 /// If use_device_ptr is used on a pointer which is a struct member and there
7143 /// is no map information about it, then emission of that entry is deferred
7144 /// until the whole struct has been processed.
7145 struct DeferredDevicePtrEntryTy {
7146 const Expr *IE = nullptr;
7147 const ValueDecl *VD = nullptr;
7148
7149 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD)
7150 : IE(IE), VD(VD) {}
7151 };
7152
Michael Krused47b9432019-08-05 18:43:21 +00007153 /// The target directive from where the mappable clauses were extracted. It
7154 /// is either a executable directive or a user-defined mapper directive.
7155 llvm::PointerUnion<const OMPExecutableDirective *,
7156 const OMPDeclareMapperDecl *>
7157 CurDir;
Samuel Antao86ace552016-04-27 22:40:57 +00007158
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007159 /// Function the directive is being generated for.
Samuel Antao86ace552016-04-27 22:40:57 +00007160 CodeGenFunction &CGF;
7161
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007162 /// Set of all first private variables in the current directive.
Alexey Bataevf288cf92019-06-27 18:53:07 +00007163 /// bool data is set to true if the variable is implicitly marked as
7164 /// firstprivate, false otherwise.
7165 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls;
Samuel Antaod486f842016-05-26 16:53:38 +00007166
Samuel Antao6890b092016-07-28 14:25:09 +00007167 /// Map between device pointer declarations and their expression components.
7168 /// The key value for declarations in 'this' is null.
7169 llvm::DenseMap<
7170 const ValueDecl *,
7171 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7172 DevPointersMap;
7173
Samuel Antao86ace552016-04-27 22:40:57 +00007174 llvm::Value *getExprTypeSize(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007175 QualType ExprTy = E->getType().getCanonicalType();
Samuel Antao86ace552016-04-27 22:40:57 +00007176
7177 // Reference types are ignored for mapping purposes.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007178 if (const auto *RefTy = ExprTy->getAs<ReferenceType>())
Samuel Antao86ace552016-04-27 22:40:57 +00007179 ExprTy = RefTy->getPointeeType().getCanonicalType();
7180
7181 // Given that an array section is considered a built-in type, we need to
7182 // do the calculation based on the length of the section instead of relying
7183 // on CGF.getTypeSize(E->getType()).
7184 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) {
7185 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType(
7186 OAE->getBase()->IgnoreParenImpCasts())
7187 .getCanonicalType();
7188
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007189 // If there is no length associated with the expression and lower bound is
7190 // not specified too, that means we are using the whole length of the
7191 // base.
7192 if (!OAE->getLength() && OAE->getColonLoc().isValid() &&
7193 !OAE->getLowerBound())
Samuel Antao86ace552016-04-27 22:40:57 +00007194 return CGF.getTypeSize(BaseTy);
7195
7196 llvm::Value *ElemSize;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007197 if (const auto *PTy = BaseTy->getAs<PointerType>()) {
Samuel Antao86ace552016-04-27 22:40:57 +00007198 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007199 } else {
7200 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr());
Samuel Antao86ace552016-04-27 22:40:57 +00007201 assert(ATy && "Expecting array type if not a pointer type.");
7202 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType());
7203 }
7204
7205 // If we don't have a length at this point, that is because we have an
7206 // array section with a single element.
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007207 if (!OAE->getLength() && OAE->getColonLoc().isInvalid())
Samuel Antao86ace552016-04-27 22:40:57 +00007208 return ElemSize;
7209
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007210 if (const Expr *LenExpr = OAE->getLength()) {
Michael Liaod838cf72019-10-02 00:22:45 +00007211 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr);
7212 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(),
7213 CGF.getContext().getSizeType(),
7214 LenExpr->getExprLoc());
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007215 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize);
7216 }
7217 assert(!OAE->getLength() && OAE->getColonLoc().isValid() &&
7218 OAE->getLowerBound() && "expected array_section[lb:].");
7219 // Size = sizetype - lb * elemtype;
7220 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy);
7221 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound());
7222 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(),
7223 CGF.getContext().getSizeType(),
7224 OAE->getLowerBound()->getExprLoc());
7225 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize);
7226 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal);
7227 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal);
7228 LengthVal = CGF.Builder.CreateSelect(
7229 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0));
7230 return LengthVal;
Samuel Antao86ace552016-04-27 22:40:57 +00007231 }
7232 return CGF.getTypeSize(ExprTy);
7233 }
7234
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007235 /// Return the corresponding bits for a given map clause modifier. Add
Samuel Antao86ace552016-04-27 22:40:57 +00007236 /// a flag marking the map as a pointer if requested. Add a flag marking the
Samuel Antao6782e942016-05-26 16:48:10 +00007237 /// map as the first one of a series of maps that relate to the same map
7238 /// expression.
Kelvin Lief579432018-12-18 22:18:41 +00007239 OpenMPOffloadMappingFlags getMapTypeBits(
7240 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
7241 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const {
Alexey Bataevb3638132018-07-19 16:34:13 +00007242 OpenMPOffloadMappingFlags Bits =
7243 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE;
Samuel Antao86ace552016-04-27 22:40:57 +00007244 switch (MapType) {
7245 case OMPC_MAP_alloc:
Samuel Antao6782e942016-05-26 16:48:10 +00007246 case OMPC_MAP_release:
7247 // alloc and release is the default behavior in the runtime library, i.e.
7248 // if we don't pass any bits alloc/release that is what the runtime is
7249 // going to do. Therefore, we don't need to signal anything for these two
7250 // type modifiers.
Samuel Antao86ace552016-04-27 22:40:57 +00007251 break;
7252 case OMPC_MAP_to:
Alexey Bataevb3638132018-07-19 16:34:13 +00007253 Bits |= OMP_MAP_TO;
Samuel Antao86ace552016-04-27 22:40:57 +00007254 break;
7255 case OMPC_MAP_from:
Alexey Bataevb3638132018-07-19 16:34:13 +00007256 Bits |= OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007257 break;
7258 case OMPC_MAP_tofrom:
Alexey Bataevb3638132018-07-19 16:34:13 +00007259 Bits |= OMP_MAP_TO | OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007260 break;
7261 case OMPC_MAP_delete:
Alexey Bataevb3638132018-07-19 16:34:13 +00007262 Bits |= OMP_MAP_DELETE;
Samuel Antao86ace552016-04-27 22:40:57 +00007263 break;
Alexey Bataevb3638132018-07-19 16:34:13 +00007264 case OMPC_MAP_unknown:
Samuel Antao86ace552016-04-27 22:40:57 +00007265 llvm_unreachable("Unexpected map type!");
Samuel Antao86ace552016-04-27 22:40:57 +00007266 }
7267 if (AddPtrFlag)
George Rokos065755d2017-11-07 18:27:04 +00007268 Bits |= OMP_MAP_PTR_AND_OBJ;
7269 if (AddIsTargetParamFlag)
7270 Bits |= OMP_MAP_TARGET_PARAM;
Kelvin Lief579432018-12-18 22:18:41 +00007271 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always)
7272 != MapModifiers.end())
Samuel Antao86ace552016-04-27 22:40:57 +00007273 Bits |= OMP_MAP_ALWAYS;
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007274 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close)
7275 != MapModifiers.end())
7276 Bits |= OMP_MAP_CLOSE;
Samuel Antao86ace552016-04-27 22:40:57 +00007277 return Bits;
7278 }
7279
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007280 /// Return true if the provided expression is a final array section. A
Samuel Antao86ace552016-04-27 22:40:57 +00007281 /// final array section, is one whose length can't be proved to be one.
7282 bool isFinalArraySectionExpression(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007283 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
Samuel Antao86ace552016-04-27 22:40:57 +00007284
7285 // It is not an array section and therefore not a unity-size one.
7286 if (!OASE)
7287 return false;
7288
7289 // An array section with no colon always refer to a single element.
7290 if (OASE->getColonLoc().isInvalid())
7291 return false;
7292
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007293 const Expr *Length = OASE->getLength();
Samuel Antao86ace552016-04-27 22:40:57 +00007294
7295 // If we don't have a length we have to check if the array has size 1
7296 // for this dimension. Also, we should always expect a length if the
7297 // base type is pointer.
7298 if (!Length) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007299 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType(
7300 OASE->getBase()->IgnoreParenImpCasts())
7301 .getCanonicalType();
7302 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
Samuel Antao86ace552016-04-27 22:40:57 +00007303 return ATy->getSize().getSExtValue() != 1;
7304 // If we don't have a constant dimension length, we have to consider
7305 // the current section as having any size, so it is not necessarily
7306 // unitary. If it happen to be unity size, that's user fault.
7307 return true;
7308 }
7309
7310 // Check if the length evaluates to 1.
Fangrui Song407659a2018-11-30 23:41:18 +00007311 Expr::EvalResult Result;
7312 if (!Length->EvaluateAsInt(Result, CGF.getContext()))
Samuel Antao86ace552016-04-27 22:40:57 +00007313 return true; // Can have more that size 1.
7314
Fangrui Song407659a2018-11-30 23:41:18 +00007315 llvm::APSInt ConstLength = Result.Val.getInt();
Samuel Antao86ace552016-04-27 22:40:57 +00007316 return ConstLength.getSExtValue() != 1;
7317 }
7318
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007319 /// Generate the base pointers, section pointers, sizes and map type
Samuel Antao86ace552016-04-27 22:40:57 +00007320 /// bits for the provided map type, map modifier, and expression components.
7321 /// \a IsFirstComponent should be set to true if the provided set of
7322 /// components is the first associated with a capture.
7323 void generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00007324 OpenMPMapClauseKind MapType,
7325 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Samuel Antao86ace552016-04-27 22:40:57 +00007326 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Samuel Antaocc10b852016-07-28 14:23:26 +00007327 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007328 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
Alexey Bataevb3638132018-07-19 16:34:13 +00007329 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007330 bool IsImplicit,
7331 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7332 OverlappedElements = llvm::None) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007333 // The following summarizes what has to be generated for each map and the
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00007334 // types below. The generated information is expressed in this order:
Samuel Antao86ace552016-04-27 22:40:57 +00007335 // base pointer, section pointer, size, flags
7336 // (to add to the ones that come from the map type and modifier).
7337 //
7338 // double d;
7339 // int i[100];
7340 // float *p;
7341 //
7342 // struct S1 {
7343 // int i;
7344 // float f[50];
7345 // }
7346 // struct S2 {
7347 // int i;
7348 // float f[50];
7349 // S1 s;
7350 // double *p;
7351 // struct S2 *ps;
7352 // }
7353 // S2 s;
7354 // S2 *ps;
7355 //
7356 // map(d)
Alexey Bataevb3638132018-07-19 16:34:13 +00007357 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007358 //
7359 // map(i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007360 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007361 //
7362 // map(i[1:23])
Alexey Bataevb3638132018-07-19 16:34:13 +00007363 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007364 //
7365 // map(p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007366 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007367 //
7368 // map(p[1:24])
Alexey Bataevb3638132018-07-19 16:34:13 +00007369 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007370 //
7371 // map(s)
Alexey Bataevb3638132018-07-19 16:34:13 +00007372 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007373 //
7374 // map(s.i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007375 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007376 //
7377 // map(s.s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007378 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007379 //
7380 // map(s.p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007381 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007382 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007383 // map(to: s.p[:22])
7384 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*)
7385 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**)
7386 // &(s.p), &(s.p[0]), 22*sizeof(double),
7387 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***)
7388 // (*) alloc space for struct members, only this is a target parameter
7389 // (**) map the pointer (nothing to be mapped in this example) (the compiler
7390 // optimizes this entry out, same in the examples below)
7391 // (***) map the pointee (map: to)
Samuel Antao86ace552016-04-27 22:40:57 +00007392 //
7393 // map(s.ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007394 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007395 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007396 // map(from: s.ps->s.i)
7397 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7398 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7399 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007400 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007401 // map(to: s.ps->ps)
7402 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7403 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7404 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007405 //
7406 // map(s.ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007407 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7408 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7409 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7410 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007411 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007412 // map(to: s.ps->ps->s.f[:22])
7413 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7414 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7415 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7416 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007417 //
7418 // map(ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007419 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007420 //
7421 // map(ps->i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007422 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007423 //
7424 // map(ps->s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007425 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007426 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007427 // map(from: ps->p)
7428 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007429 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007430 // map(to: ps->p[:22])
7431 // ps, &(ps->p), sizeof(double*), TARGET_PARAM
7432 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1)
7433 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007434 //
7435 // map(ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007436 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007437 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007438 // map(from: ps->ps->s.i)
7439 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7440 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7441 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007442 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007443 // map(from: ps->ps->ps)
7444 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7445 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7446 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007447 //
7448 // map(ps->ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007449 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7450 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7451 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7452 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007453 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007454 // map(to: ps->ps->ps->s.f[:22])
7455 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7456 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7457 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7458 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
7459 //
7460 // map(to: s.f[:22]) map(from: s.p[:33])
7461 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) +
7462 // sizeof(double*) (**), TARGET_PARAM
7463 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO
7464 // &s, &(s.p), sizeof(double*), MEMBER_OF(1)
7465 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7466 // (*) allocate contiguous space needed to fit all mapped members even if
7467 // we allocate space for members not mapped (in this example,
7468 // s.f[22..49] and s.s are not mapped, yet we must allocate space for
7469 // them as well because they fall between &s.f[0] and &s.p)
7470 //
7471 // map(from: s.f[:22]) map(to: ps->p[:33])
7472 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM
7473 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7474 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*)
7475 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO
7476 // (*) the struct this entry pertains to is the 2nd element in the list of
7477 // arguments, hence MEMBER_OF(2)
7478 //
7479 // map(from: s.f[:22], s.s) map(to: ps->p[:33])
7480 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM
7481 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM
7482 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM
7483 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7484 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*)
7485 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO
7486 // (*) the struct this entry pertains to is the 4th element in the list
7487 // of arguments, hence MEMBER_OF(4)
Samuel Antao86ace552016-04-27 22:40:57 +00007488
7489 // Track if the map information being generated is the first for a capture.
7490 bool IsCaptureFirstInfo = IsFirstComponentList;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007491 // When the variable is on a declare target link or in a to clause with
7492 // unified memory, a reference is needed to hold the host/device address
7493 // of the variable.
7494 bool RequiresReference = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007495
7496 // Scan the components from the base to the complete expression.
7497 auto CI = Components.rbegin();
7498 auto CE = Components.rend();
7499 auto I = CI;
7500
7501 // Track if the map information being generated is the first for a list of
7502 // components.
7503 bool IsExpressionFirstInfo = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00007504 Address BP = Address::invalid();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007505 const Expr *AssocExpr = I->getAssociatedExpression();
7506 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7507 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
Samuel Antao86ace552016-04-27 22:40:57 +00007508
Patrick Lystere13b1e32019-01-02 19:28:48 +00007509 if (isa<MemberExpr>(AssocExpr)) {
Samuel Antao86ace552016-04-27 22:40:57 +00007510 // The base is the 'this' pointer. The content of the pointer is going
7511 // to be the base of the field being mapped.
Alexey Bataevb3638132018-07-19 16:34:13 +00007512 BP = CGF.LoadCXXThisAddress();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007513 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7514 (OASE &&
7515 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
7516 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
Samuel Antao86ace552016-04-27 22:40:57 +00007517 } else {
7518 // The base is the reference to the variable.
7519 // BP = &Var.
Patrick Lystere13b1e32019-01-02 19:28:48 +00007520 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
Alexey Bataev92327c52018-03-26 16:40:55 +00007521 if (const auto *VD =
7522 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7523 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007524 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7525 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7526 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
7527 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) {
7528 RequiresReference = true;
7529 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataev2c1dffe2018-04-16 20:34:41 +00007530 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007531 }
Alexey Bataev92327c52018-03-26 16:40:55 +00007532 }
Samuel Antao86ace552016-04-27 22:40:57 +00007533
7534 // If the variable is a pointer and is being dereferenced (i.e. is not
Nico Webera6916892016-06-10 18:53:04 +00007535 // the last component), the base has to be the pointer itself, not its
Samuel Antao403ffd42016-07-27 22:49:49 +00007536 // reference. References are ignored for mapping purposes.
7537 QualType Ty =
7538 I->getAssociatedDeclaration()->getType().getNonReferenceType();
7539 if (Ty->isAnyPointerType() && std::next(I) != CE) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007540 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
Samuel Antao86ace552016-04-27 22:40:57 +00007541
7542 // We do not need to generate individual map information for the
7543 // pointer, it can be associated with the combined storage.
7544 ++I;
7545 }
7546 }
7547
Alexey Bataevb3638132018-07-19 16:34:13 +00007548 // Track whether a component of the list should be marked as MEMBER_OF some
7549 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry
7550 // in a component list should be marked as MEMBER_OF, all subsequent entries
7551 // do not belong to the base struct. E.g.
7552 // struct S2 s;
7553 // s.ps->ps->ps->f[:]
7554 // (1) (2) (3) (4)
7555 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a
7556 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3)
7557 // is the pointee of ps(2) which is not member of struct s, so it should not
7558 // be marked as such (it is still PTR_AND_OBJ).
7559 // The variable is initialized to false so that PTR_AND_OBJ entries which
7560 // are not struct members are not considered (e.g. array of pointers to
7561 // data).
7562 bool ShouldBeMemberOf = false;
7563
7564 // Variable keeping track of whether or not we have encountered a component
7565 // in the component list which is a member expression. Useful when we have a
7566 // pointer or a final array section, in which case it is the previous
7567 // component in the list which tells us whether we have a member expression.
7568 // E.g. X.f[:]
7569 // While processing the final array section "[:]" it is "f" which tells us
7570 // whether we are dealing with a member of a declared struct.
7571 const MemberExpr *EncounteredME = nullptr;
7572
Samuel Antao86ace552016-04-27 22:40:57 +00007573 for (; I != CE; ++I) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007574 // If the current component is member of a struct (parent struct) mark it.
7575 if (!EncounteredME) {
7576 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7577 // If we encounter a PTR_AND_OBJ entry from now on it should be marked
7578 // as MEMBER_OF the parent struct.
7579 if (EncounteredME)
7580 ShouldBeMemberOf = true;
7581 }
7582
Samuel Antao86ace552016-04-27 22:40:57 +00007583 auto Next = std::next(I);
7584
7585 // We need to generate the addresses and sizes if this is the last
7586 // component, if the component is a pointer or if it is an array section
7587 // whose length can't be proved to be one. If this is a pointer, it
7588 // becomes the base address for the following components.
7589
7590 // A final array section, is one whose length can't be proved to be one.
7591 bool IsFinalArraySection =
7592 isFinalArraySectionExpression(I->getAssociatedExpression());
7593
7594 // Get information on whether the element is a pointer. Have to do a
7595 // special treatment for array sections given that they are built-in
7596 // types.
7597 const auto *OASE =
7598 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression());
7599 bool IsPointer =
Alexey Bataevb3638132018-07-19 16:34:13 +00007600 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE)
7601 .getCanonicalType()
7602 ->isAnyPointerType()) ||
Samuel Antao86ace552016-04-27 22:40:57 +00007603 I->getAssociatedExpression()->getType()->isAnyPointerType();
7604
7605 if (Next == CE || IsPointer || IsFinalArraySection) {
Samuel Antao86ace552016-04-27 22:40:57 +00007606 // If this is not the last component, we expect the pointer to be
7607 // associated with an array expression or member expression.
7608 assert((Next == CE ||
7609 isa<MemberExpr>(Next->getAssociatedExpression()) ||
7610 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||
7611 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) &&
7612 "Unexpected expression");
7613
Alexey Bataevb3638132018-07-19 16:34:13 +00007614 Address LB =
7615 CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getAddress();
Samuel Antao86ace552016-04-27 22:40:57 +00007616
Alexey Bataevb3638132018-07-19 16:34:13 +00007617 // If this component is a pointer inside the base struct then we don't
7618 // need to create any entry for it - it will be combined with the object
7619 // it is pointing to into a single PTR_AND_OBJ entry.
7620 bool IsMemberPointer =
7621 IsPointer && EncounteredME &&
7622 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) ==
7623 EncounteredME);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007624 if (!OverlappedElements.empty()) {
7625 // Handle base element with the info for overlapped elements.
7626 assert(!PartialStruct.Base.isValid() && "The base element is set.");
7627 assert(Next == CE &&
7628 "Expected last element for the overlapped elements.");
7629 assert(!IsPointer &&
7630 "Unexpected base element with the pointer type.");
7631 // Mark the whole struct as the struct that requires allocation on the
7632 // device.
7633 PartialStruct.LowestElem = {0, LB};
7634 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(
7635 I->getAssociatedExpression()->getType());
7636 Address HB = CGF.Builder.CreateConstGEP(
7637 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB,
7638 CGF.VoidPtrTy),
James Y Knight751fe282019-02-09 22:22:28 +00007639 TypeSize.getQuantity() - 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007640 PartialStruct.HighestElem = {
7641 std::numeric_limits<decltype(
7642 PartialStruct.HighestElem.first)>::max(),
7643 HB};
7644 PartialStruct.Base = BP;
7645 // Emit data for non-overlapped data.
7646 OpenMPOffloadMappingFlags Flags =
7647 OMP_MAP_MEMBER_OF |
Kelvin Lief579432018-12-18 22:18:41 +00007648 getMapTypeBits(MapType, MapModifiers, IsImplicit,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007649 /*AddPtrFlag=*/false,
7650 /*AddIsTargetParamFlag=*/false);
7651 LB = BP;
7652 llvm::Value *Size = nullptr;
7653 // Do bitcopy of all non-overlapped structure elements.
7654 for (OMPClauseMappableExprCommon::MappableExprComponentListRef
7655 Component : OverlappedElements) {
7656 Address ComponentLB = Address::invalid();
7657 for (const OMPClauseMappableExprCommon::MappableComponent &MC :
7658 Component) {
7659 if (MC.getAssociatedDeclaration()) {
7660 ComponentLB =
7661 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
7662 .getAddress();
7663 Size = CGF.Builder.CreatePtrDiff(
7664 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()),
7665 CGF.EmitCastToVoidPtr(LB.getPointer()));
7666 break;
7667 }
7668 }
7669 BasePointers.push_back(BP.getPointer());
7670 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007671 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty,
7672 /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007673 Types.push_back(Flags);
James Y Knight751fe282019-02-09 22:22:28 +00007674 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007675 }
7676 BasePointers.push_back(BP.getPointer());
7677 Pointers.push_back(LB.getPointer());
7678 Size = CGF.Builder.CreatePtrDiff(
7679 CGF.EmitCastToVoidPtr(
James Y Knight751fe282019-02-09 22:22:28 +00007680 CGF.Builder.CreateConstGEP(HB, 1).getPointer()),
Alexey Bataeve82445f2018-09-20 13:54:02 +00007681 CGF.EmitCastToVoidPtr(LB.getPointer()));
Alexey Bataeva90fc662019-06-25 16:00:43 +00007682 Sizes.push_back(
7683 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007684 Types.push_back(Flags);
7685 break;
7686 }
7687 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
Alexey Bataevb3638132018-07-19 16:34:13 +00007688 if (!IsMemberPointer) {
7689 BasePointers.push_back(BP.getPointer());
7690 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007691 Sizes.push_back(
7692 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Samuel Antao03a3cec2016-07-27 22:52:16 +00007693
Alexey Bataevb3638132018-07-19 16:34:13 +00007694 // We need to add a pointer flag for each map that comes from the
7695 // same expression except for the first one. We also need to signal
7696 // this map is the first one that relates with the current capture
7697 // (there is a set of entries for each capture).
7698 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
Kelvin Lief579432018-12-18 22:18:41 +00007699 MapType, MapModifiers, IsImplicit,
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007700 !IsExpressionFirstInfo || RequiresReference,
7701 IsCaptureFirstInfo && !RequiresReference);
Alexey Bataevb3638132018-07-19 16:34:13 +00007702
7703 if (!IsExpressionFirstInfo) {
7704 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007705 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags.
Alexey Bataevb3638132018-07-19 16:34:13 +00007706 if (IsPointer)
7707 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS |
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007708 OMP_MAP_DELETE | OMP_MAP_CLOSE);
Alexey Bataevb3638132018-07-19 16:34:13 +00007709
7710 if (ShouldBeMemberOf) {
7711 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag
7712 // should be later updated with the correct value of MEMBER_OF.
7713 Flags |= OMP_MAP_MEMBER_OF;
7714 // From now on, all subsequent PTR_AND_OBJ entries should not be
7715 // marked as MEMBER_OF.
7716 ShouldBeMemberOf = false;
7717 }
7718 }
7719
7720 Types.push_back(Flags);
Samuel Antao03a3cec2016-07-27 22:52:16 +00007721 }
7722
Alexey Bataevb3638132018-07-19 16:34:13 +00007723 // If we have encountered a member expression so far, keep track of the
7724 // mapped member. If the parent is "*this", then the value declaration
7725 // is nullptr.
7726 if (EncounteredME) {
7727 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl());
7728 unsigned FieldIndex = FD->getFieldIndex();
Samuel Antao03a3cec2016-07-27 22:52:16 +00007729
Alexey Bataevb3638132018-07-19 16:34:13 +00007730 // Update info about the lowest and highest elements for this struct
7731 if (!PartialStruct.Base.isValid()) {
7732 PartialStruct.LowestElem = {FieldIndex, LB};
7733 PartialStruct.HighestElem = {FieldIndex, LB};
7734 PartialStruct.Base = BP;
7735 } else if (FieldIndex < PartialStruct.LowestElem.first) {
7736 PartialStruct.LowestElem = {FieldIndex, LB};
7737 } else if (FieldIndex > PartialStruct.HighestElem.first) {
7738 PartialStruct.HighestElem = {FieldIndex, LB};
7739 }
7740 }
Samuel Antao86ace552016-04-27 22:40:57 +00007741
7742 // If we have a final array section, we are done with this expression.
7743 if (IsFinalArraySection)
7744 break;
7745
7746 // The pointer becomes the base for the next element.
7747 if (Next != CE)
7748 BP = LB;
7749
7750 IsExpressionFirstInfo = false;
7751 IsCaptureFirstInfo = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007752 }
7753 }
7754 }
7755
Alexey Bataevb3638132018-07-19 16:34:13 +00007756 /// Return the adjusted map modifiers if the declaration a capture refers to
7757 /// appears in a first-private clause. This is expected to be used only with
7758 /// directives that start with 'target'.
7759 MappableExprsHandler::OpenMPOffloadMappingFlags
7760 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const {
7761 assert(Cap.capturesVariable() && "Expected capture by reference only!");
7762
7763 // A first private variable captured by reference will use only the
7764 // 'private ptr' and 'map to' flag. Return the right flags if the captured
7765 // declaration is known as first-private in this handler.
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007766 if (FirstPrivateDecls.count(Cap.getCapturedVar())) {
7767 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) &&
7768 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef)
7769 return MappableExprsHandler::OMP_MAP_ALWAYS |
7770 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataevc2b831f2019-04-02 16:03:40 +00007771 if (Cap.getCapturedVar()->getType()->isAnyPointerType())
7772 return MappableExprsHandler::OMP_MAP_TO |
7773 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ;
Alexey Bataevb3638132018-07-19 16:34:13 +00007774 return MappableExprsHandler::OMP_MAP_PRIVATE |
7775 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007776 }
Alexey Bataevb3638132018-07-19 16:34:13 +00007777 return MappableExprsHandler::OMP_MAP_TO |
7778 MappableExprsHandler::OMP_MAP_FROM;
7779 }
7780
7781 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) {
Michael Krused47b9432019-08-05 18:43:21 +00007782 // Rotate by getFlagMemberOffset() bits.
Alexey Bataevb3638132018-07-19 16:34:13 +00007783 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1)
Michael Krused47b9432019-08-05 18:43:21 +00007784 << getFlagMemberOffset());
Alexey Bataevb3638132018-07-19 16:34:13 +00007785 }
7786
7787 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags,
7788 OpenMPOffloadMappingFlags MemberOfFlag) {
7789 // If the entry is PTR_AND_OBJ but has not been marked with the special
7790 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be
7791 // marked as MEMBER_OF.
7792 if ((Flags & OMP_MAP_PTR_AND_OBJ) &&
7793 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF))
7794 return;
7795
7796 // Reset the placeholder value to prepare the flag for the assignment of the
7797 // proper MEMBER_OF value.
7798 Flags &= ~OMP_MAP_MEMBER_OF;
7799 Flags |= MemberOfFlag;
7800 }
7801
Alexey Bataeve82445f2018-09-20 13:54:02 +00007802 void getPlainLayout(const CXXRecordDecl *RD,
7803 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
7804 bool AsBase) const {
7805 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD);
7806
7807 llvm::StructType *St =
7808 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType();
7809
7810 unsigned NumElements = St->getNumElements();
7811 llvm::SmallVector<
7812 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
7813 RecordLayout(NumElements);
7814
7815 // Fill bases.
7816 for (const auto &I : RD->bases()) {
7817 if (I.isVirtual())
7818 continue;
7819 const auto *Base = I.getType()->getAsCXXRecordDecl();
7820 // Ignore empty bases.
7821 if (Base->isEmpty() || CGF.getContext()
7822 .getASTRecordLayout(Base)
7823 .getNonVirtualSize()
7824 .isZero())
7825 continue;
7826
7827 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
7828 RecordLayout[FieldIndex] = Base;
7829 }
7830 // Fill in virtual bases.
7831 for (const auto &I : RD->vbases()) {
7832 const auto *Base = I.getType()->getAsCXXRecordDecl();
7833 // Ignore empty bases.
7834 if (Base->isEmpty())
7835 continue;
7836 unsigned FieldIndex = RL.getVirtualBaseIndex(Base);
7837 if (RecordLayout[FieldIndex])
7838 continue;
7839 RecordLayout[FieldIndex] = Base;
7840 }
7841 // Fill in all the fields.
7842 assert(!RD->isUnion() && "Unexpected union.");
7843 for (const auto *Field : RD->fields()) {
7844 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
7845 // will fill in later.)
Richard Smith78b239e2019-06-20 20:44:45 +00007846 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) {
Alexey Bataeve82445f2018-09-20 13:54:02 +00007847 unsigned FieldIndex = RL.getLLVMFieldNo(Field);
7848 RecordLayout[FieldIndex] = Field;
7849 }
7850 }
7851 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
7852 &Data : RecordLayout) {
7853 if (Data.isNull())
7854 continue;
7855 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>())
7856 getPlainLayout(Base, Layout, /*AsBase=*/true);
7857 else
7858 Layout.push_back(Data.get<const FieldDecl *>());
7859 }
7860 }
7861
Alexey Bataevb3638132018-07-19 16:34:13 +00007862public:
7863 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
Michael Krused47b9432019-08-05 18:43:21 +00007864 : CurDir(&Dir), CGF(CGF) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007865 // Extract firstprivate clause information.
7866 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>())
7867 for (const auto *D : C->varlists())
Alexey Bataevf288cf92019-06-27 18:53:07 +00007868 FirstPrivateDecls.try_emplace(
7869 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit());
Alexey Bataevb3638132018-07-19 16:34:13 +00007870 // Extract device pointer clause information.
7871 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
7872 for (auto L : C->component_lists())
7873 DevPointersMap[L.first].push_back(L.second);
7874 }
7875
Michael Krused47b9432019-08-05 18:43:21 +00007876 /// Constructor for the declare mapper directive.
7877 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF)
7878 : CurDir(&Dir), CGF(CGF) {}
7879
Alexey Bataevb3638132018-07-19 16:34:13 +00007880 /// Generate code for the combined entry if we have a partially mapped struct
7881 /// and take care of the mapping flags of the arguments corresponding to
7882 /// individual struct members.
7883 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers,
7884 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7885 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes,
7886 const StructRangeInfoTy &PartialStruct) const {
7887 // Base is the base of the struct
7888 BasePointers.push_back(PartialStruct.Base.getPointer());
7889 // Pointer is the address of the lowest element
7890 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer();
7891 Pointers.push_back(LB);
7892 // Size is (addr of {highest+1} element) - (addr of lowest element)
7893 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer();
7894 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1);
7895 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy);
7896 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy);
7897 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00007898 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00007899 /*isSigned=*/false);
Alexey Bataevb3638132018-07-19 16:34:13 +00007900 Sizes.push_back(Size);
7901 // Map type is always TARGET_PARAM
7902 Types.push_back(OMP_MAP_TARGET_PARAM);
7903 // Remove TARGET_PARAM flag from the first element
7904 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM;
7905
7906 // All other current entries will be MEMBER_OF the combined entry
7907 // (except for PTR_AND_OBJ entries which do not have a placeholder value
7908 // 0xFFFF in the MEMBER_OF field).
7909 OpenMPOffloadMappingFlags MemberOfFlag =
7910 getMemberOfFlag(BasePointers.size() - 1);
7911 for (auto &M : CurTypes)
7912 setCorrectMemberOfFlag(M, MemberOfFlag);
7913 }
7914
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007915 /// Generate all the base pointers, section pointers, sizes and map
Samuel Antaocc10b852016-07-28 14:23:26 +00007916 /// types for the extracted mappable expressions. Also, for each item that
7917 /// relates with a device pointer, a pair of the relevant declaration and
7918 /// index where it occurs is appended to the device pointers info array.
7919 void generateAllInfo(MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007920 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7921 MapFlagsArrayTy &Types) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007922 // We have to process the component lists that relate with the same
7923 // declaration in a single chunk so that we can generate the map flags
7924 // correctly. Therefore, we organize all lists in a map.
Alexey Bataev5d1c3f62017-06-27 15:46:42 +00007925 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
Samuel Antao8d2d7302016-05-26 18:30:22 +00007926
7927 // Helper function to fill the information map for the different supported
7928 // clauses.
Samuel Antaocc10b852016-07-28 14:23:26 +00007929 auto &&InfoGen = [&Info](
7930 const ValueDecl *D,
7931 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
Kelvin Lief579432018-12-18 22:18:41 +00007932 OpenMPMapClauseKind MapType,
7933 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007934 bool ReturnDevicePointer, bool IsImplicit) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007935 const ValueDecl *VD =
7936 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
Kelvin Lief579432018-12-18 22:18:41 +00007937 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007938 IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00007939 };
Samuel Antao8d2d7302016-05-26 18:30:22 +00007940
Michael Krused47b9432019-08-05 18:43:21 +00007941 assert(CurDir.is<const OMPExecutableDirective *>() &&
7942 "Expect a executable directive");
7943 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
7944 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>())
Mark de Wever51abceb2019-11-12 20:48:11 +01007945 for (const auto L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007946 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(),
Alexey Bataevb3638132018-07-19 16:34:13 +00007947 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007948 }
Michael Krused47b9432019-08-05 18:43:21 +00007949 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>())
Mark de Wever51abceb2019-11-12 20:48:11 +01007950 for (const auto L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007951 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007952 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007953 }
Michael Krused47b9432019-08-05 18:43:21 +00007954 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>())
Mark de Wever51abceb2019-11-12 20:48:11 +01007955 for (const auto L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007956 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007957 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007958 }
Samuel Antao86ace552016-04-27 22:40:57 +00007959
Samuel Antaocc10b852016-07-28 14:23:26 +00007960 // Look at the use_device_ptr clause information and mark the existing map
7961 // entries as such. If there is no map information for an entry in the
7962 // use_device_ptr list, we create one with map type 'alloc' and zero size
Alexey Bataevb3638132018-07-19 16:34:13 +00007963 // section. It is the user fault if that was not mapped before. If there is
7964 // no map information and the pointer is a struct member, then we defer the
7965 // emission of that entry until the whole struct has been processed.
7966 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>>
7967 DeferredInfo;
7968
Alexey Bataevb3638132018-07-19 16:34:13 +00007969 for (const auto *C :
Michael Krused47b9432019-08-05 18:43:21 +00007970 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) {
Mark de Wever51abceb2019-11-12 20:48:11 +01007971 for (const auto L : C->component_lists()) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007972 assert(!L.second.empty() && "Not expecting empty list of components!");
7973 const ValueDecl *VD = L.second.back().getAssociatedDeclaration();
7974 VD = cast<ValueDecl>(VD->getCanonicalDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007975 const Expr *IE = L.second.back().getAssociatedExpression();
Samuel Antaocc10b852016-07-28 14:23:26 +00007976 // If the first component is a member expression, we have to look into
7977 // 'this', which maps to null in the map of map information. Otherwise
7978 // look directly for the information.
7979 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
7980
7981 // We potentially have map information for this declaration already.
7982 // Look for the first set of components that refer to it.
7983 if (It != Info.end()) {
7984 auto CI = std::find_if(
7985 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) {
7986 return MI.Components.back().getAssociatedDeclaration() == VD;
7987 });
7988 // If we found a map entry, signal that the pointer has to be returned
7989 // and move on to the next declaration.
7990 if (CI != It->second.end()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007991 CI->ReturnDevicePointer = true;
Samuel Antaocc10b852016-07-28 14:23:26 +00007992 continue;
7993 }
7994 }
7995
7996 // We didn't find any match in our map information - generate a zero
Alexey Bataevb3638132018-07-19 16:34:13 +00007997 // size array section - if the pointer is a struct member we defer this
7998 // action until the whole struct has been processed.
Alexey Bataevb3638132018-07-19 16:34:13 +00007999 if (isa<MemberExpr>(IE)) {
8000 // Insert the pointer into Info to be processed by
8001 // generateInfoForComponentList. Because it is a member pointer
8002 // without a pointee, no entry will be generated for it, therefore
8003 // we need to generate one after the whole struct has been processed.
8004 // Nonetheless, generateInfoForComponentList must be called to take
8005 // the pointer into account for the calculation of the range of the
8006 // partial struct.
Kelvin Lief579432018-12-18 22:18:41 +00008007 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00008008 /*ReturnDevicePointer=*/false, C->isImplicit());
8009 DeferredInfo[nullptr].emplace_back(IE, VD);
8010 } else {
Michael Krused47b9432019-08-05 18:43:21 +00008011 llvm::Value *Ptr =
8012 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc());
Alexey Bataevb3638132018-07-19 16:34:13 +00008013 BasePointers.emplace_back(Ptr, VD);
8014 Pointers.push_back(Ptr);
Michael Krused47b9432019-08-05 18:43:21 +00008015 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00008016 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM);
8017 }
Samuel Antaocc10b852016-07-28 14:23:26 +00008018 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008019 }
Samuel Antaocc10b852016-07-28 14:23:26 +00008020
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008021 for (const auto &M : Info) {
Samuel Antao86ace552016-04-27 22:40:57 +00008022 // We need to know when we generate information for the first component
8023 // associated with a capture, because the mapping flags depend on it.
8024 bool IsFirstComponentList = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00008025
8026 // Temporary versions of arrays
8027 MapBaseValuesArrayTy CurBasePointers;
8028 MapValuesArrayTy CurPointers;
8029 MapValuesArrayTy CurSizes;
8030 MapFlagsArrayTy CurTypes;
8031 StructRangeInfoTy PartialStruct;
8032
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008033 for (const MapInfo &L : M.second) {
Samuel Antao86ace552016-04-27 22:40:57 +00008034 assert(!L.Components.empty() &&
8035 "Not expecting declaration with no component lists.");
Samuel Antaocc10b852016-07-28 14:23:26 +00008036
8037 // Remember the current base pointer index.
Alexey Bataevb3638132018-07-19 16:34:13 +00008038 unsigned CurrentBasePointersIdx = CurBasePointers.size();
Michael Krused47b9432019-08-05 18:43:21 +00008039 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8040 CurBasePointers, CurPointers, CurSizes,
8041 CurTypes, PartialStruct,
8042 IsFirstComponentList, L.IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00008043
8044 // If this entry relates with a device pointer, set the relevant
8045 // declaration and add the 'return pointer' flag.
Alexey Bataevb3638132018-07-19 16:34:13 +00008046 if (L.ReturnDevicePointer) {
8047 assert(CurBasePointers.size() > CurrentBasePointersIdx &&
Samuel Antaocc10b852016-07-28 14:23:26 +00008048 "Unexpected number of mapped base pointers.");
8049
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008050 const ValueDecl *RelevantVD =
8051 L.Components.back().getAssociatedDeclaration();
Samuel Antaocc10b852016-07-28 14:23:26 +00008052 assert(RelevantVD &&
8053 "No relevant declaration related with device pointer??");
8054
Alexey Bataevb3638132018-07-19 16:34:13 +00008055 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD);
8056 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008057 }
Samuel Antao86ace552016-04-27 22:40:57 +00008058 IsFirstComponentList = false;
8059 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008060
8061 // Append any pending zero-length pointers which are struct members and
8062 // used with use_device_ptr.
8063 auto CI = DeferredInfo.find(M.first);
8064 if (CI != DeferredInfo.end()) {
8065 for (const DeferredDevicePtrEntryTy &L : CI->second) {
8066 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer();
8067 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar(
8068 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc());
8069 CurBasePointers.emplace_back(BasePtr, L.VD);
8070 CurPointers.push_back(Ptr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008071 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00008072 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder
8073 // value MEMBER_OF=FFFF so that the entry is later updated with the
8074 // correct value of MEMBER_OF.
8075 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM |
8076 OMP_MAP_MEMBER_OF);
8077 }
8078 }
8079
8080 // If there is an entry in PartialStruct it means we have a struct with
8081 // individual members mapped. Emit an extra combined entry.
8082 if (PartialStruct.Base.isValid())
8083 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8084 PartialStruct);
8085
8086 // We need to append the results of this capture to what we already have.
8087 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8088 Pointers.append(CurPointers.begin(), CurPointers.end());
8089 Sizes.append(CurSizes.begin(), CurSizes.end());
8090 Types.append(CurTypes.begin(), CurTypes.end());
Samuel Antao86ace552016-04-27 22:40:57 +00008091 }
8092 }
8093
Michael Krused47b9432019-08-05 18:43:21 +00008094 /// Generate all the base pointers, section pointers, sizes and map types for
8095 /// the extracted map clauses of user-defined mapper.
8096 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers,
8097 MapValuesArrayTy &Pointers,
8098 MapValuesArrayTy &Sizes,
8099 MapFlagsArrayTy &Types) const {
8100 assert(CurDir.is<const OMPDeclareMapperDecl *>() &&
8101 "Expect a declare mapper directive");
8102 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>();
8103 // We have to process the component lists that relate with the same
8104 // declaration in a single chunk so that we can generate the map flags
8105 // correctly. Therefore, we organize all lists in a map.
8106 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
8107
8108 // Helper function to fill the information map for the different supported
8109 // clauses.
8110 auto &&InfoGen = [&Info](
8111 const ValueDecl *D,
8112 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
8113 OpenMPMapClauseKind MapType,
8114 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8115 bool ReturnDevicePointer, bool IsImplicit) {
8116 const ValueDecl *VD =
8117 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
8118 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
8119 IsImplicit);
8120 };
8121
8122 for (const auto *C : CurMapperDir->clauselists()) {
8123 const auto *MC = cast<OMPMapClause>(C);
Mark de Wever51abceb2019-11-12 20:48:11 +01008124 for (const auto L : MC->component_lists()) {
Michael Krused47b9432019-08-05 18:43:21 +00008125 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(),
8126 /*ReturnDevicePointer=*/false, MC->isImplicit());
8127 }
8128 }
8129
8130 for (const auto &M : Info) {
8131 // We need to know when we generate information for the first component
8132 // associated with a capture, because the mapping flags depend on it.
8133 bool IsFirstComponentList = true;
8134
8135 // Temporary versions of arrays
8136 MapBaseValuesArrayTy CurBasePointers;
8137 MapValuesArrayTy CurPointers;
8138 MapValuesArrayTy CurSizes;
8139 MapFlagsArrayTy CurTypes;
8140 StructRangeInfoTy PartialStruct;
8141
8142 for (const MapInfo &L : M.second) {
8143 assert(!L.Components.empty() &&
8144 "Not expecting declaration with no component lists.");
8145 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8146 CurBasePointers, CurPointers, CurSizes,
8147 CurTypes, PartialStruct,
8148 IsFirstComponentList, L.IsImplicit);
8149 IsFirstComponentList = false;
8150 }
8151
8152 // If there is an entry in PartialStruct it means we have a struct with
8153 // individual members mapped. Emit an extra combined entry.
8154 if (PartialStruct.Base.isValid())
8155 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8156 PartialStruct);
8157
8158 // We need to append the results of this capture to what we already have.
8159 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8160 Pointers.append(CurPointers.begin(), CurPointers.end());
8161 Sizes.append(CurSizes.begin(), CurSizes.end());
8162 Types.append(CurTypes.begin(), CurTypes.end());
8163 }
8164 }
8165
Alexey Bataev60705422018-10-30 15:50:12 +00008166 /// Emit capture info for lambdas for variables captured by reference.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008167 void generateInfoForLambdaCaptures(
8168 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers,
8169 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
8170 MapFlagsArrayTy &Types,
8171 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008172 const auto *RD = VD->getType()
8173 .getCanonicalType()
8174 .getNonReferenceType()
8175 ->getAsCXXRecordDecl();
8176 if (!RD || !RD->isLambda())
8177 return;
8178 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD));
8179 LValue VDLVal = CGF.MakeAddrLValue(
8180 VDAddr, VD->getType().getCanonicalType().getNonReferenceType());
8181 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
8182 FieldDecl *ThisCapture = nullptr;
8183 RD->getCaptureFields(Captures, ThisCapture);
8184 if (ThisCapture) {
8185 LValue ThisLVal =
8186 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture);
Alexey Bataev969dbc02018-11-08 15:47:39 +00008187 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture);
8188 LambdaPointers.try_emplace(ThisLVal.getPointer(), VDLVal.getPointer());
8189 BasePointers.push_back(ThisLVal.getPointer());
8190 Pointers.push_back(ThisLValVal.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00008191 Sizes.push_back(
8192 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8193 CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008194 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008195 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8196 }
8197 for (const LambdaCapture &LC : RD->captures()) {
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008198 if (!LC.capturesVariable())
Alexey Bataev60705422018-10-30 15:50:12 +00008199 continue;
8200 const VarDecl *VD = LC.getCapturedVar();
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008201 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType())
8202 continue;
Alexey Bataev60705422018-10-30 15:50:12 +00008203 auto It = Captures.find(VD);
8204 assert(It != Captures.end() && "Found lambda capture without field.");
8205 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second);
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008206 if (LC.getCaptureKind() == LCK_ByRef) {
8207 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second);
8208 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer());
8209 BasePointers.push_back(VarLVal.getPointer());
8210 Pointers.push_back(VarLValVal.getPointer());
8211 Sizes.push_back(CGF.Builder.CreateIntCast(
8212 CGF.getTypeSize(
8213 VD->getType().getCanonicalType().getNonReferenceType()),
8214 CGF.Int64Ty, /*isSigned=*/true));
8215 } else {
8216 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation());
8217 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer());
8218 BasePointers.push_back(VarLVal.getPointer());
8219 Pointers.push_back(VarRVal.getScalarVal());
8220 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0));
8221 }
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008222 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008223 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8224 }
8225 }
8226
8227 /// Set correct indices for lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008228 void adjustMemberOfForLambdaCaptures(
8229 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
8230 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
8231 MapFlagsArrayTy &Types) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008232 for (unsigned I = 0, E = Types.size(); I < E; ++I) {
8233 // Set correct member_of idx for all implicit lambda captures.
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008234 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008235 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT))
8236 continue;
Alexey Bataev969dbc02018-11-08 15:47:39 +00008237 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]);
8238 assert(BasePtr && "Unable to find base lambda address.");
Alexey Bataev60705422018-10-30 15:50:12 +00008239 int TgtIdx = -1;
8240 for (unsigned J = I; J > 0; --J) {
8241 unsigned Idx = J - 1;
8242 if (Pointers[Idx] != BasePtr)
8243 continue;
8244 TgtIdx = Idx;
8245 break;
8246 }
8247 assert(TgtIdx != -1 && "Unable to find parent lambda.");
8248 // All other current entries will be MEMBER_OF the combined entry
8249 // (except for PTR_AND_OBJ entries which do not have a placeholder value
8250 // 0xFFFF in the MEMBER_OF field).
8251 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx);
8252 setCorrectMemberOfFlag(Types[I], MemberOfFlag);
8253 }
8254 }
8255
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008256 /// Generate the base pointers, section pointers, sizes and map types
Samuel Antao86ace552016-04-27 22:40:57 +00008257 /// associated to a given capture.
8258 void generateInfoForCapture(const CapturedStmt::Capture *Cap,
Samuel Antao6890b092016-07-28 14:25:09 +00008259 llvm::Value *Arg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008260 MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00008261 MapValuesArrayTy &Pointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008262 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
8263 StructRangeInfoTy &PartialStruct) const {
Samuel Antao86ace552016-04-27 22:40:57 +00008264 assert(!Cap->capturesVariableArrayType() &&
8265 "Not expecting to generate map info for a variable array type!");
8266
Samuel Antao6890b092016-07-28 14:25:09 +00008267 // We need to know when we generating information for the first component
Alexey Bataevb3638132018-07-19 16:34:13 +00008268 const ValueDecl *VD = Cap->capturesThis()
8269 ? nullptr
8270 : Cap->getCapturedVar()->getCanonicalDecl();
Samuel Antao86ace552016-04-27 22:40:57 +00008271
Samuel Antao6890b092016-07-28 14:25:09 +00008272 // If this declaration appears in a is_device_ptr clause we just have to
8273 // pass the pointer by value. If it is a reference to a declaration, we just
Alexey Bataevb3638132018-07-19 16:34:13 +00008274 // pass its value.
8275 if (DevPointersMap.count(VD)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008276 BasePointers.emplace_back(Arg, VD);
Samuel Antao6890b092016-07-28 14:25:09 +00008277 Pointers.push_back(Arg);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008278 Sizes.push_back(
8279 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8280 CGF.Int64Ty, /*isSigned=*/true));
George Rokos065755d2017-11-07 18:27:04 +00008281 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM);
Samuel Antao6890b092016-07-28 14:25:09 +00008282 return;
8283 }
8284
Alexey Bataeve82445f2018-09-20 13:54:02 +00008285 using MapData =
8286 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
Kelvin Lief579432018-12-18 22:18:41 +00008287 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008288 SmallVector<MapData, 4> DeclComponentLists;
Michael Krused47b9432019-08-05 18:43:21 +00008289 assert(CurDir.is<const OMPExecutableDirective *>() &&
8290 "Expect a executable directive");
8291 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
8292 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
Mark de Wever51abceb2019-11-12 20:48:11 +01008293 for (const auto L : C->decl_component_lists(VD)) {
Samuel Antao86ace552016-04-27 22:40:57 +00008294 assert(L.first == VD &&
8295 "We got information for the wrong declaration??");
8296 assert(!L.second.empty() &&
8297 "Not expecting declaration with no component lists.");
Alexey Bataeve82445f2018-09-20 13:54:02 +00008298 DeclComponentLists.emplace_back(L.second, C->getMapType(),
Kelvin Lief579432018-12-18 22:18:41 +00008299 C->getMapTypeModifiers(),
Alexey Bataeve82445f2018-09-20 13:54:02 +00008300 C->isImplicit());
Samuel Antao86ace552016-04-27 22:40:57 +00008301 }
Alexey Bataeve82445f2018-09-20 13:54:02 +00008302 }
8303
8304 // Find overlapping elements (including the offset from the base element).
8305 llvm::SmallDenseMap<
8306 const MapData *,
8307 llvm::SmallVector<
8308 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>,
8309 4>
8310 OverlappedData;
8311 size_t Count = 0;
8312 for (const MapData &L : DeclComponentLists) {
8313 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8314 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008315 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008316 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008317 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008318 ++Count;
8319 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) {
8320 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1;
Kelvin Lief579432018-12-18 22:18:41 +00008321 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008322 auto CI = Components.rbegin();
8323 auto CE = Components.rend();
8324 auto SI = Components1.rbegin();
8325 auto SE = Components1.rend();
8326 for (; CI != CE && SI != SE; ++CI, ++SI) {
8327 if (CI->getAssociatedExpression()->getStmtClass() !=
8328 SI->getAssociatedExpression()->getStmtClass())
8329 break;
8330 // Are we dealing with different variables/fields?
8331 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
8332 break;
8333 }
8334 // Found overlapping if, at least for one component, reached the head of
8335 // the components list.
8336 if (CI == CE || SI == SE) {
8337 assert((CI != CE || SI != SE) &&
8338 "Unexpected full match of the mapping components.");
8339 const MapData &BaseData = CI == CE ? L : L1;
8340 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData =
8341 SI == SE ? Components : Components1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008342 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData);
8343 OverlappedElements.getSecond().push_back(SubData);
8344 }
8345 }
8346 }
8347 // Sort the overlapped elements for each item.
8348 llvm::SmallVector<const FieldDecl *, 4> Layout;
8349 if (!OverlappedData.empty()) {
8350 if (const auto *CRD =
8351 VD->getType().getCanonicalType()->getAsCXXRecordDecl())
8352 getPlainLayout(CRD, Layout, /*AsBase=*/false);
8353 else {
8354 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl();
8355 Layout.append(RD->field_begin(), RD->field_end());
8356 }
8357 }
8358 for (auto &Pair : OverlappedData) {
8359 llvm::sort(
8360 Pair.getSecond(),
8361 [&Layout](
8362 OMPClauseMappableExprCommon::MappableExprComponentListRef First,
8363 OMPClauseMappableExprCommon::MappableExprComponentListRef
8364 Second) {
8365 auto CI = First.rbegin();
8366 auto CE = First.rend();
8367 auto SI = Second.rbegin();
8368 auto SE = Second.rend();
8369 for (; CI != CE && SI != SE; ++CI, ++SI) {
8370 if (CI->getAssociatedExpression()->getStmtClass() !=
8371 SI->getAssociatedExpression()->getStmtClass())
8372 break;
8373 // Are we dealing with different variables/fields?
8374 if (CI->getAssociatedDeclaration() !=
8375 SI->getAssociatedDeclaration())
8376 break;
8377 }
Richard Trieu5061e832018-09-21 21:20:33 +00008378
8379 // Lists contain the same elements.
8380 if (CI == CE && SI == SE)
8381 return false;
8382
8383 // List with less elements is less than list with more elements.
8384 if (CI == CE || SI == SE)
8385 return CI == CE;
8386
Alexey Bataeve82445f2018-09-20 13:54:02 +00008387 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
8388 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
8389 if (FD1->getParent() == FD2->getParent())
8390 return FD1->getFieldIndex() < FD2->getFieldIndex();
8391 const auto It =
8392 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) {
8393 return FD == FD1 || FD == FD2;
8394 });
8395 return *It == FD1;
8396 });
8397 }
8398
8399 // Associated with a capture, because the mapping flags depend on it.
8400 // Go through all of the elements with the overlapped elements.
8401 for (const auto &Pair : OverlappedData) {
8402 const MapData &L = *Pair.getFirst();
8403 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8404 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008405 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008406 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008407 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008408 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
8409 OverlappedComponents = Pair.getSecond();
8410 bool IsFirstComponentList = true;
Kelvin Lief579432018-12-18 22:18:41 +00008411 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008412 BasePointers, Pointers, Sizes, Types,
8413 PartialStruct, IsFirstComponentList,
8414 IsImplicit, OverlappedComponents);
8415 }
8416 // Go through other elements without overlapped elements.
8417 bool IsFirstComponentList = OverlappedData.empty();
8418 for (const MapData &L : DeclComponentLists) {
8419 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8420 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008421 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008422 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008423 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008424 auto It = OverlappedData.find(&L);
8425 if (It == OverlappedData.end())
Kelvin Lief579432018-12-18 22:18:41 +00008426 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008427 BasePointers, Pointers, Sizes, Types,
8428 PartialStruct, IsFirstComponentList,
8429 IsImplicit);
8430 IsFirstComponentList = false;
8431 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008432 }
Samuel Antao86ace552016-04-27 22:40:57 +00008433
Alexey Bataevb3638132018-07-19 16:34:13 +00008434 /// Generate the base pointers, section pointers, sizes and map types
8435 /// associated with the declare target link variables.
8436 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers,
8437 MapValuesArrayTy &Pointers,
8438 MapValuesArrayTy &Sizes,
8439 MapFlagsArrayTy &Types) const {
Michael Krused47b9432019-08-05 18:43:21 +00008440 assert(CurDir.is<const OMPExecutableDirective *>() &&
8441 "Expect a executable directive");
8442 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
Alexey Bataevb3638132018-07-19 16:34:13 +00008443 // Map other list items in the map clause which are not captured variables
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00008444 // but "declare target link" global variables.
Michael Krused47b9432019-08-05 18:43:21 +00008445 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
Mark de Wever51abceb2019-11-12 20:48:11 +01008446 for (const auto L : C->component_lists()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00008447 if (!L.first)
8448 continue;
8449 const auto *VD = dyn_cast<VarDecl>(L.first);
8450 if (!VD)
8451 continue;
8452 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00008453 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00008454 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
8455 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)
Alexey Bataevb3638132018-07-19 16:34:13 +00008456 continue;
8457 StructRangeInfoTy PartialStruct;
8458 generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00008459 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008460 Pointers, Sizes, Types, PartialStruct,
8461 /*IsFirstComponentList=*/true, C->isImplicit());
8462 assert(!PartialStruct.Base.isValid() &&
8463 "No partial structs for declare target link expected.");
8464 }
8465 }
Samuel Antao86ace552016-04-27 22:40:57 +00008466 }
Samuel Antaod486f842016-05-26 16:53:38 +00008467
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008468 /// Generate the default map information for a given capture \a CI,
Samuel Antaod486f842016-05-26 16:53:38 +00008469 /// record field declaration \a RI and captured value \a CV.
Samuel Antaocc10b852016-07-28 14:23:26 +00008470 void generateDefaultMapInfo(const CapturedStmt::Capture &CI,
8471 const FieldDecl &RI, llvm::Value *CV,
8472 MapBaseValuesArrayTy &CurBasePointers,
8473 MapValuesArrayTy &CurPointers,
8474 MapValuesArrayTy &CurSizes,
Alexey Bataevb3638132018-07-19 16:34:13 +00008475 MapFlagsArrayTy &CurMapTypes) const {
Alexey Bataevf288cf92019-06-27 18:53:07 +00008476 bool IsImplicit = true;
Samuel Antaod486f842016-05-26 16:53:38 +00008477 // Do the default mapping.
8478 if (CI.capturesThis()) {
8479 CurBasePointers.push_back(CV);
8480 CurPointers.push_back(CV);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008481 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr());
Alexey Bataeva90fc662019-06-25 16:00:43 +00008482 CurSizes.push_back(
8483 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()),
8484 CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008485 // Default map type.
Samuel Antaocc10b852016-07-28 14:23:26 +00008486 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM);
Samuel Antaod486f842016-05-26 16:53:38 +00008487 } else if (CI.capturesVariableByCopy()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008488 CurBasePointers.push_back(CV);
8489 CurPointers.push_back(CV);
Samuel Antaod486f842016-05-26 16:53:38 +00008490 if (!RI.getType()->isAnyPointerType()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008491 // We have to signal to the runtime captures passed by value that are
8492 // not pointers.
George Rokos065755d2017-11-07 18:27:04 +00008493 CurMapTypes.push_back(OMP_MAP_LITERAL);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008494 CurSizes.push_back(CGF.Builder.CreateIntCast(
8495 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008496 } else {
8497 // Pointers are implicitly mapped with a zero size and no flags
8498 // (other than first map that is added for all implicit maps).
Alexey Bataevb3638132018-07-19 16:34:13 +00008499 CurMapTypes.push_back(OMP_MAP_NONE);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008500 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
Samuel Antaod486f842016-05-26 16:53:38 +00008501 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008502 const VarDecl *VD = CI.getCapturedVar();
8503 auto I = FirstPrivateDecls.find(VD);
8504 if (I != FirstPrivateDecls.end())
8505 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008506 } else {
8507 assert(CI.capturesVariable() && "Expected captured reference.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008508 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr());
Samuel Antaod486f842016-05-26 16:53:38 +00008509 QualType ElementType = PtrTy->getPointeeType();
Alexey Bataeva90fc662019-06-25 16:00:43 +00008510 CurSizes.push_back(CGF.Builder.CreateIntCast(
8511 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008512 // The default map type for a scalar/complex type is 'to' because by
8513 // default the value doesn't have to be retrieved. For an aggregate
8514 // type, the default is 'tofrom'.
Alexey Bataevb3638132018-07-19 16:34:13 +00008515 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI));
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008516 const VarDecl *VD = CI.getCapturedVar();
Alexey Bataevf288cf92019-06-27 18:53:07 +00008517 auto I = FirstPrivateDecls.find(VD);
8518 if (I != FirstPrivateDecls.end() &&
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008519 VD->getType().isConstant(CGF.getContext())) {
8520 llvm::Constant *Addr =
8521 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD);
8522 // Copy the value of the original variable to the new global copy.
8523 CGF.Builder.CreateMemCpy(
8524 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(),
8525 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)),
Rui Ueyama49a3ad22019-07-16 04:46:31 +00008526 CurSizes.back(), /*IsVolatile=*/false);
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008527 // Use new global variable as the base pointers.
8528 CurBasePointers.push_back(Addr);
8529 CurPointers.push_back(Addr);
8530 } else {
8531 CurBasePointers.push_back(CV);
Alexey Bataevf288cf92019-06-27 18:53:07 +00008532 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) {
Alexey Bataevc2b831f2019-04-02 16:03:40 +00008533 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue(
8534 CV, ElementType, CGF.getContext().getDeclAlign(VD),
8535 AlignmentSource::Decl));
8536 CurPointers.push_back(PtrAddr.getPointer());
8537 } else {
8538 CurPointers.push_back(CV);
8539 }
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008540 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008541 if (I != FirstPrivateDecls.end())
8542 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008543 }
George Rokos065755d2017-11-07 18:27:04 +00008544 // Every default map produces a single argument which is a target parameter.
8545 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM;
Alexey Bataevb3638132018-07-19 16:34:13 +00008546
8547 // Add flag stating this is an implicit map.
Alexey Bataevf288cf92019-06-27 18:53:07 +00008548 if (IsImplicit)
8549 CurMapTypes.back() |= OMP_MAP_IMPLICIT;
Samuel Antaod486f842016-05-26 16:53:38 +00008550 }
Samuel Antao86ace552016-04-27 22:40:57 +00008551};
Samuel Antaodf158d52016-04-27 22:58:19 +00008552} // anonymous namespace
8553
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008554/// Emit the arrays used to pass the captures and map information to the
Samuel Antaodf158d52016-04-27 22:58:19 +00008555/// offloading runtime library. If there is no map or capture information,
8556/// return nullptr by reference.
8557static void
Samuel Antaocc10b852016-07-28 14:23:26 +00008558emitOffloadingArrays(CodeGenFunction &CGF,
8559 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers,
Samuel Antaodf158d52016-04-27 22:58:19 +00008560 MappableExprsHandler::MapValuesArrayTy &Pointers,
8561 MappableExprsHandler::MapValuesArrayTy &Sizes,
Samuel Antaocc10b852016-07-28 14:23:26 +00008562 MappableExprsHandler::MapFlagsArrayTy &MapTypes,
8563 CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008564 CodeGenModule &CGM = CGF.CGM;
8565 ASTContext &Ctx = CGF.getContext();
Samuel Antaodf158d52016-04-27 22:58:19 +00008566
Samuel Antaocc10b852016-07-28 14:23:26 +00008567 // Reset the array information.
8568 Info.clearArrayInfo();
8569 Info.NumberOfPtrs = BasePointers.size();
Samuel Antaodf158d52016-04-27 22:58:19 +00008570
Samuel Antaocc10b852016-07-28 14:23:26 +00008571 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008572 // Detect if we have any capture size requiring runtime evaluation of the
8573 // size so that a constant array could be eventually used.
8574 bool hasRuntimeEvaluationCaptureSize = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008575 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008576 if (!isa<llvm::Constant>(S)) {
8577 hasRuntimeEvaluationCaptureSize = true;
8578 break;
8579 }
8580
Samuel Antaocc10b852016-07-28 14:23:26 +00008581 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true);
Richard Smith772e2662019-10-04 01:25:59 +00008582 QualType PointerArrayType = Ctx.getConstantArrayType(
8583 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal,
8584 /*IndexTypeQuals=*/0);
Samuel Antaodf158d52016-04-27 22:58:19 +00008585
Samuel Antaocc10b852016-07-28 14:23:26 +00008586 Info.BasePointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008587 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
Samuel Antaocc10b852016-07-28 14:23:26 +00008588 Info.PointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008589 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
8590
8591 // If we don't have any VLA types or other types that require runtime
8592 // evaluation, we can use a constant array for the map sizes, otherwise we
8593 // need to fill up the arrays as we do for the pointers.
Alexey Bataeva90fc662019-06-25 16:00:43 +00008594 QualType Int64Ty =
8595 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Samuel Antaodf158d52016-04-27 22:58:19 +00008596 if (hasRuntimeEvaluationCaptureSize) {
Richard Smith772e2662019-10-04 01:25:59 +00008597 QualType SizeArrayType = Ctx.getConstantArrayType(
8598 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal,
8599 /*IndexTypeQuals=*/0);
Samuel Antaocc10b852016-07-28 14:23:26 +00008600 Info.SizesArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008601 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
8602 } else {
8603 // We expect all the sizes to be constant, so we collect them to create
8604 // a constant array.
8605 SmallVector<llvm::Constant *, 16> ConstSizes;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008606 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008607 ConstSizes.push_back(cast<llvm::Constant>(S));
8608
8609 auto *SizesArrayInit = llvm::ConstantArray::get(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008610 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008611 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008612 auto *SizesArrayGbl = new llvm::GlobalVariable(
8613 CGM.getModule(), SizesArrayInit->getType(),
8614 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008615 SizesArrayInit, Name);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008616 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008617 Info.SizesArray = SizesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008618 }
8619
8620 // The map types are always constant so we don't need to generate code to
8621 // fill arrays. Instead, we create an array constant.
Alexey Bataevb3638132018-07-19 16:34:13 +00008622 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0);
8623 llvm::copy(MapTypes, Mapping.begin());
Samuel Antaodf158d52016-04-27 22:58:19 +00008624 llvm::Constant *MapTypesArrayInit =
Alexey Bataevb3638132018-07-19 16:34:13 +00008625 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008626 std::string MaptypesName =
8627 CGM.getOpenMPRuntime().getName({"offload_maptypes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008628 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
8629 CGM.getModule(), MapTypesArrayInit->getType(),
8630 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008631 MapTypesArrayInit, MaptypesName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008632 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008633 Info.MapTypesArray = MapTypesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008634
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008635 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) {
8636 llvm::Value *BPVal = *BasePointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008637 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008638 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008639 Info.BasePointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008640 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8641 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008642 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8643 CGF.Builder.CreateStore(BPVal, BPAddr);
8644
Samuel Antaocc10b852016-07-28 14:23:26 +00008645 if (Info.requiresDevicePointerInfo())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008646 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl())
Alexey Bataev43a919f2018-04-13 17:48:43 +00008647 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr);
Samuel Antaocc10b852016-07-28 14:23:26 +00008648
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008649 llvm::Value *PVal = Pointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008650 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008651 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008652 Info.PointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008653 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8654 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008655 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8656 CGF.Builder.CreateStore(PVal, PAddr);
8657
8658 if (hasRuntimeEvaluationCaptureSize) {
8659 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008660 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008661 Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008662 /*Idx0=*/0,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008663 /*Idx1=*/I);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008664 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty));
Samuel Antaodf158d52016-04-27 22:58:19 +00008665 CGF.Builder.CreateStore(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008666 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true),
Samuel Antaodf158d52016-04-27 22:58:19 +00008667 SAddr);
8668 }
8669 }
8670 }
8671}
Michael Krused47b9432019-08-05 18:43:21 +00008672
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008673/// Emit the arguments to be passed to the runtime library based on the
Samuel Antaodf158d52016-04-27 22:58:19 +00008674/// arrays of pointers, sizes and map types.
8675static void emitOffloadingArraysArgument(
8676 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg,
8677 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008678 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008679 CodeGenModule &CGM = CGF.CGM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008680 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008681 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008682 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8683 Info.BasePointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008684 /*Idx0=*/0, /*Idx1=*/0);
8685 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008686 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8687 Info.PointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008688 /*Idx0=*/0,
8689 /*Idx1=*/0);
8690 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008691 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008692 /*Idx0=*/0, /*Idx1=*/0);
8693 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
George Rokos63bc9d62017-11-21 18:25:12 +00008694 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008695 Info.MapTypesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008696 /*Idx0=*/0,
8697 /*Idx1=*/0);
8698 } else {
8699 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
8700 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008701 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008702 MapTypesArrayArg =
George Rokos63bc9d62017-11-21 18:25:12 +00008703 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008704 }
Samuel Antao86ace552016-04-27 22:40:57 +00008705}
8706
Alexey Bataev7bb33532019-01-07 21:30:43 +00008707/// Check for inner distribute directive.
8708static const OMPExecutableDirective *
8709getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
8710 const auto *CS = D.getInnermostCapturedStmt();
8711 const auto *Body =
8712 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00008713 const Stmt *ChildStmt =
8714 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
Alexey Bataev7bb33532019-01-07 21:30:43 +00008715
Alexey Bataev5c427362019-04-10 19:11:33 +00008716 if (const auto *NestedDir =
8717 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008718 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind();
8719 switch (D.getDirectiveKind()) {
8720 case OMPD_target:
8721 if (isOpenMPDistributeDirective(DKind))
8722 return NestedDir;
8723 if (DKind == OMPD_teams) {
8724 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
8725 /*IgnoreCaptured=*/true);
8726 if (!Body)
8727 return nullptr;
Alexey Bataev5c427362019-04-10 19:11:33 +00008728 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
8729 if (const auto *NND =
8730 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008731 DKind = NND->getDirectiveKind();
8732 if (isOpenMPDistributeDirective(DKind))
8733 return NND;
8734 }
8735 }
8736 return nullptr;
8737 case OMPD_target_teams:
8738 if (isOpenMPDistributeDirective(DKind))
8739 return NestedDir;
8740 return nullptr;
8741 case OMPD_target_parallel:
8742 case OMPD_target_simd:
8743 case OMPD_target_parallel_for:
8744 case OMPD_target_parallel_for_simd:
8745 return nullptr;
8746 case OMPD_target_teams_distribute:
8747 case OMPD_target_teams_distribute_simd:
8748 case OMPD_target_teams_distribute_parallel_for:
8749 case OMPD_target_teams_distribute_parallel_for_simd:
8750 case OMPD_parallel:
8751 case OMPD_for:
8752 case OMPD_parallel_for:
8753 case OMPD_parallel_sections:
8754 case OMPD_for_simd:
8755 case OMPD_parallel_for_simd:
8756 case OMPD_cancel:
8757 case OMPD_cancellation_point:
8758 case OMPD_ordered:
8759 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00008760 case OMPD_allocate:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008761 case OMPD_task:
8762 case OMPD_simd:
8763 case OMPD_sections:
8764 case OMPD_section:
8765 case OMPD_single:
8766 case OMPD_master:
8767 case OMPD_critical:
8768 case OMPD_taskyield:
8769 case OMPD_barrier:
8770 case OMPD_taskwait:
8771 case OMPD_taskgroup:
8772 case OMPD_atomic:
8773 case OMPD_flush:
8774 case OMPD_teams:
8775 case OMPD_target_data:
8776 case OMPD_target_exit_data:
8777 case OMPD_target_enter_data:
8778 case OMPD_distribute:
8779 case OMPD_distribute_simd:
8780 case OMPD_distribute_parallel_for:
8781 case OMPD_distribute_parallel_for_simd:
8782 case OMPD_teams_distribute:
8783 case OMPD_teams_distribute_simd:
8784 case OMPD_teams_distribute_parallel_for:
8785 case OMPD_teams_distribute_parallel_for_simd:
8786 case OMPD_target_update:
8787 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00008788 case OMPD_declare_variant:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008789 case OMPD_declare_target:
8790 case OMPD_end_declare_target:
8791 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00008792 case OMPD_declare_mapper:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008793 case OMPD_taskloop:
8794 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00008795 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00008796 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00008797 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04008798 case OMPD_parallel_master_taskloop_simd:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008799 case OMPD_requires:
8800 case OMPD_unknown:
8801 llvm_unreachable("Unexpected directive.");
8802 }
8803 }
8804
8805 return nullptr;
8806}
8807
Michael Krused47b9432019-08-05 18:43:21 +00008808/// Emit the user-defined mapper function. The code generation follows the
8809/// pattern in the example below.
8810/// \code
8811/// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle,
8812/// void *base, void *begin,
8813/// int64_t size, int64_t type) {
8814/// // Allocate space for an array section first.
8815/// if (size > 1 && !maptype.IsDelete)
8816/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
8817/// size*sizeof(Ty), clearToFrom(type));
8818/// // Map members.
8819/// for (unsigned i = 0; i < size; i++) {
8820/// // For each component specified by this mapper:
8821/// for (auto c : all_components) {
8822/// if (c.hasMapper())
8823/// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size,
8824/// c.arg_type);
8825/// else
8826/// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base,
8827/// c.arg_begin, c.arg_size, c.arg_type);
8828/// }
8829/// }
8830/// // Delete the array section.
8831/// if (size > 1 && maptype.IsDelete)
8832/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
8833/// size*sizeof(Ty), clearToFrom(type));
8834/// }
8835/// \endcode
8836void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D,
8837 CodeGenFunction *CGF) {
8838 if (UDMMap.count(D) > 0)
8839 return;
8840 ASTContext &C = CGM.getContext();
8841 QualType Ty = D->getType();
8842 QualType PtrTy = C.getPointerType(Ty).withRestrict();
8843 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
8844 auto *MapperVarDecl =
8845 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl());
8846 SourceLocation Loc = D->getLocation();
8847 CharUnits ElementSize = C.getTypeSizeInChars(Ty);
8848
8849 // Prepare mapper function arguments and attributes.
8850 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
8851 C.VoidPtrTy, ImplicitParamDecl::Other);
8852 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
8853 ImplicitParamDecl::Other);
8854 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
8855 C.VoidPtrTy, ImplicitParamDecl::Other);
8856 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
8857 ImplicitParamDecl::Other);
8858 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
8859 ImplicitParamDecl::Other);
8860 FunctionArgList Args;
8861 Args.push_back(&HandleArg);
8862 Args.push_back(&BaseArg);
8863 Args.push_back(&BeginArg);
8864 Args.push_back(&SizeArg);
8865 Args.push_back(&TypeArg);
8866 const CGFunctionInfo &FnInfo =
8867 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
8868 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
8869 SmallString<64> TyStr;
8870 llvm::raw_svector_ostream Out(TyStr);
8871 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out);
8872 std::string Name = getName({"omp_mapper", TyStr, D->getName()});
8873 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
8874 Name, &CGM.getModule());
8875 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
8876 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
8877 // Start the mapper function code generation.
8878 CodeGenFunction MapperCGF(CGM);
8879 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
8880 // Compute the starting and end addreses of array elements.
8881 llvm::Value *Size = MapperCGF.EmitLoadOfScalar(
8882 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false,
8883 C.getPointerType(Int64Ty), Loc);
8884 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast(
8885 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(),
8886 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy)));
8887 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size);
8888 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar(
8889 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false,
8890 C.getPointerType(Int64Ty), Loc);
8891 // Prepare common arguments for array initiation and deletion.
8892 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar(
8893 MapperCGF.GetAddrOfLocalVar(&HandleArg),
8894 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8895 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar(
8896 MapperCGF.GetAddrOfLocalVar(&BaseArg),
8897 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8898 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar(
8899 MapperCGF.GetAddrOfLocalVar(&BeginArg),
8900 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8901
8902 // Emit array initiation if this is an array section and \p MapType indicates
8903 // that memory allocation is required.
8904 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head");
8905 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
8906 ElementSize, HeadBB, /*IsInit=*/true);
8907
8908 // Emit a for loop to iterate through SizeArg of elements and map all of them.
8909
8910 // Emit the loop header block.
8911 MapperCGF.EmitBlock(HeadBB);
8912 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body");
8913 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done");
8914 // Evaluate whether the initial condition is satisfied.
8915 llvm::Value *IsEmpty =
8916 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty");
8917 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
8918 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock();
8919
8920 // Emit the loop body block.
8921 MapperCGF.EmitBlock(BodyBB);
8922 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI(
8923 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent");
8924 PtrPHI->addIncoming(PtrBegin, EntryBB);
8925 Address PtrCurrent =
8926 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg)
8927 .getAlignment()
8928 .alignmentOfArrayElement(ElementSize));
8929 // Privatize the declared variable of mapper to be the current array element.
8930 CodeGenFunction::OMPPrivateScope Scope(MapperCGF);
8931 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() {
8932 return MapperCGF
8933 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>())
8934 .getAddress();
8935 });
8936 (void)Scope.Privatize();
8937
8938 // Get map clause information. Fill up the arrays with all mapped variables.
8939 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
8940 MappableExprsHandler::MapValuesArrayTy Pointers;
8941 MappableExprsHandler::MapValuesArrayTy Sizes;
8942 MappableExprsHandler::MapFlagsArrayTy MapTypes;
8943 MappableExprsHandler MEHandler(*D, MapperCGF);
8944 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes);
8945
8946 // Call the runtime API __tgt_mapper_num_components to get the number of
8947 // pre-existing components.
8948 llvm::Value *OffloadingArgs[] = {Handle};
8949 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall(
8950 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs);
8951 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl(
8952 PreviousSize,
8953 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset()));
8954
8955 // Fill up the runtime mapper handle for all components.
8956 for (unsigned I = 0; I < BasePointers.size(); ++I) {
8957 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast(
8958 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
8959 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast(
8960 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
8961 llvm::Value *CurSizeArg = Sizes[I];
8962
8963 // Extract the MEMBER_OF field from the map type.
8964 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member");
8965 MapperCGF.EmitBlock(MemberBB);
8966 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]);
8967 llvm::Value *Member = MapperCGF.Builder.CreateAnd(
8968 OriMapType,
8969 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF));
8970 llvm::BasicBlock *MemberCombineBB =
8971 MapperCGF.createBasicBlock("omp.member.combine");
8972 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type");
8973 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member);
8974 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB);
8975 // Add the number of pre-existing components to the MEMBER_OF field if it
8976 // is valid.
8977 MapperCGF.EmitBlock(MemberCombineBB);
8978 llvm::Value *CombinedMember =
8979 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
8980 // Do nothing if it is not a member of previous components.
8981 MapperCGF.EmitBlock(TypeBB);
8982 llvm::PHINode *MemberMapType =
8983 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype");
8984 MemberMapType->addIncoming(OriMapType, MemberBB);
8985 MemberMapType->addIncoming(CombinedMember, MemberCombineBB);
8986
8987 // Combine the map type inherited from user-defined mapper with that
8988 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM
8989 // bits of the \a MapType, which is the input argument of the mapper
8990 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM
8991 // bits of MemberMapType.
8992 // [OpenMP 5.0], 1.2.6. map-type decay.
8993 // | alloc | to | from | tofrom | release | delete
8994 // ----------------------------------------------------------
8995 // alloc | alloc | alloc | alloc | alloc | release | delete
8996 // to | alloc | to | alloc | to | release | delete
8997 // from | alloc | alloc | from | from | release | delete
8998 // tofrom | alloc | to | from | tofrom | release | delete
8999 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd(
9000 MapType,
9001 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO |
9002 MappableExprsHandler::OMP_MAP_FROM));
9003 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc");
9004 llvm::BasicBlock *AllocElseBB =
9005 MapperCGF.createBasicBlock("omp.type.alloc.else");
9006 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to");
9007 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else");
9008 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from");
9009 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end");
9010 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom);
9011 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
9012 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM.
9013 MapperCGF.EmitBlock(AllocBB);
9014 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd(
9015 MemberMapType,
9016 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9017 MappableExprsHandler::OMP_MAP_FROM)));
9018 MapperCGF.Builder.CreateBr(EndBB);
9019 MapperCGF.EmitBlock(AllocElseBB);
9020 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ(
9021 LeftToFrom,
9022 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO));
9023 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
9024 // In case of to, clear OMP_MAP_FROM.
9025 MapperCGF.EmitBlock(ToBB);
9026 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd(
9027 MemberMapType,
9028 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM));
9029 MapperCGF.Builder.CreateBr(EndBB);
9030 MapperCGF.EmitBlock(ToElseBB);
9031 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ(
9032 LeftToFrom,
9033 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM));
9034 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB);
9035 // In case of from, clear OMP_MAP_TO.
9036 MapperCGF.EmitBlock(FromBB);
9037 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd(
9038 MemberMapType,
9039 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO));
9040 // In case of tofrom, do nothing.
9041 MapperCGF.EmitBlock(EndBB);
9042 llvm::PHINode *CurMapType =
9043 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype");
9044 CurMapType->addIncoming(AllocMapType, AllocBB);
9045 CurMapType->addIncoming(ToMapType, ToBB);
9046 CurMapType->addIncoming(FromMapType, FromBB);
9047 CurMapType->addIncoming(MemberMapType, ToElseBB);
9048
9049 // TODO: call the corresponding mapper function if a user-defined mapper is
9050 // associated with this map clause.
9051 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9052 // data structure.
9053 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg,
9054 CurSizeArg, CurMapType};
9055 MapperCGF.EmitRuntimeCall(
9056 createRuntimeFunction(OMPRTL__tgt_push_mapper_component),
9057 OffloadingArgs);
9058 }
9059
9060 // Update the pointer to point to the next element that needs to be mapped,
9061 // and check whether we have mapped all elements.
9062 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32(
9063 PtrPHI, /*Idx0=*/1, "omp.arraymap.next");
9064 PtrPHI->addIncoming(PtrNext, BodyBB);
9065 llvm::Value *IsDone =
9066 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone");
9067 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit");
9068 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
9069
9070 MapperCGF.EmitBlock(ExitBB);
9071 // Emit array deletion if this is an array section and \p MapType indicates
9072 // that deletion is required.
9073 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
9074 ElementSize, DoneBB, /*IsInit=*/false);
9075
9076 // Emit the function exit block.
9077 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true);
9078 MapperCGF.FinishFunction();
9079 UDMMap.try_emplace(D, Fn);
9080 if (CGF) {
9081 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn);
9082 Decls.second.push_back(D);
9083 }
9084}
9085
9086/// Emit the array initialization or deletion portion for user-defined mapper
9087/// code generation. First, it evaluates whether an array section is mapped and
9088/// whether the \a MapType instructs to delete this section. If \a IsInit is
9089/// true, and \a MapType indicates to not delete this array, array
9090/// initialization code is generated. If \a IsInit is false, and \a MapType
9091/// indicates to not this array, array deletion code is generated.
9092void CGOpenMPRuntime::emitUDMapperArrayInitOrDel(
9093 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base,
9094 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType,
9095 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) {
9096 StringRef Prefix = IsInit ? ".init" : ".del";
9097
9098 // Evaluate if this is an array section.
9099 llvm::BasicBlock *IsDeleteBB =
9100 MapperCGF.createBasicBlock("omp.array" + Prefix + ".evaldelete");
9101 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.array" + Prefix);
9102 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE(
9103 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray");
9104 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB);
9105
9106 // Evaluate if we are going to delete this section.
9107 MapperCGF.EmitBlock(IsDeleteBB);
9108 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd(
9109 MapType,
9110 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE));
9111 llvm::Value *DeleteCond;
9112 if (IsInit) {
9113 DeleteCond = MapperCGF.Builder.CreateIsNull(
9114 DeleteBit, "omp.array" + Prefix + ".delete");
9115 } else {
9116 DeleteCond = MapperCGF.Builder.CreateIsNotNull(
9117 DeleteBit, "omp.array" + Prefix + ".delete");
9118 }
9119 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB);
9120
9121 MapperCGF.EmitBlock(BodyBB);
9122 // Get the array size by multiplying element size and element number (i.e., \p
9123 // Size).
9124 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul(
9125 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
9126 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves
9127 // memory allocation/deletion purpose only.
9128 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd(
9129 MapType,
9130 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9131 MappableExprsHandler::OMP_MAP_FROM)));
9132 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9133 // data structure.
9134 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg};
9135 MapperCGF.EmitRuntimeCall(
9136 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs);
9137}
9138
Alexey Bataev7bb33532019-01-07 21:30:43 +00009139void CGOpenMPRuntime::emitTargetNumIterationsCall(
Alexey Bataevec7946e2019-09-23 14:06:51 +00009140 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9141 llvm::Value *DeviceID,
9142 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9143 const OMPLoopDirective &D)>
9144 SizeEmitter) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00009145 OpenMPDirectiveKind Kind = D.getDirectiveKind();
9146 const OMPExecutableDirective *TD = &D;
9147 // Get nested teams distribute kind directive, if any.
9148 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind))
9149 TD = getNestedDistributeDirective(CGM.getContext(), D);
9150 if (!TD)
9151 return;
9152 const auto *LD = cast<OMPLoopDirective>(TD);
Alexey Bataevec7946e2019-09-23 14:06:51 +00009153 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF,
Alexey Bataev7bb33532019-01-07 21:30:43 +00009154 PrePostActionTy &) {
Alexey Bataevec7946e2019-09-23 14:06:51 +00009155 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) {
9156 llvm::Value *Args[] = {DeviceID, NumIterations};
9157 CGF.EmitRuntimeCall(
9158 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args);
9159 }
Alexey Bataev7bb33532019-01-07 21:30:43 +00009160 };
9161 emitInlinedDirective(CGF, OMPD_unknown, CodeGen);
9162}
9163
Alexey Bataevec7946e2019-09-23 14:06:51 +00009164void CGOpenMPRuntime::emitTargetCall(
9165 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9166 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
9167 const Expr *Device,
9168 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9169 const OMPLoopDirective &D)>
9170 SizeEmitter) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00009171 if (!CGF.HaveInsertPoint())
9172 return;
Samuel Antaobed3c462015-10-02 16:14:20 +00009173
Samuel Antaoee8fb302016-01-06 13:42:12 +00009174 assert(OutlinedFn && "Invalid outlined function!");
9175
Alexey Bataev8451efa2018-01-15 19:06:12 +00009176 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>();
9177 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
Alexey Bataev475a7442018-01-12 19:39:11 +00009178 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009179 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF,
9180 PrePostActionTy &) {
9181 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9182 };
9183 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen);
Samuel Antao86ace552016-04-27 22:40:57 +00009184
Alexey Bataev8451efa2018-01-15 19:06:12 +00009185 CodeGenFunction::OMPTargetDataInfo InputInfo;
9186 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobed3c462015-10-02 16:14:20 +00009187 // Fill up the pointer arrays and transfer execution to the device.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009188 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo,
Alexey Bataevec7946e2019-09-23 14:06:51 +00009189 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars,
9190 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobed3c462015-10-02 16:14:20 +00009191 // On top of the arrays that were filled up, the target offloading call
9192 // takes as arguments the device id as well as the host pointer. The host
9193 // pointer is used by the runtime library to identify the current target
9194 // region, so it only has to be unique and not necessarily point to
9195 // anything. It could be the pointer to the outlined function that
9196 // implements the target region, but we aren't using that so that the
9197 // compiler doesn't need to keep that, and could therefore inline the host
9198 // function if proven worthwhile during optimization.
9199
Samuel Antaoee8fb302016-01-06 13:42:12 +00009200 // From this point on, we need to have an ID of the target region defined.
9201 assert(OutlinedFnID && "Invalid outlined function ID!");
Samuel Antaobed3c462015-10-02 16:14:20 +00009202
9203 // Emit device ID if any.
9204 llvm::Value *DeviceID;
George Rokos63bc9d62017-11-21 18:25:12 +00009205 if (Device) {
Samuel Antaobed3c462015-10-02 16:14:20 +00009206 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009207 CGF.Int64Ty, /*isSigned=*/true);
9208 } else {
9209 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9210 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009211
Samuel Antaodf158d52016-04-27 22:58:19 +00009212 // Emit the number of elements in the offloading arrays.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009213 llvm::Value *PointerNum =
9214 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaodf158d52016-04-27 22:58:19 +00009215
Samuel Antaob68e2db2016-03-03 16:20:23 +00009216 // Return value of the runtime offloading call.
9217 llvm::Value *Return;
9218
Alexey Bataev5c427362019-04-10 19:11:33 +00009219 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D);
9220 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009221
Alexey Bataevec7946e2019-09-23 14:06:51 +00009222 // Emit tripcount for the target loop-based directive.
9223 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter);
9224
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009225 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00009226 // The target region is an outlined function launched by the runtime
9227 // via calls __tgt_target() or __tgt_target_teams().
9228 //
9229 // __tgt_target() launches a target region with one team and one thread,
9230 // executing a serial region. This master thread may in turn launch
9231 // more threads within its team upon encountering a parallel region,
9232 // however, no additional teams can be launched on the device.
9233 //
9234 // __tgt_target_teams() launches a target region with one or more teams,
9235 // each with one or more threads. This call is required for target
9236 // constructs such as:
9237 // 'target teams'
9238 // 'target' / 'teams'
9239 // 'target teams distribute parallel for'
9240 // 'target parallel'
9241 // and so on.
9242 //
9243 // Note that on the host and CPU targets, the runtime implementation of
9244 // these calls simply call the outlined function without forking threads.
9245 // The outlined functions themselves have runtime calls to
9246 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by
9247 // the compiler in emitTeamsCall() and emitParallelCall().
9248 //
9249 // In contrast, on the NVPTX target, the implementation of
9250 // __tgt_target_teams() launches a GPU kernel with the requested number
9251 // of teams and threads so no additional calls to the runtime are required.
Samuel Antaob68e2db2016-03-03 16:20:23 +00009252 if (NumTeams) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00009253 // If we have NumTeams defined this means that we have an enclosed teams
9254 // region. Therefore we also expect to have NumThreads defined. These two
9255 // values should be defined in the presence of a teams directive,
9256 // regardless of having any clauses associated. If the user is using teams
9257 // but no clauses, these two values will be the default that should be
9258 // passed to the runtime library - a 32-bit integer with the value zero.
9259 assert(NumThreads && "Thread limit expression should be available along "
9260 "with number of teams.");
Alexey Bataev8451efa2018-01-15 19:06:12 +00009261 llvm::Value *OffloadingArgs[] = {DeviceID,
9262 OutlinedFnID,
9263 PointerNum,
9264 InputInfo.BasePointersArray.getPointer(),
9265 InputInfo.PointersArray.getPointer(),
9266 InputInfo.SizesArray.getPointer(),
9267 MapTypesArray,
9268 NumTeams,
9269 NumThreads};
Samuel Antaob68e2db2016-03-03 16:20:23 +00009270 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00009271 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait
9272 : OMPRTL__tgt_target_teams),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009273 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009274 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009275 llvm::Value *OffloadingArgs[] = {DeviceID,
9276 OutlinedFnID,
9277 PointerNum,
9278 InputInfo.BasePointersArray.getPointer(),
9279 InputInfo.PointersArray.getPointer(),
9280 InputInfo.SizesArray.getPointer(),
9281 MapTypesArray};
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009282 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00009283 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait
9284 : OMPRTL__tgt_target),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009285 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009286 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009287
Alexey Bataev2a007e02017-10-02 14:20:58 +00009288 // Check the error code and execute the host version if required.
9289 llvm::BasicBlock *OffloadFailedBlock =
9290 CGF.createBasicBlock("omp_offload.failed");
9291 llvm::BasicBlock *OffloadContBlock =
9292 CGF.createBasicBlock("omp_offload.cont");
9293 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return);
9294 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
9295
9296 CGF.EmitBlock(OffloadFailedBlock);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009297 if (RequiresOuterTask) {
9298 CapturedVars.clear();
9299 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9300 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009301 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev2a007e02017-10-02 14:20:58 +00009302 CGF.EmitBranch(OffloadContBlock);
9303
9304 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00009305 };
9306
Samuel Antaoee8fb302016-01-06 13:42:12 +00009307 // Notify that the host version must be executed.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009308 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars,
9309 RequiresOuterTask](CodeGenFunction &CGF,
9310 PrePostActionTy &) {
9311 if (RequiresOuterTask) {
9312 CapturedVars.clear();
9313 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9314 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009315 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009316 };
9317
9318 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray,
9319 &CapturedVars, RequiresOuterTask,
9320 &CS](CodeGenFunction &CGF, PrePostActionTy &) {
9321 // Fill up the arrays with all the captured variables.
9322 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
9323 MappableExprsHandler::MapValuesArrayTy Pointers;
9324 MappableExprsHandler::MapValuesArrayTy Sizes;
9325 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9326
Alexey Bataev8451efa2018-01-15 19:06:12 +00009327 // Get mappable expression information.
9328 MappableExprsHandler MEHandler(D, CGF);
Alexey Bataev969dbc02018-11-08 15:47:39 +00009329 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
Alexey Bataev8451efa2018-01-15 19:06:12 +00009330
9331 auto RI = CS.getCapturedRecordDecl()->field_begin();
9332 auto CV = CapturedVars.begin();
9333 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
9334 CE = CS.capture_end();
9335 CI != CE; ++CI, ++RI, ++CV) {
Alexey Bataevb3638132018-07-19 16:34:13 +00009336 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers;
9337 MappableExprsHandler::MapValuesArrayTy CurPointers;
9338 MappableExprsHandler::MapValuesArrayTy CurSizes;
9339 MappableExprsHandler::MapFlagsArrayTy CurMapTypes;
9340 MappableExprsHandler::StructRangeInfoTy PartialStruct;
Alexey Bataev8451efa2018-01-15 19:06:12 +00009341
9342 // VLA sizes are passed to the outlined region by copy and do not have map
9343 // information associated.
9344 if (CI->capturesVariableArrayType()) {
9345 CurBasePointers.push_back(*CV);
9346 CurPointers.push_back(*CV);
Alexey Bataeva90fc662019-06-25 16:00:43 +00009347 CurSizes.push_back(CGF.Builder.CreateIntCast(
9348 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev8451efa2018-01-15 19:06:12 +00009349 // Copy to the device as an argument. No need to retrieve it.
9350 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL |
Alexey Bataevf288cf92019-06-27 18:53:07 +00009351 MappableExprsHandler::OMP_MAP_TARGET_PARAM |
9352 MappableExprsHandler::OMP_MAP_IMPLICIT);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009353 } else {
9354 // If we have any information in the map clause, we use it, otherwise we
9355 // just do a default mapping.
9356 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00009357 CurSizes, CurMapTypes, PartialStruct);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009358 if (CurBasePointers.empty())
9359 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers,
9360 CurPointers, CurSizes, CurMapTypes);
Alexey Bataev60705422018-10-30 15:50:12 +00009361 // Generate correct mapping for variables captured by reference in
9362 // lambdas.
9363 if (CI->capturesVariable())
Alexey Bataev969dbc02018-11-08 15:47:39 +00009364 MEHandler.generateInfoForLambdaCaptures(
9365 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes,
9366 CurMapTypes, LambdaPointers);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009367 }
9368 // We expect to have at least an element of information for this capture.
9369 assert(!CurBasePointers.empty() &&
9370 "Non-existing map pointer for capture!");
9371 assert(CurBasePointers.size() == CurPointers.size() &&
9372 CurBasePointers.size() == CurSizes.size() &&
9373 CurBasePointers.size() == CurMapTypes.size() &&
9374 "Inconsistent map information sizes!");
9375
Alexey Bataevb3638132018-07-19 16:34:13 +00009376 // If there is an entry in PartialStruct it means we have a struct with
9377 // individual members mapped. Emit an extra combined entry.
9378 if (PartialStruct.Base.isValid())
9379 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes,
9380 CurMapTypes, PartialStruct);
9381
Alexey Bataev8451efa2018-01-15 19:06:12 +00009382 // We need to append the results of this capture to what we already have.
9383 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
9384 Pointers.append(CurPointers.begin(), CurPointers.end());
9385 Sizes.append(CurSizes.begin(), CurSizes.end());
9386 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end());
9387 }
Alexey Bataev60705422018-10-30 15:50:12 +00009388 // Adjust MEMBER_OF flags for the lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00009389 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers,
9390 Pointers, MapTypes);
Alexey Bataev92327c52018-03-26 16:40:55 +00009391 // Map other list items in the map clause which are not captured variables
9392 // but "declare target link" global variables.
Alexey Bataevb3638132018-07-19 16:34:13 +00009393 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes,
9394 MapTypes);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009395
9396 TargetDataInfo Info;
9397 // Fill up the arrays and create the arguments.
9398 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
9399 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
9400 Info.PointersArray, Info.SizesArray,
9401 Info.MapTypesArray, Info);
9402 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
9403 InputInfo.BasePointersArray =
9404 Address(Info.BasePointersArray, CGM.getPointerAlign());
9405 InputInfo.PointersArray =
9406 Address(Info.PointersArray, CGM.getPointerAlign());
9407 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign());
9408 MapTypesArray = Info.MapTypesArray;
9409 if (RequiresOuterTask)
9410 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
9411 else
9412 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
9413 };
9414
9415 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask](
9416 CodeGenFunction &CGF, PrePostActionTy &) {
9417 if (RequiresOuterTask) {
9418 CodeGenFunction::OMPTargetDataInfo InputInfo;
9419 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo);
9420 } else {
9421 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen);
9422 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009423 };
9424
9425 // If we have a target function ID it means that we need to support
9426 // offloading, otherwise, just execute on the host. We need to execute on host
9427 // regardless of the conditional in the if clause if, e.g., the user do not
9428 // specify target triples.
9429 if (OutlinedFnID) {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009430 if (IfCond) {
9431 emitOMPIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
9432 } else {
9433 RegionCodeGenTy ThenRCG(TargetThenGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00009434 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00009435 }
9436 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009437 RegionCodeGenTy ElseRCG(TargetElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00009438 ElseRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00009439 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009440}
Samuel Antaoee8fb302016-01-06 13:42:12 +00009441
9442void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
9443 StringRef ParentName) {
9444 if (!S)
9445 return;
9446
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009447 // Codegen OMP target directives that offload compute to the device.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009448 bool RequiresDeviceCodegen =
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009449 isa<OMPExecutableDirective>(S) &&
9450 isOpenMPTargetExecutionDirective(
9451 cast<OMPExecutableDirective>(S)->getDirectiveKind());
Samuel Antaoee8fb302016-01-06 13:42:12 +00009452
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009453 if (RequiresDeviceCodegen) {
9454 const auto &E = *cast<OMPExecutableDirective>(S);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009455 unsigned DeviceID;
9456 unsigned FileID;
9457 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009458 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID,
Samuel Antao2de62b02016-02-13 23:35:10 +00009459 FileID, Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009460
9461 // Is this a target region that should not be emitted as an entry point? If
9462 // so just signal we are done with this target region.
Samuel Antao2de62b02016-02-13 23:35:10 +00009463 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
9464 ParentName, Line))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009465 return;
9466
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009467 switch (E.getDirectiveKind()) {
9468 case OMPD_target:
9469 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName,
9470 cast<OMPTargetDirective>(E));
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009471 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009472 case OMPD_target_parallel:
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009473 CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009474 CGM, ParentName, cast<OMPTargetParallelDirective>(E));
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009475 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009476 case OMPD_target_teams:
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009477 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009478 CGM, ParentName, cast<OMPTargetTeamsDirective>(E));
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009479 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009480 case OMPD_target_teams_distribute:
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009481 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009482 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E));
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009483 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009484 case OMPD_target_teams_distribute_simd:
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009485 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009486 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E));
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009487 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009488 case OMPD_target_parallel_for:
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009489 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009490 CGM, ParentName, cast<OMPTargetParallelForDirective>(E));
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009491 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009492 case OMPD_target_parallel_for_simd:
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009493 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009494 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E));
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009495 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009496 case OMPD_target_simd:
Alexey Bataevf8365372017-11-17 17:57:25 +00009497 CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009498 CGM, ParentName, cast<OMPTargetSimdDirective>(E));
Alexey Bataevf8365372017-11-17 17:57:25 +00009499 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009500 case OMPD_target_teams_distribute_parallel_for:
Carlo Bertolli52978c32018-01-03 21:12:44 +00009501 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
9502 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009503 cast<OMPTargetTeamsDistributeParallelForDirective>(E));
Carlo Bertolli52978c32018-01-03 21:12:44 +00009504 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009505 case OMPD_target_teams_distribute_parallel_for_simd:
Alexey Bataev647dd842018-01-15 20:59:40 +00009506 CodeGenFunction::
9507 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
9508 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009509 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E));
Alexey Bataev647dd842018-01-15 20:59:40 +00009510 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009511 case OMPD_parallel:
9512 case OMPD_for:
9513 case OMPD_parallel_for:
9514 case OMPD_parallel_sections:
9515 case OMPD_for_simd:
9516 case OMPD_parallel_for_simd:
9517 case OMPD_cancel:
9518 case OMPD_cancellation_point:
9519 case OMPD_ordered:
9520 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00009521 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009522 case OMPD_task:
9523 case OMPD_simd:
9524 case OMPD_sections:
9525 case OMPD_section:
9526 case OMPD_single:
9527 case OMPD_master:
9528 case OMPD_critical:
9529 case OMPD_taskyield:
9530 case OMPD_barrier:
9531 case OMPD_taskwait:
9532 case OMPD_taskgroup:
9533 case OMPD_atomic:
9534 case OMPD_flush:
9535 case OMPD_teams:
9536 case OMPD_target_data:
9537 case OMPD_target_exit_data:
9538 case OMPD_target_enter_data:
9539 case OMPD_distribute:
9540 case OMPD_distribute_simd:
9541 case OMPD_distribute_parallel_for:
9542 case OMPD_distribute_parallel_for_simd:
9543 case OMPD_teams_distribute:
9544 case OMPD_teams_distribute_simd:
9545 case OMPD_teams_distribute_parallel_for:
9546 case OMPD_teams_distribute_parallel_for_simd:
9547 case OMPD_target_update:
9548 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00009549 case OMPD_declare_variant:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009550 case OMPD_declare_target:
9551 case OMPD_end_declare_target:
9552 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00009553 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009554 case OMPD_taskloop:
9555 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00009556 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00009557 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00009558 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04009559 case OMPD_parallel_master_taskloop_simd:
Kelvin Li1408f912018-09-26 04:28:39 +00009560 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009561 case OMPD_unknown:
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009562 llvm_unreachable("Unknown target directive for OpenMP device codegen.");
9563 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009564 return;
9565 }
9566
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009567 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
Alexey Bataev475a7442018-01-12 19:39:11 +00009568 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009569 return;
9570
9571 scanForTargetRegionsFunctions(
Alexey Bataev475a7442018-01-12 19:39:11 +00009572 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009573 return;
9574 }
9575
9576 // If this is a lambda function, look into its body.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009577 if (const auto *L = dyn_cast<LambdaExpr>(S))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009578 S = L->getBody();
9579
9580 // Keep looking for target regions recursively.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009581 for (const Stmt *II : S->children())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009582 scanForTargetRegionsFunctions(II, ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009583}
9584
9585bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009586 // If emitting code for the host, we do not process FD here. Instead we do
9587 // the normal code generation.
Alexey Bataev729e2422019-08-23 16:11:14 +00009588 if (!CGM.getLangOpts().OpenMPIsDevice) {
9589 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) {
9590 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9591 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9592 // Do not emit device_type(nohost) functions for the host.
9593 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
9594 return true;
9595 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009596 return false;
Alexey Bataev729e2422019-08-23 16:11:14 +00009597 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009598
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009599 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009600 StringRef Name = CGM.getMangledName(GD);
9601 // Try to detect target regions in the function.
Alexey Bataev729e2422019-08-23 16:11:14 +00009602 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009603 scanForTargetRegionsFunctions(FD->getBody(), Name);
Alexey Bataev729e2422019-08-23 16:11:14 +00009604 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9605 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9606 // Do not emit device_type(nohost) functions for the host.
9607 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
9608 return true;
9609 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009610
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009611 // Do not to emit function if it is not marked as declare target.
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009612 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009613 AlreadyEmittedTargetFunctions.count(Name) == 0;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009614}
9615
9616bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
9617 if (!CGM.getLangOpts().OpenMPIsDevice)
9618 return false;
9619
9620 // Check if there are Ctors/Dtors in this declaration and look for target
9621 // regions in it. We use the complete variant to produce the kernel name
9622 // mangling.
9623 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009624 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
9625 for (const CXXConstructorDecl *Ctor : RD->ctors()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009626 StringRef ParentName =
9627 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
9628 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
9629 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009630 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009631 StringRef ParentName =
9632 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
9633 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
9634 }
9635 }
9636
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009637 // Do not to emit variable if it is not marked as declare target.
Alexey Bataev92327c52018-03-26 16:40:55 +00009638 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009639 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
9640 cast<VarDecl>(GD.getDecl()));
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009641 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
9642 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9643 HasRequiresUnifiedSharedMemory)) {
Alexey Bataevd01b7492018-08-15 19:45:12 +00009644 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009645 return true;
9646 }
9647 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009648}
9649
Alexey Bataev1af5bd52019-03-05 17:47:18 +00009650llvm::Constant *
9651CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF,
9652 const VarDecl *VD) {
9653 assert(VD->getType().isConstant(CGM.getContext()) &&
9654 "Expected constant variable.");
9655 StringRef VarName;
9656 llvm::Constant *Addr;
9657 llvm::GlobalValue::LinkageTypes Linkage;
9658 QualType Ty = VD->getType();
9659 SmallString<128> Buffer;
9660 {
9661 unsigned DeviceID;
9662 unsigned FileID;
9663 unsigned Line;
9664 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID,
9665 FileID, Line);
9666 llvm::raw_svector_ostream OS(Buffer);
9667 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID)
9668 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
9669 VarName = OS.str();
9670 }
9671 Linkage = llvm::GlobalValue::InternalLinkage;
9672 Addr =
9673 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName,
9674 getDefaultFirstprivateAddressSpace());
9675 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage);
9676 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty);
9677 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr));
9678 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9679 VarName, Addr, VarSize,
9680 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage);
9681 return Addr;
9682}
9683
Alexey Bataev03f270c2018-03-30 18:31:07 +00009684void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
9685 llvm::Constant *Addr) {
Alexey Bataev36724b72019-10-03 16:46:49 +00009686 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
9687 !CGM.getLangOpts().OpenMPIsDevice)
Alexey Bataev4db9dc62019-09-23 15:53:51 +00009688 return;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009689 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9690 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
9691 if (!Res) {
9692 if (CGM.getLangOpts().OpenMPIsDevice) {
9693 // Register non-target variables being emitted in device code (debug info
9694 // may cause this).
9695 StringRef VarName = CGM.getMangledName(VD);
9696 EmittedNonTargetVariables.try_emplace(VarName, Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009697 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009698 return;
Alexey Bataev03f270c2018-03-30 18:31:07 +00009699 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009700 // Register declare target variables.
9701 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
9702 StringRef VarName;
9703 CharUnits VarSize;
9704 llvm::GlobalValue::LinkageTypes Linkage;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009705
9706 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9707 !HasRequiresUnifiedSharedMemory) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009708 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9709 VarName = CGM.getMangledName(VD);
9710 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) {
9711 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType());
9712 assert(!VarSize.isZero() && "Expected non-zero size of the variable");
9713 } else {
9714 VarSize = CharUnits::Zero();
9715 }
9716 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
9717 // Temp solution to prevent optimizations of the internal variables.
9718 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) {
9719 std::string RefName = getName({VarName, "ref"});
9720 if (!CGM.GetGlobalValue(RefName)) {
9721 llvm::Constant *AddrRef =
9722 getOrCreateInternalVariable(Addr->getType(), RefName);
9723 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef);
9724 GVAddrRef->setConstant(/*Val=*/true);
9725 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage);
9726 GVAddrRef->setInitializer(Addr);
9727 CGM.addCompilerUsedGlobal(GVAddrRef);
9728 }
9729 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009730 } else {
9731 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
9732 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9733 HasRequiresUnifiedSharedMemory)) &&
9734 "Declare target attribute must link or to with unified memory.");
9735 if (*Res == OMPDeclareTargetDeclAttr::MT_Link)
9736 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink;
9737 else
9738 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9739
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009740 if (CGM.getLangOpts().OpenMPIsDevice) {
9741 VarName = Addr->getName();
9742 Addr = nullptr;
9743 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009744 VarName = getAddrOfDeclareTargetVar(VD).getName();
9745 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009746 }
9747 VarSize = CGM.getPointerSize();
9748 Linkage = llvm::GlobalValue::WeakAnyLinkage;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009749 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009750
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009751 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9752 VarName, Addr, VarSize, Flags, Linkage);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009753}
9754
Samuel Antaoee8fb302016-01-06 13:42:12 +00009755bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009756 if (isa<FunctionDecl>(GD.getDecl()) ||
9757 isa<OMPDeclareReductionDecl>(GD.getDecl()))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009758 return emitTargetFunctions(GD);
9759
9760 return emitTargetGlobalVariable(GD);
9761}
9762
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009763void CGOpenMPRuntime::emitDeferredTargetDecls() const {
9764 for (const VarDecl *VD : DeferredGlobalVariables) {
9765 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009766 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009767 if (!Res)
9768 continue;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009769 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9770 !HasRequiresUnifiedSharedMemory) {
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009771 CGM.EmitGlobal(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009772 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009773 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
9774 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9775 HasRequiresUnifiedSharedMemory)) &&
9776 "Expected link clause or to clause with unified memory.");
9777 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009778 }
9779 }
9780}
9781
Alexey Bataev60705422018-10-30 15:50:12 +00009782void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas(
9783 CodeGenFunction &CGF, const OMPExecutableDirective &D) const {
9784 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) &&
9785 " Expected target-based directive.");
9786}
9787
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009788void CGOpenMPRuntime::checkArchForUnifiedAddressing(
9789 const OMPRequiresDecl *D) {
9790 for (const OMPClause *Clause : D->clauselists()) {
9791 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
9792 HasRequiresUnifiedSharedMemory = true;
9793 break;
9794 }
9795 }
9796}
9797
Alexey Bataevc5687252019-03-21 19:35:27 +00009798bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD,
9799 LangAS &AS) {
9800 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())
9801 return false;
9802 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
9803 switch(A->getAllocatorType()) {
9804 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
9805 // Not supported, fallback to the default mem space.
9806 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
9807 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
9808 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
9809 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
9810 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
9811 case OMPAllocateDeclAttr::OMPConstMemAlloc:
9812 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
9813 AS = LangAS::Default;
9814 return true;
9815 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
9816 llvm_unreachable("Expected predefined allocator for the variables with the "
9817 "static storage.");
9818 }
9819 return false;
9820}
9821
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00009822bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const {
9823 return HasRequiresUnifiedSharedMemory;
9824}
9825
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009826CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
9827 CodeGenModule &CGM)
9828 : CGM(CGM) {
9829 if (CGM.getLangOpts().OpenMPIsDevice) {
9830 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
9831 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
9832 }
9833}
9834
9835CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() {
9836 if (CGM.getLangOpts().OpenMPIsDevice)
9837 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
9838}
9839
Alexey Bataev6d944102018-05-02 15:45:28 +00009840bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009841 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal)
9842 return true;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009843
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009844 StringRef Name = CGM.getMangledName(GD);
Alexey Bataev6d944102018-05-02 15:45:28 +00009845 const auto *D = cast<FunctionDecl>(GD.getDecl());
Alexey Bataev34f8a702018-03-28 14:28:54 +00009846 // Do not to emit function if it is marked as declare target as it was already
9847 // emitted.
Alexey Bataev97b72212018-08-14 18:31:20 +00009848 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009849 if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) {
9850 if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name)))
Alexey Bataev34f8a702018-03-28 14:28:54 +00009851 return !F->isDeclaration();
9852 return false;
9853 }
9854 return true;
9855 }
9856
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009857 return !AlreadyEmittedTargetFunctions.insert(Name).second;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009858}
9859
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009860llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() {
9861 // If we don't have entries or if we are emitting code for the device, we
9862 // don't need to do anything.
9863 if (CGM.getLangOpts().OMPTargetTriples.empty() ||
9864 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice ||
9865 (OffloadEntriesInfoManager.empty() &&
9866 !HasEmittedDeclareTargetRegion &&
9867 !HasEmittedTargetRegion))
9868 return nullptr;
9869
9870 // Create and register the function that handles the requires directives.
9871 ASTContext &C = CGM.getContext();
9872
9873 llvm::Function *RequiresRegFn;
9874 {
9875 CodeGenFunction CGF(CGM);
9876 const auto &FI = CGM.getTypes().arrangeNullaryFunction();
9877 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
9878 std::string ReqName = getName({"omp_offloading", "requires_reg"});
9879 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI);
9880 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {});
9881 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE;
9882 // TODO: check for other requires clauses.
9883 // The requires directive takes effect only when a target region is
9884 // present in the compilation unit. Otherwise it is ignored and not
9885 // passed to the runtime. This avoids the runtime from throwing an error
9886 // for mismatching requires clauses across compilation units that don't
9887 // contain at least 1 target region.
9888 assert((HasEmittedTargetRegion ||
9889 HasEmittedDeclareTargetRegion ||
9890 !OffloadEntriesInfoManager.empty()) &&
9891 "Target or declare target region expected.");
9892 if (HasRequiresUnifiedSharedMemory)
9893 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY;
9894 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires),
9895 llvm::ConstantInt::get(CGM.Int64Ty, Flags));
9896 CGF.FinishFunction();
9897 }
9898 return RequiresRegFn;
9899}
9900
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009901void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
9902 const OMPExecutableDirective &D,
9903 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00009904 llvm::Function *OutlinedFn,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009905 ArrayRef<llvm::Value *> CapturedVars) {
9906 if (!CGF.HaveInsertPoint())
9907 return;
9908
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009909 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009910 CodeGenFunction::RunCleanupsScope Scope(CGF);
9911
9912 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
9913 llvm::Value *Args[] = {
9914 RTLoc,
9915 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
9916 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
9917 llvm::SmallVector<llvm::Value *, 16> RealArgs;
9918 RealArgs.append(std::begin(Args), std::end(Args));
9919 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
9920
James Y Knight9871db02019-02-05 16:42:33 +00009921 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009922 CGF.EmitRuntimeCall(RTLFn, RealArgs);
9923}
9924
9925void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
Carlo Bertollic6872252016-04-04 15:55:02 +00009926 const Expr *NumTeams,
9927 const Expr *ThreadLimit,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009928 SourceLocation Loc) {
9929 if (!CGF.HaveInsertPoint())
9930 return;
9931
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009932 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009933
Carlo Bertollic6872252016-04-04 15:55:02 +00009934 llvm::Value *NumTeamsVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009935 NumTeams
Carlo Bertollic6872252016-04-04 15:55:02 +00009936 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
9937 CGF.CGM.Int32Ty, /* isSigned = */ true)
9938 : CGF.Builder.getInt32(0);
9939
9940 llvm::Value *ThreadLimitVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009941 ThreadLimit
Carlo Bertollic6872252016-04-04 15:55:02 +00009942 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
9943 CGF.CGM.Int32Ty, /* isSigned = */ true)
9944 : CGF.Builder.getInt32(0);
9945
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009946 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
Carlo Bertollic6872252016-04-04 15:55:02 +00009947 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
9948 ThreadLimitVal};
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009949 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams),
9950 PushNumTeamsArgs);
9951}
Samuel Antaodf158d52016-04-27 22:58:19 +00009952
Samuel Antaocc10b852016-07-28 14:23:26 +00009953void CGOpenMPRuntime::emitTargetDataCalls(
9954 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
9955 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009956 if (!CGF.HaveInsertPoint())
9957 return;
9958
Samuel Antaocc10b852016-07-28 14:23:26 +00009959 // Action used to replace the default codegen action and turn privatization
9960 // off.
9961 PrePostActionTy NoPrivAction;
Samuel Antaodf158d52016-04-27 22:58:19 +00009962
9963 // Generate the code for the opening of the data environment. Capture all the
9964 // arguments of the runtime call by reference because they are used in the
9965 // closing of the region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009966 auto &&BeginThenGen = [this, &D, Device, &Info,
9967 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009968 // Fill up the arrays with all the mapped variables.
Samuel Antaocc10b852016-07-28 14:23:26 +00009969 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
Samuel Antaodf158d52016-04-27 22:58:19 +00009970 MappableExprsHandler::MapValuesArrayTy Pointers;
9971 MappableExprsHandler::MapValuesArrayTy Sizes;
9972 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9973
9974 // Get map clause information.
9975 MappableExprsHandler MCHandler(D, CGF);
9976 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
Samuel Antaodf158d52016-04-27 22:58:19 +00009977
9978 // Fill up the arrays and create the arguments.
Samuel Antaocc10b852016-07-28 14:23:26 +00009979 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +00009980
9981 llvm::Value *BasePointersArrayArg = nullptr;
9982 llvm::Value *PointersArrayArg = nullptr;
9983 llvm::Value *SizesArrayArg = nullptr;
9984 llvm::Value *MapTypesArrayArg = nullptr;
9985 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00009986 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +00009987
9988 // Emit device ID if any.
9989 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +00009990 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009991 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009992 CGF.Int64Ty, /*isSigned=*/true);
9993 } else {
9994 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9995 }
Samuel Antaodf158d52016-04-27 22:58:19 +00009996
9997 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009998 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +00009999
10000 llvm::Value *OffloadingArgs[] = {
10001 DeviceID, PointerNum, BasePointersArrayArg,
10002 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010003 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin),
Samuel Antaodf158d52016-04-27 22:58:19 +000010004 OffloadingArgs);
Samuel Antaocc10b852016-07-28 14:23:26 +000010005
10006 // If device pointer privatization is required, emit the body of the region
10007 // here. It will have to be duplicated: with and without privatization.
10008 if (!Info.CaptureDeviceAddrMap.empty())
10009 CodeGen(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010010 };
10011
10012 // Generate code for the closing of the data region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010013 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF,
10014 PrePostActionTy &) {
Samuel Antaocc10b852016-07-28 14:23:26 +000010015 assert(Info.isValid() && "Invalid data environment closing arguments.");
Samuel Antaodf158d52016-04-27 22:58:19 +000010016
10017 llvm::Value *BasePointersArrayArg = nullptr;
10018 llvm::Value *PointersArrayArg = nullptr;
10019 llvm::Value *SizesArrayArg = nullptr;
10020 llvm::Value *MapTypesArrayArg = nullptr;
10021 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +000010022 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +000010023
10024 // Emit device ID if any.
10025 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010026 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +000010027 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010028 CGF.Int64Ty, /*isSigned=*/true);
10029 } else {
10030 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10031 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010032
10033 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010034 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +000010035
10036 llvm::Value *OffloadingArgs[] = {
10037 DeviceID, PointerNum, BasePointersArrayArg,
10038 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010039 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end),
Samuel Antaodf158d52016-04-27 22:58:19 +000010040 OffloadingArgs);
10041 };
10042
Samuel Antaocc10b852016-07-28 14:23:26 +000010043 // If we need device pointer privatization, we need to emit the body of the
10044 // region with no privatization in the 'else' branch of the conditional.
10045 // Otherwise, we don't have to do anything.
10046 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF,
10047 PrePostActionTy &) {
10048 if (!Info.CaptureDeviceAddrMap.empty()) {
10049 CodeGen.setAction(NoPrivAction);
10050 CodeGen(CGF);
10051 }
10052 };
10053
10054 // We don't have to do anything to close the region if the if clause evaluates
10055 // to false.
10056 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
Samuel Antaodf158d52016-04-27 22:58:19 +000010057
10058 if (IfCond) {
Samuel Antaocc10b852016-07-28 14:23:26 +000010059 emitOMPIfClause(CGF, IfCond, BeginThenGen, BeginElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +000010060 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +000010061 RegionCodeGenTy RCG(BeginThenGen);
10062 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010063 }
10064
Samuel Antaocc10b852016-07-28 14:23:26 +000010065 // If we don't require privatization of device pointers, we emit the body in
10066 // between the runtime calls. This avoids duplicating the body code.
10067 if (Info.CaptureDeviceAddrMap.empty()) {
10068 CodeGen.setAction(NoPrivAction);
10069 CodeGen(CGF);
10070 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010071
10072 if (IfCond) {
Samuel Antaocc10b852016-07-28 14:23:26 +000010073 emitOMPIfClause(CGF, IfCond, EndThenGen, EndElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +000010074 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +000010075 RegionCodeGenTy RCG(EndThenGen);
10076 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010077 }
10078}
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010079
Samuel Antao8d2d7302016-05-26 18:30:22 +000010080void CGOpenMPRuntime::emitTargetDataStandAloneCall(
Samuel Antao8dd66282016-04-27 23:14:30 +000010081 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10082 const Expr *Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010083 if (!CGF.HaveInsertPoint())
10084 return;
10085
Samuel Antao8dd66282016-04-27 23:14:30 +000010086 assert((isa<OMPTargetEnterDataDirective>(D) ||
Samuel Antao8d2d7302016-05-26 18:30:22 +000010087 isa<OMPTargetExitDataDirective>(D) ||
10088 isa<OMPTargetUpdateDirective>(D)) &&
10089 "Expecting either target enter, exit data, or update directives.");
Samuel Antao8dd66282016-04-27 23:14:30 +000010090
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010091 CodeGenFunction::OMPTargetDataInfo InputInfo;
10092 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010093 // Generate the code for the opening of the data environment.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010094 auto &&ThenGen = [this, &D, Device, &InputInfo,
10095 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010096 // Emit device ID if any.
10097 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010098 if (Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010099 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010100 CGF.Int64Ty, /*isSigned=*/true);
10101 } else {
10102 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10103 }
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010104
10105 // Emit the number of elements in the offloading arrays.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010106 llvm::Constant *PointerNum =
10107 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010108
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010109 llvm::Value *OffloadingArgs[] = {DeviceID,
10110 PointerNum,
10111 InputInfo.BasePointersArray.getPointer(),
10112 InputInfo.PointersArray.getPointer(),
10113 InputInfo.SizesArray.getPointer(),
10114 MapTypesArray};
Samuel Antao8d2d7302016-05-26 18:30:22 +000010115
Samuel Antao8d2d7302016-05-26 18:30:22 +000010116 // Select the right runtime function call for each expected standalone
10117 // directive.
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010118 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Samuel Antao8d2d7302016-05-26 18:30:22 +000010119 OpenMPRTLFunction RTLFn;
10120 switch (D.getDirectiveKind()) {
Samuel Antao8d2d7302016-05-26 18:30:22 +000010121 case OMPD_target_enter_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010122 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait
10123 : OMPRTL__tgt_target_data_begin;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010124 break;
10125 case OMPD_target_exit_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010126 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait
10127 : OMPRTL__tgt_target_data_end;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010128 break;
10129 case OMPD_target_update:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010130 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait
10131 : OMPRTL__tgt_target_data_update;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010132 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010133 case OMPD_parallel:
10134 case OMPD_for:
10135 case OMPD_parallel_for:
10136 case OMPD_parallel_sections:
10137 case OMPD_for_simd:
10138 case OMPD_parallel_for_simd:
10139 case OMPD_cancel:
10140 case OMPD_cancellation_point:
10141 case OMPD_ordered:
10142 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +000010143 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010144 case OMPD_task:
10145 case OMPD_simd:
10146 case OMPD_sections:
10147 case OMPD_section:
10148 case OMPD_single:
10149 case OMPD_master:
10150 case OMPD_critical:
10151 case OMPD_taskyield:
10152 case OMPD_barrier:
10153 case OMPD_taskwait:
10154 case OMPD_taskgroup:
10155 case OMPD_atomic:
10156 case OMPD_flush:
10157 case OMPD_teams:
10158 case OMPD_target_data:
10159 case OMPD_distribute:
10160 case OMPD_distribute_simd:
10161 case OMPD_distribute_parallel_for:
10162 case OMPD_distribute_parallel_for_simd:
10163 case OMPD_teams_distribute:
10164 case OMPD_teams_distribute_simd:
10165 case OMPD_teams_distribute_parallel_for:
10166 case OMPD_teams_distribute_parallel_for_simd:
10167 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +000010168 case OMPD_declare_variant:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010169 case OMPD_declare_target:
10170 case OMPD_end_declare_target:
10171 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +000010172 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010173 case OMPD_taskloop:
10174 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +000010175 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +000010176 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +000010177 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -040010178 case OMPD_parallel_master_taskloop_simd:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010179 case OMPD_target:
10180 case OMPD_target_simd:
10181 case OMPD_target_teams_distribute:
10182 case OMPD_target_teams_distribute_simd:
10183 case OMPD_target_teams_distribute_parallel_for:
10184 case OMPD_target_teams_distribute_parallel_for_simd:
10185 case OMPD_target_teams:
10186 case OMPD_target_parallel:
10187 case OMPD_target_parallel_for:
10188 case OMPD_target_parallel_for_simd:
Kelvin Li1408f912018-09-26 04:28:39 +000010189 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010190 case OMPD_unknown:
10191 llvm_unreachable("Unexpected standalone target data directive.");
10192 break;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010193 }
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010194 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010195 };
10196
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010197 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray](
10198 CodeGenFunction &CGF, PrePostActionTy &) {
10199 // Fill up the arrays with all the mapped variables.
10200 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
10201 MappableExprsHandler::MapValuesArrayTy Pointers;
10202 MappableExprsHandler::MapValuesArrayTy Sizes;
10203 MappableExprsHandler::MapFlagsArrayTy MapTypes;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010204
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010205 // Get map clause information.
10206 MappableExprsHandler MEHandler(D, CGF);
10207 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
10208
10209 TargetDataInfo Info;
10210 // Fill up the arrays and create the arguments.
10211 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
10212 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
10213 Info.PointersArray, Info.SizesArray,
10214 Info.MapTypesArray, Info);
10215 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
10216 InputInfo.BasePointersArray =
10217 Address(Info.BasePointersArray, CGM.getPointerAlign());
10218 InputInfo.PointersArray =
10219 Address(Info.PointersArray, CGM.getPointerAlign());
10220 InputInfo.SizesArray =
10221 Address(Info.SizesArray, CGM.getPointerAlign());
10222 MapTypesArray = Info.MapTypesArray;
10223 if (D.hasClausesOfKind<OMPDependClause>())
10224 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
10225 else
Alexey Bataev768f1f22018-01-09 19:59:25 +000010226 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010227 };
10228
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010229 if (IfCond) {
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010230 emitOMPIfClause(CGF, IfCond, TargetThenGen,
10231 [](CodeGenFunction &CGF, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010232 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010233 RegionCodeGenTy ThenRCG(TargetThenGen);
10234 ThenRCG(CGF);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010235 }
10236}
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010237
10238namespace {
10239 /// Kind of parameter in a function with 'declare simd' directive.
10240 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector };
10241 /// Attribute set of the parameter.
10242 struct ParamAttrTy {
10243 ParamKindTy Kind = Vector;
10244 llvm::APSInt StrideOrArg;
10245 llvm::APSInt Alignment;
10246 };
10247} // namespace
10248
10249static unsigned evaluateCDTSize(const FunctionDecl *FD,
10250 ArrayRef<ParamAttrTy> ParamAttrs) {
10251 // Every vector variant of a SIMD-enabled function has a vector length (VLEN).
10252 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument
10253 // of that clause. The VLEN value must be power of 2.
10254 // In other case the notion of the function`s "characteristic data type" (CDT)
10255 // is used to compute the vector length.
10256 // CDT is defined in the following order:
10257 // a) For non-void function, the CDT is the return type.
10258 // b) If the function has any non-uniform, non-linear parameters, then the
10259 // CDT is the type of the first such parameter.
10260 // c) If the CDT determined by a) or b) above is struct, union, or class
10261 // type which is pass-by-value (except for the type that maps to the
10262 // built-in complex data type), the characteristic data type is int.
10263 // d) If none of the above three cases is applicable, the CDT is int.
10264 // The VLEN is then determined based on the CDT and the size of vector
10265 // register of that ISA for which current vector version is generated. The
10266 // VLEN is computed using the formula below:
10267 // VLEN = sizeof(vector_register) / sizeof(CDT),
10268 // where vector register size specified in section 3.2.1 Registers and the
10269 // Stack Frame of original AMD64 ABI document.
10270 QualType RetType = FD->getReturnType();
10271 if (RetType.isNull())
10272 return 0;
10273 ASTContext &C = FD->getASTContext();
10274 QualType CDT;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010275 if (!RetType.isNull() && !RetType->isVoidType()) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010276 CDT = RetType;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010277 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010278 unsigned Offset = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010279 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010280 if (ParamAttrs[Offset].Kind == Vector)
10281 CDT = C.getPointerType(C.getRecordType(MD->getParent()));
10282 ++Offset;
10283 }
10284 if (CDT.isNull()) {
10285 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10286 if (ParamAttrs[I + Offset].Kind == Vector) {
10287 CDT = FD->getParamDecl(I)->getType();
10288 break;
10289 }
10290 }
10291 }
10292 }
10293 if (CDT.isNull())
10294 CDT = C.IntTy;
10295 CDT = CDT->getCanonicalTypeUnqualified();
10296 if (CDT->isRecordType() || CDT->isUnionType())
10297 CDT = C.IntTy;
10298 return C.getTypeSize(CDT);
10299}
10300
10301static void
10302emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
Benjamin Kramer81cb4b72016-11-24 16:01:20 +000010303 const llvm::APSInt &VLENVal,
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010304 ArrayRef<ParamAttrTy> ParamAttrs,
10305 OMPDeclareSimdDeclAttr::BranchStateTy State) {
10306 struct ISADataTy {
10307 char ISA;
10308 unsigned VecRegSize;
10309 };
10310 ISADataTy ISAData[] = {
10311 {
10312 'b', 128
10313 }, // SSE
10314 {
10315 'c', 256
10316 }, // AVX
10317 {
10318 'd', 256
10319 }, // AVX2
10320 {
10321 'e', 512
10322 }, // AVX512
10323 };
10324 llvm::SmallVector<char, 2> Masked;
10325 switch (State) {
10326 case OMPDeclareSimdDeclAttr::BS_Undefined:
10327 Masked.push_back('N');
10328 Masked.push_back('M');
10329 break;
10330 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10331 Masked.push_back('N');
10332 break;
10333 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10334 Masked.push_back('M');
10335 break;
10336 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010337 for (char Mask : Masked) {
10338 for (const ISADataTy &Data : ISAData) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010339 SmallString<256> Buffer;
10340 llvm::raw_svector_ostream Out(Buffer);
10341 Out << "_ZGV" << Data.ISA << Mask;
10342 if (!VLENVal) {
Simon Pilgrim823a99c2019-05-22 13:02:19 +000010343 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs);
10344 assert(NumElts && "Non-zero simdlen/cdtsize expected");
10345 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010346 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010347 Out << VLENVal;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010348 }
10349 for (const ParamAttrTy &ParamAttr : ParamAttrs) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010350 switch (ParamAttr.Kind){
10351 case LinearWithVarStride:
10352 Out << 's' << ParamAttr.StrideOrArg;
10353 break;
10354 case Linear:
10355 Out << 'l';
10356 if (!!ParamAttr.StrideOrArg)
10357 Out << ParamAttr.StrideOrArg;
10358 break;
10359 case Uniform:
10360 Out << 'u';
10361 break;
10362 case Vector:
10363 Out << 'v';
10364 break;
10365 }
10366 if (!!ParamAttr.Alignment)
10367 Out << 'a' << ParamAttr.Alignment;
10368 }
10369 Out << '_' << Fn->getName();
10370 Fn->addFnAttr(Out.str());
10371 }
10372 }
10373}
10374
Alexey Bataeva0a22642019-04-16 13:56:21 +000010375// This are the Functions that are needed to mangle the name of the
10376// vector functions generated by the compiler, according to the rules
10377// defined in the "Vector Function ABI specifications for AArch64",
10378// available at
10379// https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi.
10380
10381/// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI.
10382///
10383/// TODO: Need to implement the behavior for reference marked with a
10384/// var or no linear modifiers (1.b in the section). For this, we
10385/// need to extend ParamKindTy to support the linear modifiers.
10386static bool getAArch64MTV(QualType QT, ParamKindTy Kind) {
10387 QT = QT.getCanonicalType();
10388
10389 if (QT->isVoidType())
10390 return false;
10391
10392 if (Kind == ParamKindTy::Uniform)
10393 return false;
10394
10395 if (Kind == ParamKindTy::Linear)
10396 return false;
10397
10398 // TODO: Handle linear references with modifiers
10399
10400 if (Kind == ParamKindTy::LinearWithVarStride)
10401 return false;
10402
10403 return true;
10404}
10405
10406/// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
10407static bool getAArch64PBV(QualType QT, ASTContext &C) {
10408 QT = QT.getCanonicalType();
10409 unsigned Size = C.getTypeSize(QT);
10410
10411 // Only scalars and complex within 16 bytes wide set PVB to true.
10412 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
10413 return false;
10414
10415 if (QT->isFloatingType())
10416 return true;
10417
10418 if (QT->isIntegerType())
10419 return true;
10420
10421 if (QT->isPointerType())
10422 return true;
10423
10424 // TODO: Add support for complex types (section 3.1.2, item 2).
10425
10426 return false;
10427}
10428
10429/// Computes the lane size (LS) of a return type or of an input parameter,
10430/// as defined by `LS(P)` in 3.2.1 of the AAVFABI.
10431/// TODO: Add support for references, section 3.2.1, item 1.
10432static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) {
10433 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) {
10434 QualType PTy = QT.getCanonicalType()->getPointeeType();
10435 if (getAArch64PBV(PTy, C))
10436 return C.getTypeSize(PTy);
10437 }
10438 if (getAArch64PBV(QT, C))
10439 return C.getTypeSize(QT);
10440
10441 return C.getTypeSize(C.getUIntPtrType());
10442}
10443
10444// Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the
10445// signature of the scalar function, as defined in 3.2.2 of the
10446// AAVFABI.
10447static std::tuple<unsigned, unsigned, bool>
10448getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) {
10449 QualType RetType = FD->getReturnType().getCanonicalType();
10450
10451 ASTContext &C = FD->getASTContext();
10452
10453 bool OutputBecomesInput = false;
10454
10455 llvm::SmallVector<unsigned, 8> Sizes;
10456 if (!RetType->isVoidType()) {
10457 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C));
10458 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {}))
10459 OutputBecomesInput = true;
10460 }
10461 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10462 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType();
10463 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C));
10464 }
10465
10466 assert(!Sizes.empty() && "Unable to determine NDS and WDS.");
10467 // The LS of a function parameter / return value can only be a power
10468 // of 2, starting from 8 bits, up to 128.
10469 assert(std::all_of(Sizes.begin(), Sizes.end(),
10470 [](unsigned Size) {
10471 return Size == 8 || Size == 16 || Size == 32 ||
10472 Size == 64 || Size == 128;
10473 }) &&
10474 "Invalid size");
10475
10476 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)),
10477 *std::max_element(std::begin(Sizes), std::end(Sizes)),
10478 OutputBecomesInput);
10479}
10480
10481/// Mangle the parameter part of the vector function name according to
10482/// their OpenMP classification. The mangling function is defined in
10483/// section 3.5 of the AAVFABI.
10484static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) {
10485 SmallString<256> Buffer;
10486 llvm::raw_svector_ostream Out(Buffer);
10487 for (const auto &ParamAttr : ParamAttrs) {
10488 switch (ParamAttr.Kind) {
10489 case LinearWithVarStride:
10490 Out << "ls" << ParamAttr.StrideOrArg;
10491 break;
10492 case Linear:
10493 Out << 'l';
10494 // Don't print the step value if it is not present or if it is
10495 // equal to 1.
10496 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1)
10497 Out << ParamAttr.StrideOrArg;
10498 break;
10499 case Uniform:
10500 Out << 'u';
10501 break;
10502 case Vector:
10503 Out << 'v';
10504 break;
10505 }
10506
10507 if (!!ParamAttr.Alignment)
10508 Out << 'a' << ParamAttr.Alignment;
10509 }
10510
10511 return Out.str();
10512}
10513
10514// Function used to add the attribute. The parameter `VLEN` is
10515// templated to allow the use of "x" when targeting scalable functions
10516// for SVE.
10517template <typename T>
10518static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix,
10519 char ISA, StringRef ParSeq,
10520 StringRef MangledName, bool OutputBecomesInput,
10521 llvm::Function *Fn) {
10522 SmallString<256> Buffer;
10523 llvm::raw_svector_ostream Out(Buffer);
10524 Out << Prefix << ISA << LMask << VLEN;
10525 if (OutputBecomesInput)
10526 Out << "v";
10527 Out << ParSeq << "_" << MangledName;
10528 Fn->addFnAttr(Out.str());
10529}
10530
10531// Helper function to generate the Advanced SIMD names depending on
10532// the value of the NDS when simdlen is not present.
10533static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask,
10534 StringRef Prefix, char ISA,
10535 StringRef ParSeq, StringRef MangledName,
10536 bool OutputBecomesInput,
10537 llvm::Function *Fn) {
10538 switch (NDS) {
10539 case 8:
10540 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10541 OutputBecomesInput, Fn);
10542 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName,
10543 OutputBecomesInput, Fn);
10544 break;
10545 case 16:
10546 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10547 OutputBecomesInput, Fn);
10548 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10549 OutputBecomesInput, Fn);
10550 break;
10551 case 32:
10552 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10553 OutputBecomesInput, Fn);
10554 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10555 OutputBecomesInput, Fn);
10556 break;
10557 case 64:
10558 case 128:
10559 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10560 OutputBecomesInput, Fn);
10561 break;
10562 default:
10563 llvm_unreachable("Scalar type is too wide.");
10564 }
10565}
10566
10567/// Emit vector function attributes for AArch64, as defined in the AAVFABI.
10568static void emitAArch64DeclareSimdFunction(
10569 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN,
10570 ArrayRef<ParamAttrTy> ParamAttrs,
10571 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
10572 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) {
10573
10574 // Get basic data for building the vector signature.
10575 const auto Data = getNDSWDS(FD, ParamAttrs);
10576 const unsigned NDS = std::get<0>(Data);
10577 const unsigned WDS = std::get<1>(Data);
10578 const bool OutputBecomesInput = std::get<2>(Data);
10579
10580 // Check the values provided via `simdlen` by the user.
10581 // 1. A `simdlen(1)` doesn't produce vector signatures,
10582 if (UserVLEN == 1) {
10583 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10584 DiagnosticsEngine::Warning,
10585 "The clause simdlen(1) has no effect when targeting aarch64.");
10586 CGM.getDiags().Report(SLoc, DiagID);
10587 return;
10588 }
10589
10590 // 2. Section 3.3.1, item 1: user input must be a power of 2 for
10591 // Advanced SIMD output.
10592 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
10593 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10594 DiagnosticsEngine::Warning, "The value specified in simdlen must be a "
10595 "power of 2 when targeting Advanced SIMD.");
10596 CGM.getDiags().Report(SLoc, DiagID);
10597 return;
10598 }
10599
10600 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural
10601 // limits.
10602 if (ISA == 's' && UserVLEN != 0) {
10603 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
10604 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10605 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit "
10606 "lanes in the architectural constraints "
10607 "for SVE (min is 128-bit, max is "
10608 "2048-bit, by steps of 128-bit)");
10609 CGM.getDiags().Report(SLoc, DiagID) << WDS;
10610 return;
10611 }
10612 }
10613
10614 // Sort out parameter sequence.
10615 const std::string ParSeq = mangleVectorParameters(ParamAttrs);
10616 StringRef Prefix = "_ZGV";
10617 // Generate simdlen from user input (if any).
10618 if (UserVLEN) {
10619 if (ISA == 's') {
10620 // SVE generates only a masked function.
10621 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10622 OutputBecomesInput, Fn);
10623 } else {
10624 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10625 // Advanced SIMD generates one or two functions, depending on
10626 // the `[not]inbranch` clause.
10627 switch (State) {
10628 case OMPDeclareSimdDeclAttr::BS_Undefined:
10629 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10630 OutputBecomesInput, Fn);
10631 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10632 OutputBecomesInput, Fn);
10633 break;
10634 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10635 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10636 OutputBecomesInput, Fn);
10637 break;
10638 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10639 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10640 OutputBecomesInput, Fn);
10641 break;
10642 }
10643 }
10644 } else {
10645 // If no user simdlen is provided, follow the AAVFABI rules for
10646 // generating the vector length.
10647 if (ISA == 's') {
10648 // SVE, section 3.4.1, item 1.
10649 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName,
10650 OutputBecomesInput, Fn);
10651 } else {
10652 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10653 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or
10654 // two vector names depending on the use of the clause
10655 // `[not]inbranch`.
10656 switch (State) {
10657 case OMPDeclareSimdDeclAttr::BS_Undefined:
10658 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10659 OutputBecomesInput, Fn);
10660 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10661 OutputBecomesInput, Fn);
10662 break;
10663 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10664 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10665 OutputBecomesInput, Fn);
10666 break;
10667 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10668 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10669 OutputBecomesInput, Fn);
10670 break;
10671 }
10672 }
10673 }
10674}
10675
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010676void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
10677 llvm::Function *Fn) {
10678 ASTContext &C = CGM.getContext();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010679 FD = FD->getMostRecentDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010680 // Map params to their positions in function decl.
10681 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
10682 if (isa<CXXMethodDecl>(FD))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010683 ParamPositions.try_emplace(FD, 0);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010684 unsigned ParamPos = ParamPositions.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010685 for (const ParmVarDecl *P : FD->parameters()) {
10686 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010687 ++ParamPos;
10688 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010689 while (FD) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010690 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010691 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
10692 // Mark uniform parameters.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010693 for (const Expr *E : Attr->uniforms()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010694 E = E->IgnoreParenImpCasts();
10695 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010696 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010697 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010698 } else {
10699 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10700 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010701 Pos = ParamPositions[PVD];
10702 }
10703 ParamAttrs[Pos].Kind = Uniform;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010704 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010705 // Get alignment info.
10706 auto NI = Attr->alignments_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010707 for (const Expr *E : Attr->aligneds()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010708 E = E->IgnoreParenImpCasts();
10709 unsigned Pos;
10710 QualType ParmTy;
10711 if (isa<CXXThisExpr>(E)) {
10712 Pos = ParamPositions[FD];
10713 ParmTy = E->getType();
10714 } else {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010715 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10716 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010717 Pos = ParamPositions[PVD];
10718 ParmTy = PVD->getType();
10719 }
10720 ParamAttrs[Pos].Alignment =
10721 (*NI)
10722 ? (*NI)->EvaluateKnownConstInt(C)
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010723 : llvm::APSInt::getUnsigned(
10724 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy))
10725 .getQuantity());
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010726 ++NI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010727 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010728 // Mark linear parameters.
10729 auto SI = Attr->steps_begin();
10730 auto MI = Attr->modifiers_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010731 for (const Expr *E : Attr->linears()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010732 E = E->IgnoreParenImpCasts();
10733 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010734 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010735 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010736 } else {
10737 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10738 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010739 Pos = ParamPositions[PVD];
10740 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010741 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010742 ParamAttr.Kind = Linear;
10743 if (*SI) {
Fangrui Song407659a2018-11-30 23:41:18 +000010744 Expr::EvalResult Result;
10745 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010746 if (const auto *DRE =
10747 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
10748 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010749 ParamAttr.Kind = LinearWithVarStride;
10750 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(
10751 ParamPositions[StridePVD->getCanonicalDecl()]);
10752 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010753 }
Fangrui Song407659a2018-11-30 23:41:18 +000010754 } else {
10755 ParamAttr.StrideOrArg = Result.Val.getInt();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010756 }
10757 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010758 ++SI;
10759 ++MI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010760 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010761 llvm::APSInt VLENVal;
Alexey Bataeva0a22642019-04-16 13:56:21 +000010762 SourceLocation ExprLoc;
10763 const Expr *VLENExpr = Attr->getSimdlen();
10764 if (VLENExpr) {
10765 VLENVal = VLENExpr->EvaluateKnownConstInt(C);
10766 ExprLoc = VLENExpr->getExprLoc();
10767 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010768 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
10769 if (CGM.getTriple().getArch() == llvm::Triple::x86 ||
Alexey Bataeva0a22642019-04-16 13:56:21 +000010770 CGM.getTriple().getArch() == llvm::Triple::x86_64) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010771 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
Alexey Bataeva0a22642019-04-16 13:56:21 +000010772 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) {
10773 unsigned VLEN = VLENVal.getExtValue();
10774 StringRef MangledName = Fn->getName();
10775 if (CGM.getTarget().hasFeature("sve"))
10776 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10777 MangledName, 's', 128, Fn, ExprLoc);
10778 if (CGM.getTarget().hasFeature("neon"))
10779 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10780 MangledName, 'n', 128, Fn, ExprLoc);
10781 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010782 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010783 FD = FD->getPreviousDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010784 }
10785}
Alexey Bataev8b427062016-05-25 12:36:08 +000010786
10787namespace {
10788/// Cleanup action for doacross support.
10789class DoacrossCleanupTy final : public EHScopeStack::Cleanup {
10790public:
10791 static const int DoacrossFinArgs = 2;
10792
10793private:
James Y Knight9871db02019-02-05 16:42:33 +000010794 llvm::FunctionCallee RTLFn;
Alexey Bataev8b427062016-05-25 12:36:08 +000010795 llvm::Value *Args[DoacrossFinArgs];
10796
10797public:
James Y Knight9871db02019-02-05 16:42:33 +000010798 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
10799 ArrayRef<llvm::Value *> CallArgs)
Alexey Bataev8b427062016-05-25 12:36:08 +000010800 : RTLFn(RTLFn) {
10801 assert(CallArgs.size() == DoacrossFinArgs);
10802 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10803 }
10804 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10805 if (!CGF.HaveInsertPoint())
10806 return;
10807 CGF.EmitRuntimeCall(RTLFn, Args);
10808 }
10809};
10810} // namespace
10811
10812void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000010813 const OMPLoopDirective &D,
10814 ArrayRef<Expr *> NumIterations) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010815 if (!CGF.HaveInsertPoint())
10816 return;
10817
10818 ASTContext &C = CGM.getContext();
10819 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
10820 RecordDecl *RD;
10821 if (KmpDimTy.isNull()) {
10822 // Build struct kmp_dim { // loop bounds info casted to kmp_int64
10823 // kmp_int64 lo; // lower
10824 // kmp_int64 up; // upper
10825 // kmp_int64 st; // stride
10826 // };
10827 RD = C.buildImplicitRecord("kmp_dim");
10828 RD->startDefinition();
10829 addFieldToRecordDecl(C, RD, Int64Ty);
10830 addFieldToRecordDecl(C, RD, Int64Ty);
10831 addFieldToRecordDecl(C, RD, Int64Ty);
10832 RD->completeDefinition();
10833 KmpDimTy = C.getRecordType(RD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010834 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010835 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010836 }
Alexey Bataevf138fda2018-08-13 19:04:24 +000010837 llvm::APInt Size(/*numBits=*/32, NumIterations.size());
10838 QualType ArrayTy =
Richard Smith772e2662019-10-04 01:25:59 +000010839 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0);
Alexey Bataev8b427062016-05-25 12:36:08 +000010840
Alexey Bataevf138fda2018-08-13 19:04:24 +000010841 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
10842 CGF.EmitNullInitialization(DimsAddr, ArrayTy);
Alexey Bataev8b427062016-05-25 12:36:08 +000010843 enum { LowerFD = 0, UpperFD, StrideFD };
10844 // Fill dims with data.
Alexey Bataevf138fda2018-08-13 19:04:24 +000010845 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +000010846 LValue DimsLVal = CGF.MakeAddrLValue(
10847 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010848 // dims.upper = num_iterations;
10849 LValue UpperLVal = CGF.EmitLValueForField(
10850 DimsLVal, *std::next(RD->field_begin(), UpperFD));
10851 llvm::Value *NumIterVal =
10852 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]),
10853 D.getNumIterations()->getType(), Int64Ty,
10854 D.getNumIterations()->getExprLoc());
10855 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
10856 // dims.stride = 1;
10857 LValue StrideLVal = CGF.EmitLValueForField(
10858 DimsLVal, *std::next(RD->field_begin(), StrideFD));
10859 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
10860 StrideLVal);
10861 }
Alexey Bataev8b427062016-05-25 12:36:08 +000010862
10863 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
10864 // kmp_int32 num_dims, struct kmp_dim * dims);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010865 llvm::Value *Args[] = {
10866 emitUpdateLocation(CGF, D.getBeginLoc()),
10867 getThreadID(CGF, D.getBeginLoc()),
10868 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()),
10869 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knight751fe282019-02-09 22:22:28 +000010870 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(),
Alexey Bataevf138fda2018-08-13 19:04:24 +000010871 CGM.VoidPtrTy)};
Alexey Bataev8b427062016-05-25 12:36:08 +000010872
James Y Knight9871db02019-02-05 16:42:33 +000010873 llvm::FunctionCallee RTLFn =
10874 createRuntimeFunction(OMPRTL__kmpc_doacross_init);
Alexey Bataev8b427062016-05-25 12:36:08 +000010875 CGF.EmitRuntimeCall(RTLFn, Args);
10876 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
Stephen Kelly1c301dc2018-08-09 21:09:38 +000010877 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())};
James Y Knight9871db02019-02-05 16:42:33 +000010878 llvm::FunctionCallee FiniRTLFn =
10879 createRuntimeFunction(OMPRTL__kmpc_doacross_fini);
Alexey Bataev8b427062016-05-25 12:36:08 +000010880 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
10881 llvm::makeArrayRef(FiniArgs));
10882}
10883
10884void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
10885 const OMPDependClause *C) {
10886 QualType Int64Ty =
10887 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010888 llvm::APInt Size(/*numBits=*/32, C->getNumLoops());
10889 QualType ArrayTy = CGM.getContext().getConstantArrayType(
Richard Smith772e2662019-10-04 01:25:59 +000010890 Int64Ty, Size, nullptr, ArrayType::Normal, 0);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010891 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr");
10892 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) {
10893 const Expr *CounterVal = C->getLoopData(I);
10894 assert(CounterVal);
10895 llvm::Value *CntVal = CGF.EmitScalarConversion(
10896 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
10897 CounterVal->getExprLoc());
James Y Knight751fe282019-02-09 22:22:28 +000010898 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I),
10899 /*Volatile=*/false, Int64Ty);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010900 }
10901 llvm::Value *Args[] = {
10902 emitUpdateLocation(CGF, C->getBeginLoc()),
10903 getThreadID(CGF, C->getBeginLoc()),
James Y Knight751fe282019-02-09 22:22:28 +000010904 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()};
James Y Knight9871db02019-02-05 16:42:33 +000010905 llvm::FunctionCallee RTLFn;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010906 if (C->getDependencyKind() == OMPC_DEPEND_source) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010907 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010908 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010909 assert(C->getDependencyKind() == OMPC_DEPEND_sink);
10910 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait);
10911 }
10912 CGF.EmitRuntimeCall(RTLFn, Args);
10913}
10914
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010915void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000010916 llvm::FunctionCallee Callee,
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010917 ArrayRef<llvm::Value *> Args) const {
10918 assert(Loc.isValid() && "Outlined function call location must be valid.");
Alexey Bataev3c595a62017-08-14 15:01:03 +000010919 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
10920
James Y Knight9871db02019-02-05 16:42:33 +000010921 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010922 if (Fn->doesNotThrow()) {
Alexey Bataev3c595a62017-08-14 15:01:03 +000010923 CGF.EmitNounwindRuntimeCall(Fn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010924 return;
10925 }
10926 }
Alexey Bataev3c595a62017-08-14 15:01:03 +000010927 CGF.EmitRuntimeCall(Callee, Args);
10928}
10929
10930void CGOpenMPRuntime::emitOutlinedFunctionCall(
James Y Knight9871db02019-02-05 16:42:33 +000010931 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn,
Alexey Bataev3c595a62017-08-14 15:01:03 +000010932 ArrayRef<llvm::Value *> Args) const {
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010933 emitCall(CGF, Loc, OutlinedFn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010934}
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010935
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +000010936void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) {
10937 if (const auto *FD = dyn_cast<FunctionDecl>(D))
10938 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
10939 HasEmittedDeclareTargetRegion = true;
10940}
10941
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010942Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
10943 const VarDecl *NativeParam,
10944 const VarDecl *TargetParam) const {
10945 return CGF.GetAddrOfLocalVar(NativeParam);
10946}
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010947
Alexey Bataev4f680db2019-03-19 16:41:16 +000010948namespace {
10949/// Cleanup action for allocate support.
10950class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup {
10951public:
10952 static const int CleanupArgs = 3;
10953
10954private:
10955 llvm::FunctionCallee RTLFn;
10956 llvm::Value *Args[CleanupArgs];
10957
10958public:
10959 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
10960 ArrayRef<llvm::Value *> CallArgs)
10961 : RTLFn(RTLFn) {
10962 assert(CallArgs.size() == CleanupArgs &&
10963 "Size of arguments does not match.");
10964 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10965 }
10966 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10967 if (!CGF.HaveInsertPoint())
10968 return;
10969 CGF.EmitRuntimeCall(RTLFn, Args);
10970 }
10971};
10972} // namespace
10973
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000010974Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF,
10975 const VarDecl *VD) {
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010976 if (!VD)
10977 return Address::invalid();
Alexey Bataev4f680db2019-03-19 16:41:16 +000010978 const VarDecl *CVD = VD->getCanonicalDecl();
10979 if (!CVD->hasAttr<OMPAllocateDeclAttr>())
10980 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010981 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
10982 // Use the default allocation.
Alexey Bataev0fd3c682019-04-02 19:44:46 +000010983 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
10984 !AA->getAllocator())
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010985 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010986 llvm::Value *Size;
10987 CharUnits Align = CGM.getContext().getDeclAlign(CVD);
10988 if (CVD->getType()->isVariablyModifiedType()) {
10989 Size = CGF.getTypeSize(CVD->getType());
Alexey Bataev9c397812019-04-03 17:57:06 +000010990 // Align the size: ((size + align - 1) / align) * align
10991 Size = CGF.Builder.CreateNUWAdd(
10992 Size, CGM.getSize(Align - CharUnits::fromQuantity(1)));
10993 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align));
10994 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align));
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010995 } else {
10996 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType());
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010997 Size = CGM.getSize(Sz.alignTo(Align));
Alexey Bataev4f680db2019-03-19 16:41:16 +000010998 }
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010999 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc());
11000 assert(AA->getAllocator() &&
11001 "Expected allocator expression for non-default allocator.");
11002 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator());
Alexey Bataev6cf7b712019-04-08 19:06:42 +000011003 // According to the standard, the original allocator type is a enum (integer).
11004 // Convert to pointer type, if required.
11005 if (Allocator->getType()->isIntegerTy())
11006 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy);
11007 else if (Allocator->getType()->isPointerTy())
11008 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator,
11009 CGM.VoidPtrTy);
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011010 llvm::Value *Args[] = {ThreadID, Size, Allocator};
11011
11012 llvm::Value *Addr =
11013 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args,
11014 CVD->getName() + ".void.addr");
11015 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr,
11016 Allocator};
11017 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free);
11018
11019 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
11020 llvm::makeArrayRef(FiniArgs));
11021 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11022 Addr,
11023 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())),
11024 CVD->getName() + ".addr");
11025 return Address(Addr, Align);
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000011026}
11027
Alexey Bataevfde11e92019-11-07 11:03:10 -050011028namespace {
11029using OMPContextSelectorData =
11030 OpenMPCtxSelectorData<StringRef, ArrayRef<StringRef>, llvm::APSInt>;
11031using CompleteOMPContextSelectorData = SmallVector<OMPContextSelectorData, 4>;
11032} // anonymous namespace
11033
Alexey Bataev2df5f122019-10-01 20:18:32 +000011034/// Checks current context and returns true if it matches the context selector.
Alexey Bataevfde11e92019-11-07 11:03:10 -050011035template <OpenMPContextSelectorSetKind CtxSet, OpenMPContextSelectorKind Ctx>
11036static bool checkContext(const OMPContextSelectorData &Data) {
11037 assert(Data.CtxSet != OMP_CTX_SET_unknown && Data.Ctx != OMP_CTX_unknown &&
Alexey Bataev2df5f122019-10-01 20:18:32 +000011038 "Unknown context selector or context selector set.");
11039 return false;
11040}
11041
11042/// Checks for implementation={vendor(<vendor>)} context selector.
11043/// \returns true iff <vendor>="llvm", false otherwise.
11044template <>
Alexey Bataevfde11e92019-11-07 11:03:10 -050011045bool checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(
11046 const OMPContextSelectorData &Data) {
11047 return llvm::all_of(Data.Names,
Alexey Bataev303657a2019-10-08 19:44:16 +000011048 [](StringRef S) { return !S.compare_lower("llvm"); });
Alexey Bataev2df5f122019-10-01 20:18:32 +000011049}
11050
Alexey Bataevfde11e92019-11-07 11:03:10 -050011051bool matchesContext(const CompleteOMPContextSelectorData &ContextData) {
11052 for (const OMPContextSelectorData &Data : ContextData) {
11053 switch (Data.CtxSet) {
11054 case OMP_CTX_SET_implementation:
11055 switch (Data.Ctx) {
11056 case OMP_CTX_vendor:
11057 if (!checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(Data))
11058 return false;
11059 break;
11060 case OMP_CTX_unknown:
11061 llvm_unreachable("Unexpected context selector kind.");
11062 }
11063 break;
11064 case OMP_CTX_SET_unknown:
11065 llvm_unreachable("Unexpected context selector set kind.");
11066 }
11067 }
11068 return true;
11069}
11070
11071static CompleteOMPContextSelectorData
11072translateAttrToContextSelectorData(ASTContext &C,
11073 const OMPDeclareVariantAttr *A) {
11074 CompleteOMPContextSelectorData Data;
11075 for (unsigned I = 0, E = A->scores_size(); I < E; ++I) {
11076 Data.emplace_back();
11077 auto CtxSet = static_cast<OpenMPContextSelectorSetKind>(
11078 *std::next(A->ctxSelectorSets_begin(), I));
11079 auto Ctx = static_cast<OpenMPContextSelectorKind>(
11080 *std::next(A->ctxSelectors_begin(), I));
11081 Data.back().CtxSet = CtxSet;
11082 Data.back().Ctx = Ctx;
11083 const Expr *Score = *std::next(A->scores_begin(), I);
11084 Data.back().Score = Score->EvaluateKnownConstInt(C);
11085 switch (CtxSet) {
11086 case OMP_CTX_SET_implementation:
11087 switch (Ctx) {
11088 case OMP_CTX_vendor:
11089 Data.back().Names =
11090 llvm::makeArrayRef(A->implVendors_begin(), A->implVendors_end());
11091 break;
11092 case OMP_CTX_unknown:
11093 llvm_unreachable("Unexpected context selector kind.");
11094 }
11095 break;
11096 case OMP_CTX_SET_unknown:
11097 llvm_unreachable("Unexpected context selector set kind.");
11098 }
11099 }
11100 return Data;
11101}
11102
11103static bool greaterCtxScore(const CompleteOMPContextSelectorData &LHS,
11104 const CompleteOMPContextSelectorData &RHS) {
11105 // Score is calculated as sum of all scores + 1.
11106 llvm::APSInt LHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false);
11107 for (const OMPContextSelectorData &Data : LHS) {
11108 if (Data.Score.getBitWidth() > LHSScore.getBitWidth()) {
11109 LHSScore = LHSScore.extend(Data.Score.getBitWidth()) + Data.Score;
11110 } else if (Data.Score.getBitWidth() < LHSScore.getBitWidth()) {
11111 LHSScore += Data.Score.extend(LHSScore.getBitWidth());
11112 } else {
11113 LHSScore += Data.Score;
11114 }
11115 }
11116 llvm::APSInt RHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false);
11117 for (const OMPContextSelectorData &Data : RHS) {
11118 if (Data.Score.getBitWidth() > RHSScore.getBitWidth()) {
11119 RHSScore = RHSScore.extend(Data.Score.getBitWidth()) + Data.Score;
11120 } else if (Data.Score.getBitWidth() < RHSScore.getBitWidth()) {
11121 RHSScore += Data.Score.extend(RHSScore.getBitWidth());
11122 } else {
11123 RHSScore += Data.Score;
11124 }
11125 }
11126 return llvm::APSInt::compareValues(LHSScore, RHSScore) >= 0;
Alexey Bataev0364c762019-10-03 20:49:48 +000011127}
11128
Alexey Bataev2df5f122019-10-01 20:18:32 +000011129/// Finds the variant function that matches current context with its context
11130/// selector.
Alexey Bataev0364c762019-10-03 20:49:48 +000011131static const FunctionDecl *getDeclareVariantFunction(ASTContext &Ctx,
11132 const FunctionDecl *FD) {
Alexey Bataev2df5f122019-10-01 20:18:32 +000011133 if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>())
11134 return FD;
11135 // Iterate through all DeclareVariant attributes and check context selectors.
Alexey Bataev0364c762019-10-03 20:49:48 +000011136 const OMPDeclareVariantAttr *TopMostAttr = nullptr;
Alexey Bataevfde11e92019-11-07 11:03:10 -050011137 CompleteOMPContextSelectorData TopMostData;
Alexey Bataev0364c762019-10-03 20:49:48 +000011138 for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) {
Alexey Bataevfde11e92019-11-07 11:03:10 -050011139 CompleteOMPContextSelectorData Data =
11140 translateAttrToContextSelectorData(Ctx, A);
11141 if (!matchesContext(Data))
11142 continue;
Alexey Bataev0364c762019-10-03 20:49:48 +000011143 // If the attribute matches the context, find the attribute with the highest
11144 // score.
Alexey Bataevfde11e92019-11-07 11:03:10 -050011145 if (!TopMostAttr || !greaterCtxScore(TopMostData, Data)) {
11146 TopMostAttr = A;
11147 TopMostData.swap(Data);
11148 }
Alexey Bataev2df5f122019-10-01 20:18:32 +000011149 }
Alexey Bataev0364c762019-10-03 20:49:48 +000011150 if (!TopMostAttr)
Alexey Bataev2df5f122019-10-01 20:18:32 +000011151 return FD;
Alexey Bataev2df5f122019-10-01 20:18:32 +000011152 return cast<FunctionDecl>(
Alexey Bataev0364c762019-10-03 20:49:48 +000011153 cast<DeclRefExpr>(TopMostAttr->getVariantFuncRef()->IgnoreParenImpCasts())
Alexey Bataev2df5f122019-10-01 20:18:32 +000011154 ->getDecl());
11155}
11156
11157bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) {
11158 const auto *D = cast<FunctionDecl>(GD.getDecl());
11159 // If the original function is defined already, use its definition.
11160 StringRef MangledName = CGM.getMangledName(GD);
11161 llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName);
11162 if (Orig && !Orig->isDeclaration())
11163 return false;
Alexey Bataev0364c762019-10-03 20:49:48 +000011164 const FunctionDecl *NewFD = getDeclareVariantFunction(CGM.getContext(), D);
Alexey Bataev2df5f122019-10-01 20:18:32 +000011165 // Emit original function if it does not have declare variant attribute or the
11166 // context does not match.
11167 if (NewFD == D)
11168 return false;
11169 GlobalDecl NewGD = GD.getWithDecl(NewFD);
Alexey Bataevc2cd2d42019-10-10 17:28:10 +000011170 if (tryEmitDeclareVariant(NewGD, GD, Orig, IsForDefinition)) {
Alexey Bataev2df5f122019-10-01 20:18:32 +000011171 DeferredVariantFunction.erase(D);
11172 return true;
11173 }
11174 DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD)));
11175 return true;
11176}
11177
James Y Knight9871db02019-02-05 16:42:33 +000011178llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011179 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11180 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11181 llvm_unreachable("Not supported in SIMD-only mode");
11182}
11183
James Y Knight9871db02019-02-05 16:42:33 +000011184llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011185 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11186 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11187 llvm_unreachable("Not supported in SIMD-only mode");
11188}
11189
James Y Knight9871db02019-02-05 16:42:33 +000011190llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011191 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11192 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
11193 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
11194 bool Tied, unsigned &NumberOfParts) {
11195 llvm_unreachable("Not supported in SIMD-only mode");
11196}
11197
11198void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF,
11199 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000011200 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011201 ArrayRef<llvm::Value *> CapturedVars,
11202 const Expr *IfCond) {
11203 llvm_unreachable("Not supported in SIMD-only mode");
11204}
11205
11206void CGOpenMPSIMDRuntime::emitCriticalRegion(
11207 CodeGenFunction &CGF, StringRef CriticalName,
11208 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
11209 const Expr *Hint) {
11210 llvm_unreachable("Not supported in SIMD-only mode");
11211}
11212
11213void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF,
11214 const RegionCodeGenTy &MasterOpGen,
11215 SourceLocation Loc) {
11216 llvm_unreachable("Not supported in SIMD-only mode");
11217}
11218
11219void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
11220 SourceLocation Loc) {
11221 llvm_unreachable("Not supported in SIMD-only mode");
11222}
11223
11224void CGOpenMPSIMDRuntime::emitTaskgroupRegion(
11225 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen,
11226 SourceLocation Loc) {
11227 llvm_unreachable("Not supported in SIMD-only mode");
11228}
11229
11230void CGOpenMPSIMDRuntime::emitSingleRegion(
11231 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen,
11232 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars,
11233 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs,
11234 ArrayRef<const Expr *> AssignmentOps) {
11235 llvm_unreachable("Not supported in SIMD-only mode");
11236}
11237
11238void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF,
11239 const RegionCodeGenTy &OrderedOpGen,
11240 SourceLocation Loc,
11241 bool IsThreads) {
11242 llvm_unreachable("Not supported in SIMD-only mode");
11243}
11244
11245void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF,
11246 SourceLocation Loc,
11247 OpenMPDirectiveKind Kind,
11248 bool EmitChecks,
11249 bool ForceSimpleCall) {
11250 llvm_unreachable("Not supported in SIMD-only mode");
11251}
11252
11253void CGOpenMPSIMDRuntime::emitForDispatchInit(
11254 CodeGenFunction &CGF, SourceLocation Loc,
11255 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
11256 bool Ordered, const DispatchRTInput &DispatchValues) {
11257 llvm_unreachable("Not supported in SIMD-only mode");
11258}
11259
11260void CGOpenMPSIMDRuntime::emitForStaticInit(
11261 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind,
11262 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) {
11263 llvm_unreachable("Not supported in SIMD-only mode");
11264}
11265
11266void CGOpenMPSIMDRuntime::emitDistributeStaticInit(
11267 CodeGenFunction &CGF, SourceLocation Loc,
11268 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) {
11269 llvm_unreachable("Not supported in SIMD-only mode");
11270}
11271
11272void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
11273 SourceLocation Loc,
11274 unsigned IVSize,
11275 bool IVSigned) {
11276 llvm_unreachable("Not supported in SIMD-only mode");
11277}
11278
11279void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF,
11280 SourceLocation Loc,
11281 OpenMPDirectiveKind DKind) {
11282 llvm_unreachable("Not supported in SIMD-only mode");
11283}
11284
11285llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF,
11286 SourceLocation Loc,
11287 unsigned IVSize, bool IVSigned,
11288 Address IL, Address LB,
11289 Address UB, Address ST) {
11290 llvm_unreachable("Not supported in SIMD-only mode");
11291}
11292
11293void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
11294 llvm::Value *NumThreads,
11295 SourceLocation Loc) {
11296 llvm_unreachable("Not supported in SIMD-only mode");
11297}
11298
11299void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF,
11300 OpenMPProcBindClauseKind ProcBind,
11301 SourceLocation Loc) {
11302 llvm_unreachable("Not supported in SIMD-only mode");
11303}
11304
11305Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
11306 const VarDecl *VD,
11307 Address VDAddr,
11308 SourceLocation Loc) {
11309 llvm_unreachable("Not supported in SIMD-only mode");
11310}
11311
11312llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition(
11313 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit,
11314 CodeGenFunction *CGF) {
11315 llvm_unreachable("Not supported in SIMD-only mode");
11316}
11317
11318Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate(
11319 CodeGenFunction &CGF, QualType VarType, StringRef Name) {
11320 llvm_unreachable("Not supported in SIMD-only mode");
11321}
11322
11323void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF,
11324 ArrayRef<const Expr *> Vars,
11325 SourceLocation Loc) {
11326 llvm_unreachable("Not supported in SIMD-only mode");
11327}
11328
11329void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
11330 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000011331 llvm::Function *TaskFunction,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011332 QualType SharedsTy, Address Shareds,
11333 const Expr *IfCond,
11334 const OMPTaskDataTy &Data) {
11335 llvm_unreachable("Not supported in SIMD-only mode");
11336}
11337
11338void CGOpenMPSIMDRuntime::emitTaskLoopCall(
11339 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000011340 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011341 const Expr *IfCond, const OMPTaskDataTy &Data) {
11342 llvm_unreachable("Not supported in SIMD-only mode");
11343}
11344
11345void CGOpenMPSIMDRuntime::emitReduction(
11346 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates,
11347 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
11348 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) {
11349 assert(Options.SimpleReduction && "Only simple reduction is expected.");
11350 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
11351 ReductionOps, Options);
11352}
11353
11354llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit(
11355 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
11356 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
11357 llvm_unreachable("Not supported in SIMD-only mode");
11358}
11359
11360void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
11361 SourceLocation Loc,
11362 ReductionCodeGen &RCG,
11363 unsigned N) {
11364 llvm_unreachable("Not supported in SIMD-only mode");
11365}
11366
11367Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
11368 SourceLocation Loc,
11369 llvm::Value *ReductionsPtr,
11370 LValue SharedLVal) {
11371 llvm_unreachable("Not supported in SIMD-only mode");
11372}
11373
11374void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
11375 SourceLocation Loc) {
11376 llvm_unreachable("Not supported in SIMD-only mode");
11377}
11378
11379void CGOpenMPSIMDRuntime::emitCancellationPointCall(
11380 CodeGenFunction &CGF, SourceLocation Loc,
11381 OpenMPDirectiveKind CancelRegion) {
11382 llvm_unreachable("Not supported in SIMD-only mode");
11383}
11384
11385void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF,
11386 SourceLocation Loc, const Expr *IfCond,
11387 OpenMPDirectiveKind CancelRegion) {
11388 llvm_unreachable("Not supported in SIMD-only mode");
11389}
11390
11391void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction(
11392 const OMPExecutableDirective &D, StringRef ParentName,
11393 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
11394 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
11395 llvm_unreachable("Not supported in SIMD-only mode");
11396}
11397
Alexey Bataevec7946e2019-09-23 14:06:51 +000011398void CGOpenMPSIMDRuntime::emitTargetCall(
11399 CodeGenFunction &CGF, const OMPExecutableDirective &D,
11400 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
11401 const Expr *Device,
11402 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
11403 const OMPLoopDirective &D)>
11404 SizeEmitter) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011405 llvm_unreachable("Not supported in SIMD-only mode");
11406}
11407
11408bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) {
11409 llvm_unreachable("Not supported in SIMD-only mode");
11410}
11411
11412bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
11413 llvm_unreachable("Not supported in SIMD-only mode");
11414}
11415
11416bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) {
11417 return false;
11418}
11419
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011420void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF,
11421 const OMPExecutableDirective &D,
11422 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000011423 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011424 ArrayRef<llvm::Value *> CapturedVars) {
11425 llvm_unreachable("Not supported in SIMD-only mode");
11426}
11427
11428void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
11429 const Expr *NumTeams,
11430 const Expr *ThreadLimit,
11431 SourceLocation Loc) {
11432 llvm_unreachable("Not supported in SIMD-only mode");
11433}
11434
11435void CGOpenMPSIMDRuntime::emitTargetDataCalls(
11436 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
11437 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
11438 llvm_unreachable("Not supported in SIMD-only mode");
11439}
11440
11441void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
11442 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
11443 const Expr *Device) {
11444 llvm_unreachable("Not supported in SIMD-only mode");
11445}
11446
11447void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000011448 const OMPLoopDirective &D,
11449 ArrayRef<Expr *> NumIterations) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011450 llvm_unreachable("Not supported in SIMD-only mode");
11451}
11452
11453void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
11454 const OMPDependClause *C) {
11455 llvm_unreachable("Not supported in SIMD-only mode");
11456}
11457
11458const VarDecl *
11459CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD,
11460 const VarDecl *NativeParam) const {
11461 llvm_unreachable("Not supported in SIMD-only mode");
11462}
11463
11464Address
11465CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF,
11466 const VarDecl *NativeParam,
11467 const VarDecl *TargetParam) const {
11468 llvm_unreachable("Not supported in SIMD-only mode");
11469}