blob: 514457d9e4afd7bb7b75656f07c2e60e66a67c32 [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 ||
3619 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static))
3620 Modifier = OMP_sch_modifier_nonmonotonic;
3621 }
Alexey Bataev6cff6242016-05-30 13:05:14 +00003622 return Schedule | Modifier;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003623}
3624
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003625void CGOpenMPRuntime::emitForDispatchInit(
3626 CodeGenFunction &CGF, SourceLocation Loc,
3627 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
3628 bool Ordered, const DispatchRTInput &DispatchValues) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003629 if (!CGF.HaveInsertPoint())
3630 return;
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003631 OpenMPSchedType Schedule = getRuntimeSchedule(
3632 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered);
John McCall7f416cc2015-09-08 08:05:57 +00003633 assert(Ordered ||
3634 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
Alexey Bataev6cff6242016-05-30 13:05:14 +00003635 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
3636 Schedule != OMP_sch_static_balanced_chunked));
John McCall7f416cc2015-09-08 08:05:57 +00003637 // Call __kmpc_dispatch_init(
3638 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
3639 // kmp_int[32|64] lower, kmp_int[32|64] upper,
3640 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00003641
John McCall7f416cc2015-09-08 08:05:57 +00003642 // If the Chunk was not specified in the clause - use default value 1.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003643 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk
3644 : CGF.Builder.getIntN(IVSize, 1);
John McCall7f416cc2015-09-08 08:05:57 +00003645 llvm::Value *Args[] = {
Alexey Bataev07a3b592019-08-23 19:52:05 +00003646 emitUpdateLocation(CGF, Loc),
3647 getThreadID(CGF, Loc),
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003648 CGF.Builder.getInt32(addMonoNonMonoModifier(
Alexey Bataev07a3b592019-08-23 19:52:05 +00003649 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type
3650 DispatchValues.LB, // Lower
3651 DispatchValues.UB, // Upper
3652 CGF.Builder.getIntN(IVSize, 1), // Stride
3653 Chunk // Chunk
John McCall7f416cc2015-09-08 08:05:57 +00003654 };
3655 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
3656}
3657
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003658static void emitForStaticInitCall(
3659 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
James Y Knight9871db02019-02-05 16:42:33 +00003660 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003661 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003662 const CGOpenMPRuntime::StaticRTInput &Values) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003663 if (!CGF.HaveInsertPoint())
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003664 return;
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003665
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003666 assert(!Values.Ordered);
3667 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
3668 Schedule == OMP_sch_static_balanced_chunked ||
3669 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
3670 Schedule == OMP_dist_sch_static ||
3671 Schedule == OMP_dist_sch_static_chunked);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003672
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003673 // Call __kmpc_for_static_init(
3674 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
3675 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
3676 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
3677 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
3678 llvm::Value *Chunk = Values.Chunk;
3679 if (Chunk == nullptr) {
3680 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
3681 Schedule == OMP_dist_sch_static) &&
3682 "expected static non-chunked schedule");
3683 // If the Chunk was not specified in the clause - use default value 1.
3684 Chunk = CGF.Builder.getIntN(Values.IVSize, 1);
3685 } else {
3686 assert((Schedule == OMP_sch_static_chunked ||
3687 Schedule == OMP_sch_static_balanced_chunked ||
3688 Schedule == OMP_ord_static_chunked ||
3689 Schedule == OMP_dist_sch_static_chunked) &&
3690 "expected static chunked schedule");
3691 }
3692 llvm::Value *Args[] = {
3693 UpdateLocation,
3694 ThreadId,
Alexey Bataev07a3b592019-08-23 19:52:05 +00003695 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003696 M2)), // Schedule type
3697 Values.IL.getPointer(), // &isLastIter
3698 Values.LB.getPointer(), // &LB
3699 Values.UB.getPointer(), // &UB
3700 Values.ST.getPointer(), // &Stride
3701 CGF.Builder.getIntN(Values.IVSize, 1), // Incr
3702 Chunk // Chunk
3703 };
3704 CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003705}
3706
John McCall7f416cc2015-09-08 08:05:57 +00003707void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
3708 SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003709 OpenMPDirectiveKind DKind,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003710 const OpenMPScheduleTy &ScheduleKind,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003711 const StaticRTInput &Values) {
3712 OpenMPSchedType ScheduleNum = getRuntimeSchedule(
3713 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered);
3714 assert(isOpenMPWorksharingDirective(DKind) &&
3715 "Expected loop-based or sections-based directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003716 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003717 isOpenMPLoopDirective(DKind)
3718 ? OMP_IDENT_WORK_LOOP
3719 : OMP_IDENT_WORK_SECTIONS);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003720 llvm::Value *ThreadId = getThreadID(CGF, Loc);
James Y Knight9871db02019-02-05 16:42:33 +00003721 llvm::FunctionCallee StaticInitFunction =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003722 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003723 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003724 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003725}
John McCall7f416cc2015-09-08 08:05:57 +00003726
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003727void CGOpenMPRuntime::emitDistributeStaticInit(
3728 CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003729 OpenMPDistScheduleClauseKind SchedKind,
3730 const CGOpenMPRuntime::StaticRTInput &Values) {
3731 OpenMPSchedType ScheduleNum =
3732 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003733 llvm::Value *UpdatedLocation =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003734 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003735 llvm::Value *ThreadId = getThreadID(CGF, Loc);
James Y Knight9871db02019-02-05 16:42:33 +00003736 llvm::FunctionCallee StaticInitFunction =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003737 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003738 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
3739 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003740 OMPC_SCHEDULE_MODIFIER_unknown, Values);
Alexander Musmanc6388682014-12-15 07:07:06 +00003741}
3742
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003743void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
Alexey Bataevf43f7142017-09-06 16:17:35 +00003744 SourceLocation Loc,
3745 OpenMPDirectiveKind DKind) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003746 if (!CGF.HaveInsertPoint())
3747 return;
Alexander Musmanc6388682014-12-15 07:07:06 +00003748 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataevf43f7142017-09-06 16:17:35 +00003749 llvm::Value *Args[] = {
3750 emitUpdateLocation(CGF, Loc,
3751 isOpenMPDistributeDirective(DKind)
3752 ? OMP_IDENT_WORK_DISTRIBUTE
3753 : isOpenMPLoopDirective(DKind)
3754 ? OMP_IDENT_WORK_LOOP
3755 : OMP_IDENT_WORK_SECTIONS),
3756 getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003757 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
3758 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00003759}
3760
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003761void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
3762 SourceLocation Loc,
3763 unsigned IVSize,
3764 bool IVSigned) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003765 if (!CGF.HaveInsertPoint())
3766 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003767 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00003768 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003769 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
3770}
3771
Alexander Musman92bdaab2015-03-12 13:37:50 +00003772llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
3773 SourceLocation Loc, unsigned IVSize,
John McCall7f416cc2015-09-08 08:05:57 +00003774 bool IVSigned, Address IL,
3775 Address LB, Address UB,
3776 Address ST) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00003777 // Call __kmpc_dispatch_next(
3778 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
3779 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
3780 // kmp_int[32|64] *p_stride);
3781 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00003782 emitUpdateLocation(CGF, Loc),
3783 getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00003784 IL.getPointer(), // &isLastIter
3785 LB.getPointer(), // &Lower
3786 UB.getPointer(), // &Upper
3787 ST.getPointer() // &Stride
Alexander Musman92bdaab2015-03-12 13:37:50 +00003788 };
3789 llvm::Value *Call =
3790 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
3791 return CGF.EmitScalarConversion(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003792 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00003793 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00003794}
3795
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003796void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
3797 llvm::Value *NumThreads,
3798 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003799 if (!CGF.HaveInsertPoint())
3800 return;
Alexey Bataevb2059782014-10-13 08:23:51 +00003801 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
3802 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003803 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00003804 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003805 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
3806 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00003807}
3808
Alexey Bataev7f210c62015-06-18 13:40:03 +00003809void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
3810 OpenMPProcBindClauseKind ProcBind,
3811 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003812 if (!CGF.HaveInsertPoint())
3813 return;
Alexey Bataev7f210c62015-06-18 13:40:03 +00003814 // Constants for proc bind value accepted by the runtime.
3815 enum ProcBindTy {
3816 ProcBindFalse = 0,
3817 ProcBindTrue,
3818 ProcBindMaster,
3819 ProcBindClose,
3820 ProcBindSpread,
3821 ProcBindIntel,
3822 ProcBindDefault
3823 } RuntimeProcBind;
3824 switch (ProcBind) {
3825 case OMPC_PROC_BIND_master:
3826 RuntimeProcBind = ProcBindMaster;
3827 break;
3828 case OMPC_PROC_BIND_close:
3829 RuntimeProcBind = ProcBindClose;
3830 break;
3831 case OMPC_PROC_BIND_spread:
3832 RuntimeProcBind = ProcBindSpread;
3833 break;
3834 case OMPC_PROC_BIND_unknown:
3835 llvm_unreachable("Unsupported proc_bind value.");
3836 }
3837 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
3838 llvm::Value *Args[] = {
3839 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3840 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
3841 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
3842}
3843
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003844void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
3845 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003846 if (!CGF.HaveInsertPoint())
3847 return;
Alexey Bataevd76df6d2015-02-24 12:55:09 +00003848 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003849 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
3850 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00003851}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003852
Alexey Bataev62b63b12015-03-10 07:28:44 +00003853namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003854/// Indexes of fields for type kmp_task_t.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003855enum KmpTaskTFields {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003856 /// List of shared variables.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003857 KmpTaskTShareds,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003858 /// Task routine.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003859 KmpTaskTRoutine,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003860 /// Partition id for the untied tasks.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003861 KmpTaskTPartId,
Alexey Bataevad537bb2016-05-30 09:06:50 +00003862 /// Function with call of destructors for private variables.
3863 Data1,
3864 /// Task priority.
3865 Data2,
Alexey Bataev7292c292016-04-25 12:22:29 +00003866 /// (Taskloops only) Lower bound.
3867 KmpTaskTLowerBound,
3868 /// (Taskloops only) Upper bound.
3869 KmpTaskTUpperBound,
3870 /// (Taskloops only) Stride.
3871 KmpTaskTStride,
3872 /// (Taskloops only) Is last iteration flag.
3873 KmpTaskTLastIter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003874 /// (Taskloops only) Reduction data.
3875 KmpTaskTReductions,
Alexey Bataev62b63b12015-03-10 07:28:44 +00003876};
Hans Wennborg7eb54642015-09-10 17:07:54 +00003877} // anonymous namespace
Alexey Bataev62b63b12015-03-10 07:28:44 +00003878
Samuel Antaoee8fb302016-01-06 13:42:12 +00003879bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003880 return OffloadEntriesTargetRegion.empty() &&
3881 OffloadEntriesDeviceGlobalVar.empty();
Samuel Antaoee8fb302016-01-06 13:42:12 +00003882}
3883
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003884/// Initialize target region entry.
Samuel Antaoee8fb302016-01-06 13:42:12 +00003885void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3886 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3887 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00003888 unsigned Order) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003889 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
3890 "only required for the device "
3891 "code generation.");
Samuel Antao2de62b02016-02-13 23:35:10 +00003892 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
Samuel Antaof83efdb2017-01-05 16:02:49 +00003893 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003894 OMPTargetRegionEntryTargetRegion);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003895 ++OffloadingEntriesNum;
3896}
3897
3898void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3899 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3900 StringRef ParentName, unsigned LineNum,
Samuel Antaof83efdb2017-01-05 16:02:49 +00003901 llvm::Constant *Addr, llvm::Constant *ID,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003902 OMPTargetRegionEntryKind Flags) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003903 // If we are emitting code for a target, the entry is already initialized,
3904 // only has to be registered.
3905 if (CGM.getLangOpts().OpenMPIsDevice) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00003906 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) {
3907 unsigned DiagID = CGM.getDiags().getCustomDiagID(
3908 DiagnosticsEngine::Error,
3909 "Unable to find target region on line '%0' in the device code.");
3910 CGM.getDiags().Report(DiagID) << LineNum;
3911 return;
3912 }
Samuel Antao2de62b02016-02-13 23:35:10 +00003913 auto &Entry =
3914 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
Samuel Antaoee8fb302016-01-06 13:42:12 +00003915 assert(Entry.isValid() && "Entry not initialized!");
3916 Entry.setAddress(Addr);
3917 Entry.setID(ID);
Samuel Antaof83efdb2017-01-05 16:02:49 +00003918 Entry.setFlags(Flags);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003919 } else {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003920 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags);
Samuel Antao2de62b02016-02-13 23:35:10 +00003921 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00003922 ++OffloadingEntriesNum;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003923 }
3924}
3925
3926bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00003927 unsigned DeviceID, unsigned FileID, StringRef ParentName,
3928 unsigned LineNum) const {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003929 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
3930 if (PerDevice == OffloadEntriesTargetRegion.end())
3931 return false;
3932 auto PerFile = PerDevice->second.find(FileID);
3933 if (PerFile == PerDevice->second.end())
3934 return false;
3935 auto PerParentName = PerFile->second.find(ParentName);
3936 if (PerParentName == PerFile->second.end())
3937 return false;
3938 auto PerLine = PerParentName->second.find(LineNum);
3939 if (PerLine == PerParentName->second.end())
3940 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003941 // Fail if this entry is already registered.
Samuel Antao2de62b02016-02-13 23:35:10 +00003942 if (PerLine->second.getAddress() || PerLine->second.getID())
Samuel Antaoee8fb302016-01-06 13:42:12 +00003943 return false;
3944 return true;
3945}
3946
3947void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
3948 const OffloadTargetRegionEntryInfoActTy &Action) {
3949 // Scan all target region entries and perform the provided action.
Alexey Bataev03f270c2018-03-30 18:31:07 +00003950 for (const auto &D : OffloadEntriesTargetRegion)
3951 for (const auto &F : D.second)
3952 for (const auto &P : F.second)
3953 for (const auto &L : P.second)
Samuel Antao2de62b02016-02-13 23:35:10 +00003954 Action(D.first, F.first, P.first(), L.first, L.second);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003955}
3956
Alexey Bataev03f270c2018-03-30 18:31:07 +00003957void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3958 initializeDeviceGlobalVarEntryInfo(StringRef Name,
3959 OMPTargetGlobalVarEntryKind Flags,
3960 unsigned Order) {
3961 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
3962 "only required for the device "
3963 "code generation.");
3964 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
3965 ++OffloadingEntriesNum;
3966}
Samuel Antaoee8fb302016-01-06 13:42:12 +00003967
Alexey Bataev03f270c2018-03-30 18:31:07 +00003968void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3969 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr,
3970 CharUnits VarSize,
3971 OMPTargetGlobalVarEntryKind Flags,
3972 llvm::GlobalValue::LinkageTypes Linkage) {
3973 if (CGM.getLangOpts().OpenMPIsDevice) {
3974 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3975 assert(Entry.isValid() && Entry.getFlags() == Flags &&
3976 "Entry not initialized!");
3977 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
3978 "Resetting with the new address.");
Alexey Bataev8259cc32019-03-12 20:05:17 +00003979 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) {
3980 if (Entry.getVarSize().isZero()) {
3981 Entry.setVarSize(VarSize);
3982 Entry.setLinkage(Linkage);
3983 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003984 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00003985 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003986 Entry.setVarSize(VarSize);
3987 Entry.setLinkage(Linkage);
Alexey Bataev8259cc32019-03-12 20:05:17 +00003988 Entry.setAddress(Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00003989 } else {
Alexey Bataev8259cc32019-03-12 20:05:17 +00003990 if (hasDeviceGlobalVarEntryInfo(VarName)) {
3991 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3992 assert(Entry.isValid() && Entry.getFlags() == Flags &&
3993 "Entry not initialized!");
3994 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
3995 "Resetting with the new address.");
3996 if (Entry.getVarSize().isZero()) {
3997 Entry.setVarSize(VarSize);
3998 Entry.setLinkage(Linkage);
3999 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004000 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00004001 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004002 OffloadEntriesDeviceGlobalVar.try_emplace(
4003 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage);
4004 ++OffloadingEntriesNum;
4005 }
4006}
4007
4008void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
4009 actOnDeviceGlobalVarEntriesInfo(
4010 const OffloadDeviceGlobalVarEntryInfoActTy &Action) {
4011 // Scan all target region entries and perform the provided action.
4012 for (const auto &E : OffloadEntriesDeviceGlobalVar)
4013 Action(E.getKey(), E.getValue());
Samuel Antaoee8fb302016-01-06 13:42:12 +00004014}
4015
Alexey Bataev03f270c2018-03-30 18:31:07 +00004016void CGOpenMPRuntime::createOffloadEntry(
4017 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags,
4018 llvm::GlobalValue::LinkageTypes Linkage) {
Samuel Antao2de62b02016-02-13 23:35:10 +00004019 StringRef Name = Addr->getName();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004020 llvm::Module &M = CGM.getModule();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004021 llvm::LLVMContext &C = M.getContext();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004022
4023 // Create constant string with the name.
4024 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
4025
Alexey Bataev18fa2322018-05-02 14:20:50 +00004026 std::string StringName = getName({"omp_offloading", "entry_name"});
4027 auto *Str = new llvm::GlobalVariable(
4028 M, StrPtrInit->getType(), /*isConstant=*/true,
4029 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00004030 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004031
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004032 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy),
4033 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy),
4034 llvm::ConstantInt::get(CGM.SizeTy, Size),
4035 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
4036 llvm::ConstantInt::get(CGM.Int32Ty, 0)};
Alexey Bataev18fa2322018-05-02 14:20:50 +00004037 std::string EntryName = getName({"omp_offloading", "entry", ""});
Mike Ricee1ca7b62018-08-29 15:45:11 +00004038 llvm::GlobalVariable *Entry = createGlobalStruct(
4039 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data,
4040 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004041
4042 // The entry has to be created in the section the linker expects it to be.
Sergey Dmitriev4b343fd2019-09-27 20:00:51 +00004043 Entry->setSection("omp_offloading_entries");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004044}
4045
4046void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
4047 // Emit the offloading entries and metadata so that the device codegen side
Samuel Antao4c8035b2016-12-12 18:00:20 +00004048 // can easily figure out what to emit. The produced metadata looks like
4049 // this:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004050 //
4051 // !omp_offload.info = !{!1, ...}
4052 //
4053 // Right now we only generate metadata for function that contain target
4054 // regions.
4055
Sergey Dmitriev5836c352019-10-15 18:42:47 +00004056 // If we are in simd mode or there are no entries, we don't need to do
4057 // anything.
4058 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty())
Samuel Antaoee8fb302016-01-06 13:42:12 +00004059 return;
4060
4061 llvm::Module &M = CGM.getModule();
4062 llvm::LLVMContext &C = M.getContext();
Alexey Bataevba643691d2019-10-03 16:20:34 +00004063 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *,
4064 SourceLocation, StringRef>,
4065 16>
Samuel Antaoee8fb302016-01-06 13:42:12 +00004066 OrderedEntries(OffloadEntriesInfoManager.size());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004067 llvm::SmallVector<StringRef, 16> ParentFunctions(
4068 OffloadEntriesInfoManager.size());
Samuel Antaoee8fb302016-01-06 13:42:12 +00004069
Simon Pilgrim2c518802017-03-30 14:13:19 +00004070 // Auxiliary methods to create metadata values and strings.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004071 auto &&GetMDInt = [this](unsigned V) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004072 return llvm::ConstantAsMetadata::get(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004073 llvm::ConstantInt::get(CGM.Int32Ty, V));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004074 };
4075
Alexey Bataev03f270c2018-03-30 18:31:07 +00004076 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); };
4077
4078 // Create the offloading info metadata node.
4079 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004080
4081 // Create function that emits metadata for each target region entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00004082 auto &&TargetRegionMetadataEmitter =
Alexey Bataevba643691d2019-10-03 16:20:34 +00004083 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt,
4084 &GetMDString](
Alexey Bataev03f270c2018-03-30 18:31:07 +00004085 unsigned DeviceID, unsigned FileID, StringRef ParentName,
4086 unsigned Line,
4087 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
4088 // Generate metadata for target regions. Each entry of this metadata
4089 // contains:
4090 // - Entry 0 -> Kind of this type of metadata (0).
4091 // - Entry 1 -> Device ID of the file where the entry was identified.
4092 // - Entry 2 -> File ID of the file where the entry was identified.
4093 // - Entry 3 -> Mangled name of the function where the entry was
4094 // identified.
4095 // - Entry 4 -> Line in the file where the entry was identified.
4096 // - Entry 5 -> Order the entry was created.
4097 // The first element of the metadata node is the kind.
4098 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID),
4099 GetMDInt(FileID), GetMDString(ParentName),
4100 GetMDInt(Line), GetMDInt(E.getOrder())};
Samuel Antaoee8fb302016-01-06 13:42:12 +00004101
Alexey Bataevba643691d2019-10-03 16:20:34 +00004102 SourceLocation Loc;
4103 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(),
4104 E = CGM.getContext().getSourceManager().fileinfo_end();
4105 I != E; ++I) {
4106 if (I->getFirst()->getUniqueID().getDevice() == DeviceID &&
4107 I->getFirst()->getUniqueID().getFile() == FileID) {
4108 Loc = CGM.getContext().getSourceManager().translateFileLineCol(
4109 I->getFirst(), Line, 1);
4110 break;
4111 }
4112 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004113 // Save this entry in the right position of the ordered entries array.
Alexey Bataevba643691d2019-10-03 16:20:34 +00004114 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName);
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004115 ParentFunctions[E.getOrder()] = ParentName;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004116
Alexey Bataev03f270c2018-03-30 18:31:07 +00004117 // Add metadata to the named metadata node.
4118 MD->addOperand(llvm::MDNode::get(C, Ops));
4119 };
Samuel Antaoee8fb302016-01-06 13:42:12 +00004120
4121 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
4122 TargetRegionMetadataEmitter);
4123
Alexey Bataev03f270c2018-03-30 18:31:07 +00004124 // Create function that emits metadata for each device global variable entry;
4125 auto &&DeviceGlobalVarMetadataEmitter =
4126 [&C, &OrderedEntries, &GetMDInt, &GetMDString,
4127 MD](StringRef MangledName,
4128 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar
4129 &E) {
4130 // Generate metadata for global variables. Each entry of this metadata
4131 // contains:
4132 // - Entry 0 -> Kind of this type of metadata (1).
4133 // - Entry 1 -> Mangled name of the variable.
4134 // - Entry 2 -> Declare target kind.
4135 // - Entry 3 -> Order the entry was created.
4136 // The first element of the metadata node is the kind.
4137 llvm::Metadata *Ops[] = {
4138 GetMDInt(E.getKind()), GetMDString(MangledName),
4139 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
4140
4141 // Save this entry in the right position of the ordered entries array.
Alexey Bataevba643691d2019-10-03 16:20:34 +00004142 OrderedEntries[E.getOrder()] =
4143 std::make_tuple(&E, SourceLocation(), MangledName);
Alexey Bataev03f270c2018-03-30 18:31:07 +00004144
4145 // Add metadata to the named metadata node.
4146 MD->addOperand(llvm::MDNode::get(C, Ops));
4147 };
4148
4149 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo(
4150 DeviceGlobalVarMetadataEmitter);
4151
Alexey Bataevba643691d2019-10-03 16:20:34 +00004152 for (const auto &E : OrderedEntries) {
4153 assert(std::get<0>(E) && "All ordered entries must exist!");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004154 if (const auto *CE =
Samuel Antaoee8fb302016-01-06 13:42:12 +00004155 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
Alexey Bataevba643691d2019-10-03 16:20:34 +00004156 std::get<0>(E))) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004157 if (!CE->getID() || !CE->getAddress()) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004158 // Do not blame the entry if the parent funtion is not emitted.
4159 StringRef FnName = ParentFunctions[CE->getOrder()];
4160 if (!CGM.GetGlobalValue(FnName))
4161 continue;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004162 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4163 DiagnosticsEngine::Error,
Alexey Bataevba643691d2019-10-03 16:20:34 +00004164 "Offloading entry for target region in %0 is incorrect: either the "
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004165 "address or the ID is invalid.");
Alexey Bataevba643691d2019-10-03 16:20:34 +00004166 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004167 continue;
4168 }
Alexey Bataev34f8a702018-03-28 14:28:54 +00004169 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004170 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage);
Alexey Bataevba643691d2019-10-03 16:20:34 +00004171 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy::
4172 OffloadEntryInfoDeviceGlobalVar>(
4173 std::get<0>(E))) {
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004174 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags =
4175 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4176 CE->getFlags());
4177 switch (Flags) {
4178 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00004179 if (CGM.getLangOpts().OpenMPIsDevice &&
4180 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())
4181 continue;
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004182 if (!CE->getAddress()) {
4183 unsigned DiagID = CGM.getDiags().getCustomDiagID(
Alexey Bataevba643691d2019-10-03 16:20:34 +00004184 DiagnosticsEngine::Error, "Offloading entry for declare target "
4185 "variable %0 is incorrect: the "
4186 "address is invalid.");
4187 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E);
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004188 continue;
4189 }
Alexey Bataevb4dd6d22018-08-29 20:41:37 +00004190 // The vaiable has no definition - no need to add the entry.
4191 if (CE->getVarSize().isZero())
4192 continue;
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004193 break;
4194 }
4195 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink:
4196 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) ||
4197 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) &&
4198 "Declaret target link address is set.");
4199 if (CGM.getLangOpts().OpenMPIsDevice)
4200 continue;
4201 if (!CE->getAddress()) {
4202 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4203 DiagnosticsEngine::Error,
4204 "Offloading entry for declare target variable is incorrect: the "
4205 "address is invalid.");
4206 CGM.getDiags().Report(DiagID);
4207 continue;
4208 }
4209 break;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004210 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004211 createOffloadEntry(CE->getAddress(), CE->getAddress(),
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004212 CE->getVarSize().getQuantity(), Flags,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004213 CE->getLinkage());
4214 } else {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004215 llvm_unreachable("Unsupported entry kind.");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004216 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004217 }
4218}
4219
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004220/// Loads all the offload entries information from the host IR
Samuel Antaoee8fb302016-01-06 13:42:12 +00004221/// metadata.
4222void CGOpenMPRuntime::loadOffloadInfoMetadata() {
4223 // If we are in target mode, load the metadata from the host IR. This code has
4224 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
4225
4226 if (!CGM.getLangOpts().OpenMPIsDevice)
4227 return;
4228
4229 if (CGM.getLangOpts().OMPHostIRFile.empty())
4230 return;
4231
4232 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004233 if (auto EC = Buf.getError()) {
4234 CGM.getDiags().Report(diag::err_cannot_open_file)
4235 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004236 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004237 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004238
4239 llvm::LLVMContext C;
Peter Collingbourned9445c42016-11-13 07:00:17 +00004240 auto ME = expectedToErrorOrAndEmitErrors(
4241 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004242
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004243 if (auto EC = ME.getError()) {
4244 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4245 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'");
4246 CGM.getDiags().Report(DiagID)
4247 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004248 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004249 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004250
4251 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
4252 if (!MD)
4253 return;
4254
George Burgess IV00f70bd2018-03-01 05:43:23 +00004255 for (llvm::MDNode *MN : MD->operands()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004256 auto &&GetMDInt = [MN](unsigned Idx) {
4257 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004258 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
4259 };
4260
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004261 auto &&GetMDString = [MN](unsigned Idx) {
4262 auto *V = cast<llvm::MDString>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004263 return V->getString();
4264 };
4265
Alexey Bataev03f270c2018-03-30 18:31:07 +00004266 switch (GetMDInt(0)) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004267 default:
4268 llvm_unreachable("Unexpected metadata!");
4269 break;
4270 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
Alexey Bataev34f8a702018-03-28 14:28:54 +00004271 OffloadingEntryInfoTargetRegion:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004272 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
Alexey Bataev03f270c2018-03-30 18:31:07 +00004273 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2),
4274 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4),
4275 /*Order=*/GetMDInt(5));
4276 break;
4277 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
4278 OffloadingEntryInfoDeviceGlobalVar:
4279 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo(
4280 /*MangledName=*/GetMDString(1),
4281 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4282 /*Flags=*/GetMDInt(2)),
4283 /*Order=*/GetMDInt(3));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004284 break;
4285 }
4286 }
4287}
4288
Alexey Bataev62b63b12015-03-10 07:28:44 +00004289void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
4290 if (!KmpRoutineEntryPtrTy) {
4291 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004292 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004293 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
4294 FunctionProtoType::ExtProtoInfo EPI;
4295 KmpRoutineEntryPtrQTy = C.getPointerType(
4296 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
4297 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
4298 }
4299}
4300
Samuel Antaoee8fb302016-01-06 13:42:12 +00004301QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004302 // Make sure the type of the entry is already created. This is the type we
4303 // have to create:
4304 // struct __tgt_offload_entry{
4305 // void *addr; // Pointer to the offload entry info.
4306 // // (function or global)
4307 // char *name; // Name of the function or global.
4308 // size_t size; // Size of the entry info (0 if it a function).
Samuel Antaof83efdb2017-01-05 16:02:49 +00004309 // int32_t flags; // Flags associated with the entry, e.g. 'link'.
4310 // int32_t reserved; // Reserved, to use by the runtime library.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004311 // };
4312 if (TgtOffloadEntryQTy.isNull()) {
4313 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004314 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004315 RD->startDefinition();
4316 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4317 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
4318 addFieldToRecordDecl(C, RD, C.getSizeType());
Samuel Antaof83efdb2017-01-05 16:02:49 +00004319 addFieldToRecordDecl(
4320 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4321 addFieldToRecordDecl(
4322 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004323 RD->completeDefinition();
Jonas Hahnfeld5e4df282018-01-18 15:38:03 +00004324 RD->addAttr(PackedAttr::CreateImplicit(C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004325 TgtOffloadEntryQTy = C.getRecordType(RD);
4326 }
4327 return TgtOffloadEntryQTy;
4328}
4329
4330QualType CGOpenMPRuntime::getTgtDeviceImageQTy() {
4331 // These are the types we need to build:
4332 // struct __tgt_device_image{
4333 // void *ImageStart; // Pointer to the target code start.
4334 // void *ImageEnd; // Pointer to the target code end.
4335 // // We also add the host entries to the device image, as it may be useful
4336 // // for the target runtime to have access to that information.
4337 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all
4338 // // the entries.
4339 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
4340 // // entries (non inclusive).
4341 // };
4342 if (TgtDeviceImageQTy.isNull()) {
4343 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004344 RecordDecl *RD = C.buildImplicitRecord("__tgt_device_image");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004345 RD->startDefinition();
4346 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4347 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4348 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4349 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4350 RD->completeDefinition();
4351 TgtDeviceImageQTy = C.getRecordType(RD);
4352 }
4353 return TgtDeviceImageQTy;
4354}
4355
4356QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() {
4357 // struct __tgt_bin_desc{
4358 // int32_t NumDevices; // Number of devices supported.
4359 // __tgt_device_image *DeviceImages; // Arrays of device images
4360 // // (one per device).
4361 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the
4362 // // entries.
4363 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
4364 // // entries (non inclusive).
4365 // };
4366 if (TgtBinaryDescriptorQTy.isNull()) {
4367 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004368 RecordDecl *RD = C.buildImplicitRecord("__tgt_bin_desc");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004369 RD->startDefinition();
4370 addFieldToRecordDecl(
4371 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4372 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy()));
4373 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4374 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4375 RD->completeDefinition();
4376 TgtBinaryDescriptorQTy = C.getRecordType(RD);
4377 }
4378 return TgtBinaryDescriptorQTy;
4379}
4380
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004381namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00004382struct PrivateHelpersTy {
4383 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
4384 const VarDecl *PrivateElemInit)
4385 : Original(Original), PrivateCopy(PrivateCopy),
4386 PrivateElemInit(PrivateElemInit) {}
4387 const VarDecl *Original;
4388 const VarDecl *PrivateCopy;
4389 const VarDecl *PrivateElemInit;
4390};
4391typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Hans Wennborg7eb54642015-09-10 17:07:54 +00004392} // anonymous namespace
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004393
Alexey Bataev9e034042015-05-05 04:05:12 +00004394static RecordDecl *
Craig Topper8674c5c2015-09-29 04:30:07 +00004395createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004396 if (!Privates.empty()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004397 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004398 // Build struct .kmp_privates_t. {
4399 // /* private vars */
4400 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004401 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t");
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004402 RD->startDefinition();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004403 for (const auto &Pair : Privates) {
4404 const VarDecl *VD = Pair.second.Original;
4405 QualType Type = VD->getType().getNonReferenceType();
4406 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type);
Alexey Bataevc71a4092015-09-11 10:29:41 +00004407 if (VD->hasAttrs()) {
4408 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
4409 E(VD->getAttrs().end());
4410 I != E; ++I)
4411 FD->addAttr(*I);
4412 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004413 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004414 RD->completeDefinition();
4415 return RD;
4416 }
4417 return nullptr;
4418}
4419
Alexey Bataev9e034042015-05-05 04:05:12 +00004420static RecordDecl *
Alexey Bataev7292c292016-04-25 12:22:29 +00004421createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind,
4422 QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004423 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004424 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004425 // Build struct kmp_task_t {
4426 // void * shareds;
4427 // kmp_routine_entry_t routine;
4428 // kmp_int32 part_id;
Alexey Bataevad537bb2016-05-30 09:06:50 +00004429 // kmp_cmplrdata_t data1;
4430 // kmp_cmplrdata_t data2;
Alexey Bataev7292c292016-04-25 12:22:29 +00004431 // For taskloops additional fields:
4432 // kmp_uint64 lb;
4433 // kmp_uint64 ub;
4434 // kmp_int64 st;
4435 // kmp_int32 liter;
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004436 // void * reductions;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004437 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004438 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004439 UD->startDefinition();
4440 addFieldToRecordDecl(C, UD, KmpInt32Ty);
4441 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy);
4442 UD->completeDefinition();
4443 QualType KmpCmplrdataTy = C.getRecordType(UD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004444 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t");
Alexey Bataev62b63b12015-03-10 07:28:44 +00004445 RD->startDefinition();
4446 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4447 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
4448 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004449 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
4450 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004451 if (isOpenMPTaskLoopDirective(Kind)) {
4452 QualType KmpUInt64Ty =
4453 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
4454 QualType KmpInt64Ty =
4455 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
4456 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4457 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4458 addFieldToRecordDecl(C, RD, KmpInt64Ty);
4459 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004460 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004461 }
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004462 RD->completeDefinition();
4463 return RD;
4464}
4465
4466static RecordDecl *
4467createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004468 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004469 ASTContext &C = CGM.getContext();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004470 // Build struct kmp_task_t_with_privates {
4471 // kmp_task_t task_data;
4472 // .kmp_privates_t. privates;
4473 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004474 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004475 RD->startDefinition();
4476 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004477 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates))
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004478 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004479 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004480 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004481}
4482
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004483/// Emit a proxy function which accepts kmp_task_t as the second
Alexey Bataev62b63b12015-03-10 07:28:44 +00004484/// argument.
4485/// \code
4486/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00004487/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt,
Alexey Bataev7292c292016-04-25 12:22:29 +00004488/// For taskloops:
4489/// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004490/// tt->reductions, tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004491/// return 0;
4492/// }
4493/// \endcode
James Y Knight9871db02019-02-05 16:42:33 +00004494static llvm::Function *
Alexey Bataev62b63b12015-03-10 07:28:44 +00004495emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev7292c292016-04-25 12:22:29 +00004496 OpenMPDirectiveKind Kind, QualType KmpInt32Ty,
4497 QualType KmpTaskTWithPrivatesPtrQTy,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004498 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
James Y Knight9871db02019-02-05 16:42:33 +00004499 QualType SharedsPtrTy, llvm::Function *TaskFunction,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004500 llvm::Value *TaskPrivatesMap) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004501 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004502 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004503 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4504 ImplicitParamDecl::Other);
4505 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4506 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4507 ImplicitParamDecl::Other);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004508 Args.push_back(&GtidArg);
4509 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004510 const auto &TaskEntryFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004511 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004512 llvm::FunctionType *TaskEntryTy =
4513 CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004514 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""});
4515 auto *TaskEntry = llvm::Function::Create(
4516 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004517 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004518 TaskEntry->setDoesNotRecurse();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004519 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004520 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args,
4521 Loc, Loc);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004522
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004523 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
Alexey Bataev7292c292016-04-25 12:22:29 +00004524 // tt,
4525 // For taskloops:
4526 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
4527 // tt->task_data.shareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004528 llvm::Value *GtidParam = CGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00004529 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
Alexey Bataev31300ed2016-02-04 11:27:03 +00004530 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4531 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4532 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004533 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004534 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004535 LValue Base =
4536 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004537 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004538 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004539 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
4540 llvm::Value *PartidParam = PartIdLVal.getPointer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004541
4542 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004543 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
4544 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev1e491372018-01-23 18:44:14 +00004545 CGF.EmitLoadOfScalar(SharedsLVal, Loc),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004546 CGF.ConvertTypeForMem(SharedsPtrTy));
4547
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004548 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4549 llvm::Value *PrivatesParam;
4550 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004551 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004552 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00004553 PrivatesLVal.getPointer(), CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004554 } else {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004555 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004556 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004557
Alexey Bataev7292c292016-04-25 12:22:29 +00004558 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam,
4559 TaskPrivatesMap,
4560 CGF.Builder
4561 .CreatePointerBitCastOrAddrSpaceCast(
4562 TDBase.getAddress(), CGF.VoidPtrTy)
4563 .getPointer()};
4564 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs),
4565 std::end(CommonArgs));
4566 if (isOpenMPTaskLoopDirective(Kind)) {
4567 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004568 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI);
4569 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004570 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004571 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI);
4572 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004573 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004574 LValue StLVal = CGF.EmitLValueForField(Base, *StFI);
4575 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004576 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004577 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4578 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004579 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004580 LValue RLVal = CGF.EmitLValueForField(Base, *RFI);
4581 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004582 CallArgs.push_back(LBParam);
4583 CallArgs.push_back(UBParam);
4584 CallArgs.push_back(StParam);
4585 CallArgs.push_back(LIParam);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004586 CallArgs.push_back(RParam);
Alexey Bataev7292c292016-04-25 12:22:29 +00004587 }
4588 CallArgs.push_back(SharedsParam);
4589
Alexey Bataev3c595a62017-08-14 15:01:03 +00004590 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction,
4591 CallArgs);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004592 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)),
4593 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004594 CGF.FinishFunction();
4595 return TaskEntry;
4596}
4597
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004598static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
4599 SourceLocation Loc,
4600 QualType KmpInt32Ty,
4601 QualType KmpTaskTWithPrivatesPtrQTy,
4602 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004603 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004604 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004605 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4606 ImplicitParamDecl::Other);
4607 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4608 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4609 ImplicitParamDecl::Other);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004610 Args.push_back(&GtidArg);
4611 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004612 const auto &DestructorFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004613 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004614 llvm::FunctionType *DestructorFnTy =
4615 CGM.getTypes().GetFunctionType(DestructorFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004616 std::string Name =
4617 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""});
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004618 auto *DestructorFn =
4619 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00004620 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004621 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004622 DestructorFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004623 DestructorFn->setDoesNotRecurse();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004624 CodeGenFunction CGF(CGM);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004625 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004626 Args, Loc, Loc);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004627
Alexey Bataev31300ed2016-02-04 11:27:03 +00004628 LValue Base = CGF.EmitLoadOfPointerLValue(
4629 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4630 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004631 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004632 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
4633 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004634 Base = CGF.EmitLValueForField(Base, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004635 for (const auto *Field :
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004636 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004637 if (QualType::DestructionKind DtorKind =
4638 Field->getType().isDestructedType()) {
4639 LValue FieldLValue = CGF.EmitLValueForField(Base, Field);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004640 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
4641 }
4642 }
4643 CGF.FinishFunction();
4644 return DestructorFn;
4645}
4646
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004647/// Emit a privates mapping function for correct handling of private and
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004648/// firstprivate variables.
4649/// \code
4650/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
4651/// **noalias priv1,..., <tyn> **noalias privn) {
4652/// *priv1 = &.privates.priv1;
4653/// ...;
4654/// *privn = &.privates.privn;
4655/// }
4656/// \endcode
4657static llvm::Value *
4658emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Craig Topper8674c5c2015-09-29 04:30:07 +00004659 ArrayRef<const Expr *> PrivateVars,
4660 ArrayRef<const Expr *> FirstprivateVars,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004661 ArrayRef<const Expr *> LastprivateVars,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004662 QualType PrivatesQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004663 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004664 ASTContext &C = CGM.getContext();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004665 FunctionArgList Args;
4666 ImplicitParamDecl TaskPrivatesArg(
4667 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
Alexey Bataev56223232017-06-09 13:40:18 +00004668 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
4669 ImplicitParamDecl::Other);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004670 Args.push_back(&TaskPrivatesArg);
4671 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
4672 unsigned Counter = 1;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004673 for (const Expr *E : PrivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004674 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004675 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4676 C.getPointerType(C.getPointerType(E->getType()))
4677 .withConst()
4678 .withRestrict(),
4679 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004680 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004681 PrivateVarsPos[VD] = Counter;
4682 ++Counter;
4683 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004684 for (const Expr *E : FirstprivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004685 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004686 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4687 C.getPointerType(C.getPointerType(E->getType()))
4688 .withConst()
4689 .withRestrict(),
4690 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004691 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004692 PrivateVarsPos[VD] = Counter;
4693 ++Counter;
4694 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004695 for (const Expr *E : LastprivateVars) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004696 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004697 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4698 C.getPointerType(C.getPointerType(E->getType()))
4699 .withConst()
4700 .withRestrict(),
4701 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004702 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataevf93095a2016-05-05 08:46:22 +00004703 PrivateVarsPos[VD] = Counter;
4704 ++Counter;
4705 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004706 const auto &TaskPrivatesMapFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004707 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004708 llvm::FunctionType *TaskPrivatesMapTy =
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004709 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004710 std::string Name =
4711 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""});
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004712 auto *TaskPrivatesMap = llvm::Function::Create(
Alexey Bataev18fa2322018-05-02 14:20:50 +00004713 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
4714 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004715 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004716 TaskPrivatesMapFnInfo);
Alexey Bataev8c5555c2019-05-21 15:11:58 +00004717 if (CGM.getLangOpts().Optimize) {
4718 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
4719 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
4720 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
4721 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004722 CodeGenFunction CGF(CGM);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004723 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004724 TaskPrivatesMapFnInfo, Args, Loc, Loc);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004725
4726 // *privi = &.privates.privi;
Alexey Bataev31300ed2016-02-04 11:27:03 +00004727 LValue Base = CGF.EmitLoadOfPointerLValue(
4728 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
4729 TaskPrivatesArg.getType()->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004730 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004731 Counter = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004732 for (const FieldDecl *Field : PrivatesQTyRD->fields()) {
4733 LValue FieldLVal = CGF.EmitLValueForField(Base, Field);
4734 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
4735 LValue RefLVal =
4736 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
4737 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue(
Alexey Bataev31300ed2016-02-04 11:27:03 +00004738 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>());
Alexey Bataev2377fe92015-09-10 08:12:02 +00004739 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004740 ++Counter;
4741 }
4742 CGF.FinishFunction();
4743 return TaskPrivatesMap;
4744}
4745
Alexey Bataevf93095a2016-05-05 08:46:22 +00004746/// Emit initialization for private variables in task-based directives.
Alexey Bataev8a831592016-05-10 10:36:51 +00004747static void emitPrivatesInit(CodeGenFunction &CGF,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004748 const OMPExecutableDirective &D,
4749 Address KmpTaskSharedsPtr, LValue TDBase,
4750 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4751 QualType SharedsTy, QualType SharedsPtrTy,
4752 const OMPTaskDataTy &Data,
4753 ArrayRef<PrivateDataTy> Privates, bool ForDup) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004754 ASTContext &C = CGF.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004755 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
4756 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004757 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind())
4758 ? OMPD_taskloop
4759 : OMPD_task;
4760 const CapturedStmt &CS = *D.getCapturedStmt(Kind);
4761 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004762 LValue SrcBase;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004763 bool IsTargetTask =
4764 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) ||
4765 isOpenMPTargetExecutionDirective(D.getDirectiveKind());
4766 // For target-based directives skip 3 firstprivate arrays BasePointersArray,
4767 // PointersArray and SizesArray. The original variables for these arrays are
4768 // not captured and we get their addresses explicitly.
4769 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) ||
Alexey Bataev8451efa2018-01-15 19:06:12 +00004770 (IsTargetTask && KmpTaskSharedsPtr.isValid())) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004771 SrcBase = CGF.MakeAddrLValue(
4772 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4773 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
4774 SharedsTy);
4775 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004776 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004777 for (const PrivateDataTy &Pair : Privates) {
4778 const VarDecl *VD = Pair.second.PrivateCopy;
4779 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004780 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) &&
4781 !CGF.isTrivialInitializer(Init)))) {
Alexey Bataev8a831592016-05-10 10:36:51 +00004782 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004783 if (const VarDecl *Elem = Pair.second.PrivateElemInit) {
4784 const VarDecl *OriginalVD = Pair.second.Original;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004785 // Check if the variable is the target-based BasePointersArray,
4786 // PointersArray or SizesArray.
4787 LValue SharedRefLValue;
Alexey Bataevab41ea62019-03-13 20:46:28 +00004788 QualType Type = PrivateLValue.getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004789 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004790 if (IsTargetTask && !SharedField) {
4791 assert(isa<ImplicitParamDecl>(OriginalVD) &&
4792 isa<CapturedDecl>(OriginalVD->getDeclContext()) &&
4793 cast<CapturedDecl>(OriginalVD->getDeclContext())
4794 ->getNumParams() == 0 &&
4795 isa<TranslationUnitDecl>(
4796 cast<CapturedDecl>(OriginalVD->getDeclContext())
4797 ->getDeclContext()) &&
4798 "Expected artificial target data variable.");
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004799 SharedRefLValue =
4800 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type);
4801 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004802 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField);
4803 SharedRefLValue = CGF.MakeAddrLValue(
4804 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
4805 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl),
4806 SharedRefLValue.getTBAAInfo());
4807 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004808 if (Type->isArrayType()) {
4809 // Initialize firstprivate array.
4810 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) {
4811 // Perform simple memcpy.
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00004812 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004813 } else {
4814 // Initialize firstprivate array using element-by-element
Simon Pilgrim2c518802017-03-30 14:13:19 +00004815 // initialization.
Alexey Bataevf93095a2016-05-05 08:46:22 +00004816 CGF.EmitOMPAggregateAssign(
4817 PrivateLValue.getAddress(), SharedRefLValue.getAddress(), Type,
4818 [&CGF, Elem, Init, &CapturesInfo](Address DestElement,
4819 Address SrcElement) {
4820 // Clean up any temporaries needed by the initialization.
4821 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4822 InitScope.addPrivate(
4823 Elem, [SrcElement]() -> Address { return SrcElement; });
4824 (void)InitScope.Privatize();
4825 // Emit initialization for single element.
4826 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
4827 CGF, &CapturesInfo);
4828 CGF.EmitAnyExprToMem(Init, DestElement,
4829 Init->getType().getQualifiers(),
4830 /*IsInitializer=*/false);
4831 });
4832 }
4833 } else {
4834 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4835 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
4836 return SharedRefLValue.getAddress();
4837 });
4838 (void)InitScope.Privatize();
4839 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
4840 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
4841 /*capturedByInit=*/false);
4842 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004843 } else {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004844 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004845 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004846 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004847 ++FI;
4848 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004849}
4850
4851/// Check if duplication function is required for taskloops.
4852static bool checkInitIsRequired(CodeGenFunction &CGF,
4853 ArrayRef<PrivateDataTy> Privates) {
4854 bool InitRequired = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004855 for (const PrivateDataTy &Pair : Privates) {
4856 const VarDecl *VD = Pair.second.PrivateCopy;
4857 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004858 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) &&
4859 !CGF.isTrivialInitializer(Init));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004860 if (InitRequired)
4861 break;
Alexey Bataevf93095a2016-05-05 08:46:22 +00004862 }
4863 return InitRequired;
4864}
4865
4866
4867/// Emit task_dup function (for initialization of
4868/// private/firstprivate/lastprivate vars and last_iter flag)
4869/// \code
4870/// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int
4871/// lastpriv) {
4872/// // setup lastprivate flag
4873/// task_dst->last = lastpriv;
4874/// // could be constructor calls here...
4875/// }
4876/// \endcode
4877static llvm::Value *
4878emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
4879 const OMPExecutableDirective &D,
4880 QualType KmpTaskTWithPrivatesPtrQTy,
4881 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4882 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy,
4883 QualType SharedsPtrTy, const OMPTaskDataTy &Data,
4884 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004885 ASTContext &C = CGM.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004886 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004887 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4888 KmpTaskTWithPrivatesPtrQTy,
4889 ImplicitParamDecl::Other);
4890 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4891 KmpTaskTWithPrivatesPtrQTy,
4892 ImplicitParamDecl::Other);
4893 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy,
4894 ImplicitParamDecl::Other);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004895 Args.push_back(&DstArg);
4896 Args.push_back(&SrcArg);
4897 Args.push_back(&LastprivArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004898 const auto &TaskDupFnInfo =
Alexey Bataevf93095a2016-05-05 08:46:22 +00004899 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004900 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004901 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""});
4902 auto *TaskDup = llvm::Function::Create(
4903 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004904 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004905 TaskDup->setDoesNotRecurse();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004906 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004907 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc,
4908 Loc);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004909
4910 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4911 CGF.GetAddrOfLocalVar(&DstArg),
4912 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4913 // task_dst->liter = lastpriv;
4914 if (WithLastIter) {
4915 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
4916 LValue Base = CGF.EmitLValueForField(
4917 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4918 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4919 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar(
4920 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc);
4921 CGF.EmitStoreOfScalar(Lastpriv, LILVal);
4922 }
4923
4924 // Emit initial values for private copies (if any).
4925 assert(!Privates.empty());
4926 Address KmpTaskSharedsPtr = Address::invalid();
4927 if (!Data.FirstprivateVars.empty()) {
4928 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4929 CGF.GetAddrOfLocalVar(&SrcArg),
4930 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4931 LValue Base = CGF.EmitLValueForField(
4932 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4933 KmpTaskSharedsPtr = Address(
4934 CGF.EmitLoadOfScalar(CGF.EmitLValueForField(
4935 Base, *std::next(KmpTaskTQTyRD->field_begin(),
4936 KmpTaskTShareds)),
4937 Loc),
4938 CGF.getNaturalTypeAlignment(SharedsTy));
4939 }
Alexey Bataev8a831592016-05-10 10:36:51 +00004940 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
4941 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004942 CGF.FinishFunction();
4943 return TaskDup;
4944}
4945
Alexey Bataev8a831592016-05-10 10:36:51 +00004946/// Checks if destructor function is required to be generated.
4947/// \return true if cleanups are required, false otherwise.
4948static bool
4949checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) {
4950 bool NeedsCleanup = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004951 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4952 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl());
4953 for (const FieldDecl *FD : PrivateRD->fields()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00004954 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType();
4955 if (NeedsCleanup)
4956 break;
4957 }
4958 return NeedsCleanup;
4959}
4960
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004961CGOpenMPRuntime::TaskResultTy
4962CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
4963 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00004964 llvm::Function *TaskFunction, QualType SharedsTy,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004965 Address Shareds, const OMPTaskDataTy &Data) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004966 ASTContext &C = CGM.getContext();
Alexey Bataev7292c292016-04-25 12:22:29 +00004967 llvm::SmallVector<PrivateDataTy, 4> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004968 // Aggregate privates and sort them by the alignment.
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004969 auto I = Data.PrivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004970 for (const Expr *E : Data.PrivateVars) {
4971 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00004972 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00004973 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00004974 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00004975 /*PrivateElemInit=*/nullptr));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004976 ++I;
4977 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004978 I = Data.FirstprivateCopies.begin();
4979 auto IElemInitRef = Data.FirstprivateInits.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004980 for (const Expr *E : Data.FirstprivateVars) {
4981 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00004982 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00004983 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00004984 PrivateHelpersTy(
4985 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00004986 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())));
Richard Trieucc3949d2016-02-18 22:34:54 +00004987 ++I;
4988 ++IElemInitRef;
Alexey Bataev9e034042015-05-05 04:05:12 +00004989 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004990 I = Data.LastprivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004991 for (const Expr *E : Data.LastprivateVars) {
4992 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00004993 Privates.emplace_back(
Alexey Bataevf93095a2016-05-05 08:46:22 +00004994 C.getDeclAlign(VD),
4995 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00004996 /*PrivateElemInit=*/nullptr));
Alexey Bataevf93095a2016-05-05 08:46:22 +00004997 ++I;
4998 }
Fangrui Song899d1392019-04-24 14:43:05 +00004999 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) {
5000 return L.first > R.first;
5001 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005002 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005003 // Build type kmp_routine_entry_t (if not built yet).
5004 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005005 // Build type kmp_task_t (if not built yet).
Alexey Bataeve213f3e2017-10-11 15:29:40 +00005006 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) {
5007 if (SavedKmpTaskloopTQTy.isNull()) {
5008 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5009 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5010 }
5011 KmpTaskTQTy = SavedKmpTaskloopTQTy;
Alexey Bataev3a03a7f2017-10-11 15:56:38 +00005012 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00005013 assert((D.getDirectiveKind() == OMPD_task ||
5014 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) ||
5015 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) &&
5016 "Expected taskloop, task or target directive");
Alexey Bataeve213f3e2017-10-11 15:29:40 +00005017 if (SavedKmpTaskTQTy.isNull()) {
5018 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5019 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5020 }
5021 KmpTaskTQTy = SavedKmpTaskTQTy;
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005022 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005023 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005024 // Build particular struct kmp_task_t for the given task.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005025 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005026 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005027 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005028 QualType KmpTaskTWithPrivatesPtrQTy =
5029 C.getPointerType(KmpTaskTWithPrivatesQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005030 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
5031 llvm::Type *KmpTaskTWithPrivatesPtrTy =
5032 KmpTaskTWithPrivatesTy->getPointerTo();
5033 llvm::Value *KmpTaskTWithPrivatesTySize =
5034 CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005035 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
5036
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005037 // Emit initial values for private copies (if any).
5038 llvm::Value *TaskPrivatesMap = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005039 llvm::Type *TaskPrivatesMapTy =
James Y Knight9871db02019-02-05 16:42:33 +00005040 std::next(TaskFunction->arg_begin(), 3)->getType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005041 if (!Privates.empty()) {
5042 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataevf93095a2016-05-05 08:46:22 +00005043 TaskPrivatesMap = emitTaskPrivateMappingFunction(
5044 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars,
5045 FI->getType(), Privates);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005046 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5047 TaskPrivatesMap, TaskPrivatesMapTy);
5048 } else {
5049 TaskPrivatesMap = llvm::ConstantPointerNull::get(
5050 cast<llvm::PointerType>(TaskPrivatesMapTy));
5051 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005052 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
5053 // kmp_task_t *tt);
James Y Knight9871db02019-02-05 16:42:33 +00005054 llvm::Function *TaskEntry = emitProxyTaskFunction(
Alexey Bataev7292c292016-04-25 12:22:29 +00005055 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5056 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction,
5057 TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005058
5059 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
5060 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
5061 // kmp_routine_entry_t *task_entry);
5062 // Task flags. Format is taken from
James Y Knight5d71fc52019-01-29 16:37:27 +00005063 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h,
Alexey Bataev62b63b12015-03-10 07:28:44 +00005064 // description of kmp_tasking_flags struct.
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005065 enum {
5066 TiedFlag = 0x1,
5067 FinalFlag = 0x2,
5068 DestructorsFlag = 0x8,
5069 PriorityFlag = 0x20
5070 };
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005071 unsigned Flags = Data.Tied ? TiedFlag : 0;
Alexey Bataev8a831592016-05-10 10:36:51 +00005072 bool NeedsCleanup = false;
5073 if (!Privates.empty()) {
5074 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD);
5075 if (NeedsCleanup)
5076 Flags = Flags | DestructorsFlag;
5077 }
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005078 if (Data.Priority.getInt())
5079 Flags = Flags | PriorityFlag;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005080 llvm::Value *TaskFlags =
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005081 Data.Final.getPointer()
5082 ? CGF.Builder.CreateSelect(Data.Final.getPointer(),
Alexey Bataev62b63b12015-03-10 07:28:44 +00005083 CGF.Builder.getInt32(FinalFlag),
5084 CGF.Builder.getInt32(/*C=*/0))
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005085 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005086 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005087 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00005088 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc),
5089 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
5090 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5091 TaskEntry, KmpRoutineEntryPtrTy)};
5092 llvm::Value *NewTask;
5093 if (D.hasClausesOfKind<OMPNowaitClause>()) {
5094 // Check if we have any device clause associated with the directive.
5095 const Expr *Device = nullptr;
5096 if (auto *C = D.getSingleClause<OMPDeviceClause>())
5097 Device = C->getDevice();
5098 // Emit device ID if any otherwise use default value.
5099 llvm::Value *DeviceID;
5100 if (Device)
5101 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
5102 CGF.Int64Ty, /*isSigned=*/true);
5103 else
5104 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
5105 AllocArgs.push_back(DeviceID);
5106 NewTask = CGF.EmitRuntimeCall(
5107 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs);
5108 } else {
5109 NewTask = CGF.EmitRuntimeCall(
Alexey Bataev62b63b12015-03-10 07:28:44 +00005110 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00005111 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005112 llvm::Value *NewTaskNewTaskTTy =
5113 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5114 NewTask, KmpTaskTWithPrivatesPtrTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005115 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
5116 KmpTaskTWithPrivatesQTy);
5117 LValue TDBase =
5118 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005119 // Fill the data in the resulting kmp_task_t record.
5120 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00005121 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005122 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00005123 KmpTaskSharedsPtr =
5124 Address(CGF.EmitLoadOfScalar(
5125 CGF.EmitLValueForField(
5126 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
5127 KmpTaskTShareds)),
5128 Loc),
5129 CGF.getNaturalTypeAlignment(SharedsTy));
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00005130 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy);
5131 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy);
Richard Smithe78fac52018-04-05 20:52:58 +00005132 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005133 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005134 // Emit initial values for private copies (if any).
Alexey Bataevf93095a2016-05-05 08:46:22 +00005135 TaskResultTy Result;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005136 if (!Privates.empty()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00005137 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD,
5138 SharedsTy, SharedsPtrTy, Data, Privates,
5139 /*ForDup=*/false);
Alexey Bataevf93095a2016-05-05 08:46:22 +00005140 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
5141 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) {
5142 Result.TaskDupFn = emitTaskDupFunction(
5143 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
5144 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates,
5145 /*WithLastIter=*/!Data.LastprivateVars.empty());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005146 }
5147 }
Alexey Bataevad537bb2016-05-30 09:06:50 +00005148 // Fields of union "kmp_cmplrdata_t" for destructors and priority.
5149 enum { Priority = 0, Destructors = 1 };
Alexey Bataev62b63b12015-03-10 07:28:44 +00005150 // Provide pointer to function with destructors for privates.
Alexey Bataevad537bb2016-05-30 09:06:50 +00005151 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005152 const RecordDecl *KmpCmplrdataUD =
5153 (*FI)->getType()->getAsUnionType()->getDecl();
Alexey Bataevad537bb2016-05-30 09:06:50 +00005154 if (NeedsCleanup) {
5155 llvm::Value *DestructorFn = emitDestructorsFunction(
5156 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5157 KmpTaskTWithPrivatesQTy);
5158 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI);
5159 LValue DestructorsLV = CGF.EmitLValueForField(
5160 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
5161 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5162 DestructorFn, KmpRoutineEntryPtrTy),
5163 DestructorsLV);
5164 }
5165 // Set priority.
5166 if (Data.Priority.getInt()) {
5167 LValue Data2LV = CGF.EmitLValueForField(
5168 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
5169 LValue PriorityLV = CGF.EmitLValueForField(
5170 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
5171 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV);
5172 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005173 Result.NewTask = NewTask;
5174 Result.TaskEntry = TaskEntry;
5175 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
5176 Result.TDBase = TDBase;
5177 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
5178 return Result;
Alexey Bataev7292c292016-04-25 12:22:29 +00005179}
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005180
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005181void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
5182 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005183 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005184 QualType SharedsTy, Address Shareds,
5185 const Expr *IfCond,
5186 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005187 if (!CGF.HaveInsertPoint())
5188 return;
5189
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005190 TaskResultTy Result =
5191 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
5192 llvm::Value *NewTask = Result.NewTask;
James Y Knight9871db02019-02-05 16:42:33 +00005193 llvm::Function *TaskEntry = Result.TaskEntry;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005194 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy;
5195 LValue TDBase = Result.TDBase;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005196 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD;
5197 ASTContext &C = CGM.getContext();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005198 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00005199 Address DependenciesArray = Address::invalid();
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005200 unsigned NumDependencies = Data.Dependences.size();
John McCall7f416cc2015-09-08 08:05:57 +00005201 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005202 // Dependence kind for RTL.
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005203 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 };
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005204 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
5205 RecordDecl *KmpDependInfoRD;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005206 QualType FlagsTy =
5207 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005208 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
5209 if (KmpDependInfoTy.isNull()) {
5210 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
5211 KmpDependInfoRD->startDefinition();
5212 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
5213 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
5214 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
5215 KmpDependInfoRD->completeDefinition();
5216 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005217 } else {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005218 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005219 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005220 // Define type kmp_depend_info[<Dependences.size()>];
5221 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00005222 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Richard Smith772e2662019-10-04 01:25:59 +00005223 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005224 // kmp_depend_info[<Dependences.size()>] deps;
Alexey Bataev48591dd2016-04-20 04:01:36 +00005225 DependenciesArray =
5226 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005227 for (unsigned I = 0; I < NumDependencies; ++I) {
5228 const Expr *E = Data.Dependences[I].second;
5229 LValue Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005230 llvm::Value *Size;
5231 QualType Ty = E->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005232 if (const auto *ASE =
5233 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005234 LValue UpAddrLVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005235 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005236 llvm::Value *UpAddr =
John McCall7f416cc2015-09-08 08:05:57 +00005237 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005238 llvm::Value *LowIntPtr =
John McCall7f416cc2015-09-08 08:05:57 +00005239 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005240 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
5241 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005242 } else {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005243 Size = CGF.getTypeSize(Ty);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005244 }
5245 LValue Base = CGF.MakeAddrLValue(
James Y Knight751fe282019-02-09 22:22:28 +00005246 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005247 KmpDependInfoTy);
5248 // deps[i].base_addr = &<Dependences[i].second>;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005249 LValue BaseAddrLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005250 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00005251 CGF.EmitStoreOfScalar(
5252 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy),
5253 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005254 // deps[i].len = sizeof(<Dependences[i].second>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005255 LValue LenLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005256 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
5257 CGF.EmitStoreOfScalar(Size, LenLVal);
5258 // deps[i].flags = <Dependences[i].first>;
5259 RTLDependenceKindTy DepKind;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005260 switch (Data.Dependences[I].first) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005261 case OMPC_DEPEND_in:
5262 DepKind = DepIn;
5263 break;
Alexey Bataev92e82f92015-11-23 13:33:42 +00005264 // Out and InOut dependencies must use the same code.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005265 case OMPC_DEPEND_out:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005266 case OMPC_DEPEND_inout:
5267 DepKind = DepInOut;
5268 break;
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005269 case OMPC_DEPEND_mutexinoutset:
5270 DepKind = DepMutexInOutSet;
5271 break;
Alexey Bataeveb482352015-12-18 05:05:56 +00005272 case OMPC_DEPEND_source:
Alexey Bataeva636c7f2015-12-23 10:27:45 +00005273 case OMPC_DEPEND_sink:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005274 case OMPC_DEPEND_unknown:
5275 llvm_unreachable("Unknown task dependence type");
5276 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005277 LValue FlagsLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005278 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
5279 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
5280 FlagsLVal);
5281 }
John McCall7f416cc2015-09-08 08:05:57 +00005282 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knightf5f1b0e2019-02-08 15:34:12 +00005283 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005284 }
5285
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005286 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev62b63b12015-03-10 07:28:44 +00005287 // libcall.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005288 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
5289 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
5290 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
5291 // list is not empty
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005292 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5293 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00005294 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
5295 llvm::Value *DepTaskArgs[7];
5296 if (NumDependencies) {
5297 DepTaskArgs[0] = UpLoc;
5298 DepTaskArgs[1] = ThreadID;
5299 DepTaskArgs[2] = NewTask;
5300 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
5301 DepTaskArgs[4] = DependenciesArray.getPointer();
5302 DepTaskArgs[5] = CGF.Builder.getInt32(0);
5303 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5304 }
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005305 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies,
5306 &TaskArgs,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005307 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005308 if (!Data.Tied) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005309 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005310 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
Alexey Bataev48591dd2016-04-20 04:01:36 +00005311 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
5312 }
John McCall7f416cc2015-09-08 08:05:57 +00005313 if (NumDependencies) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005314 CGF.EmitRuntimeCall(
Alexey Bataev48591dd2016-04-20 04:01:36 +00005315 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs);
John McCall7f416cc2015-09-08 08:05:57 +00005316 } else {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005317 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
John McCall7f416cc2015-09-08 08:05:57 +00005318 TaskArgs);
5319 }
Alexey Bataev48591dd2016-04-20 04:01:36 +00005320 // Check if parent region is untied and build return for untied task;
5321 if (auto *Region =
5322 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
5323 Region->emitUntiedSwitch(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00005324 };
John McCall7f416cc2015-09-08 08:05:57 +00005325
5326 llvm::Value *DepWaitTaskArgs[6];
5327 if (NumDependencies) {
5328 DepWaitTaskArgs[0] = UpLoc;
5329 DepWaitTaskArgs[1] = ThreadID;
5330 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
5331 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
5332 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
5333 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5334 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005335 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
Alexey Bataev3c595a62017-08-14 15:01:03 +00005336 NumDependencies, &DepWaitTaskArgs,
5337 Loc](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005338 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005339 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
5340 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
5341 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
5342 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
5343 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00005344 if (NumDependencies)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005345 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005346 DepWaitTaskArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005347 // Call proxy_task_entry(gtid, new_task);
Alexey Bataev3c595a62017-08-14 15:01:03 +00005348 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
5349 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005350 Action.Enter(CGF);
5351 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
Alexey Bataev3c595a62017-08-14 15:01:03 +00005352 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
Alexey Bataev2c7eee52017-08-04 19:10:54 +00005353 OutlinedFnArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005354 };
5355
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005356 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
5357 // kmp_task_t *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005358 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
5359 // kmp_task_t *new_task);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005360 RegionCodeGenTy RCG(CodeGen);
5361 CommonActionTy Action(
5362 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs,
5363 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs);
5364 RCG.setAction(Action);
5365 RCG(CGF);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005366 };
John McCall7f416cc2015-09-08 08:05:57 +00005367
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005368 if (IfCond) {
Alexey Bataev1d677132015-04-22 13:57:31 +00005369 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005370 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005371 RegionCodeGenTy ThenRCG(ThenCodeGen);
5372 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00005373 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005374}
5375
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005376void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
5377 const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005378 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005379 QualType SharedsTy, Address Shareds,
5380 const Expr *IfCond,
5381 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005382 if (!CGF.HaveInsertPoint())
5383 return;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005384 TaskResultTy Result =
5385 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005386 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev7292c292016-04-25 12:22:29 +00005387 // libcall.
5388 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
5389 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
5390 // sched, kmp_uint64 grainsize, void *task_dup);
5391 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5392 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
5393 llvm::Value *IfVal;
5394 if (IfCond) {
5395 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy,
5396 /*isSigned=*/true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005397 } else {
Alexey Bataev7292c292016-04-25 12:22:29 +00005398 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005399 }
Alexey Bataev7292c292016-04-25 12:22:29 +00005400
5401 LValue LBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005402 Result.TDBase,
5403 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005404 const auto *LBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005405 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl());
5406 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(),
5407 /*IsInitializer=*/true);
5408 LValue UBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005409 Result.TDBase,
5410 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005411 const auto *UBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005412 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl());
5413 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(),
5414 /*IsInitializer=*/true);
5415 LValue StLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005416 Result.TDBase,
5417 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005418 const auto *StVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005419 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl());
5420 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(),
5421 /*IsInitializer=*/true);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005422 // Store reductions address.
5423 LValue RedLVal = CGF.EmitLValueForField(
5424 Result.TDBase,
5425 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005426 if (Data.Reductions) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005427 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005428 } else {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005429 CGF.EmitNullInitialization(RedLVal.getAddress(),
5430 CGF.getContext().VoidPtrTy);
5431 }
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005432 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
Alexey Bataev7292c292016-04-25 12:22:29 +00005433 llvm::Value *TaskArgs[] = {
Alexey Bataev33446032017-07-12 18:09:32 +00005434 UpLoc,
5435 ThreadID,
5436 Result.NewTask,
5437 IfVal,
5438 LBLVal.getPointer(),
5439 UBLVal.getPointer(),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00005440 CGF.EmitLoadOfScalar(StLVal, Loc),
Alexey Bataevac6e4de2018-10-24 19:06:37 +00005441 llvm::ConstantInt::getSigned(
5442 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005443 llvm::ConstantInt::getSigned(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005444 CGF.IntTy, Data.Schedule.getPointer()
5445 ? Data.Schedule.getInt() ? NumTasks : Grainsize
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005446 : NoSchedule),
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005447 Data.Schedule.getPointer()
5448 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty,
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005449 /*isSigned=*/false)
5450 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0),
Alexey Bataev33446032017-07-12 18:09:32 +00005451 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5452 Result.TaskDupFn, CGF.VoidPtrTy)
5453 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)};
Alexey Bataev7292c292016-04-25 12:22:29 +00005454 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs);
5455}
5456
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005457/// Emit reduction operation for each element of array (required for
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005458/// array sections) LHS op = RHS.
5459/// \param Type Type of array.
5460/// \param LHSVar Variable on the left side of the reduction operation
5461/// (references element of array in original variable).
5462/// \param RHSVar Variable on the right side of the reduction operation
5463/// (references element of array in original variable).
5464/// \param RedOpGen Generator of reduction operation with use of LHSVar and
5465/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00005466static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005467 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
5468 const VarDecl *RHSVar,
5469 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
5470 const Expr *, const Expr *)> &RedOpGen,
5471 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
5472 const Expr *UpExpr = nullptr) {
5473 // Perform element-by-element initialization.
5474 QualType ElementTy;
5475 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
5476 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
5477
5478 // Drill down to the base element type on both arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005479 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
5480 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005481
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005482 llvm::Value *RHSBegin = RHSAddr.getPointer();
5483 llvm::Value *LHSBegin = LHSAddr.getPointer();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005484 // Cast from pointer to array type to pointer to single element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005485 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005486 // The basic structure here is a while-do loop.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005487 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
5488 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
5489 llvm::Value *IsEmpty =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005490 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
5491 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
5492
5493 // Enter the loop body, making that address the current address.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005494 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005495 CGF.EmitBlock(BodyBB);
5496
5497 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
5498
5499 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
5500 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
5501 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
5502 Address RHSElementCurrent =
5503 Address(RHSElementPHI,
5504 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5505
5506 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
5507 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
5508 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
5509 Address LHSElementCurrent =
5510 Address(LHSElementPHI,
5511 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5512
5513 // Emit copy.
5514 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005515 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; });
5516 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005517 Scope.Privatize();
5518 RedOpGen(CGF, XExpr, EExpr, UpExpr);
5519 Scope.ForceCleanup();
5520
5521 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005522 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005523 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005524 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005525 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
5526 // Check whether we've reached the end.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005527 llvm::Value *Done =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005528 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
5529 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
5530 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
5531 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
5532
5533 // Done.
5534 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
5535}
5536
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005537/// Emit reduction combiner. If the combiner is a simple expression emit it as
5538/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
5539/// UDR combiner function.
5540static void emitReductionCombiner(CodeGenFunction &CGF,
5541 const Expr *ReductionOp) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005542 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
5543 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
5544 if (const auto *DRE =
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005545 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005546 if (const auto *DRD =
5547 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005548 std::pair<llvm::Function *, llvm::Function *> Reduction =
5549 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
5550 RValue Func = RValue::get(Reduction.first);
5551 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
5552 CGF.EmitIgnoredExpr(ReductionOp);
5553 return;
5554 }
5555 CGF.EmitIgnoredExpr(ReductionOp);
5556}
5557
James Y Knight9871db02019-02-05 16:42:33 +00005558llvm::Function *CGOpenMPRuntime::emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005559 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates,
5560 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
5561 ArrayRef<const Expr *> ReductionOps) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005562 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005563
5564 // void reduction_func(void *LHSArg, void *RHSArg);
5565 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005566 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5567 ImplicitParamDecl::Other);
5568 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5569 ImplicitParamDecl::Other);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005570 Args.push_back(&LHSArg);
5571 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005572 const auto &CGFI =
5573 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00005574 std::string Name = getName({"omp", "reduction", "reduction_func"});
5575 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
5576 llvm::GlobalValue::InternalLinkage, Name,
5577 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00005578 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00005579 Fn->setDoesNotRecurse();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005580 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005581 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005582
5583 // Dst = (void*[n])(LHSArg);
5584 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00005585 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5586 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
5587 ArgsType), CGF.getPointerAlign());
5588 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5589 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
5590 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005591
5592 // ...
5593 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
5594 // ...
5595 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005596 auto IPriv = Privates.begin();
5597 unsigned Idx = 0;
5598 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005599 const auto *RHSVar =
5600 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
5601 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005602 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005603 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005604 const auto *LHSVar =
5605 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
5606 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005607 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005608 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005609 QualType PrivTy = (*IPriv)->getType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00005610 if (PrivTy->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005611 // Get array size and emit VLA type.
5612 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005613 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005614 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005615 const VariableArrayType *VLA =
5616 CGF.getContext().getAsVariableArrayType(PrivTy);
5617 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005618 CodeGenFunction::OpaqueValueMapping OpaqueMap(
Alexey Bataev1189bd02016-01-26 12:20:39 +00005619 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005620 CGF.EmitVariablyModifiedType(PrivTy);
5621 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005622 }
5623 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005624 IPriv = Privates.begin();
5625 auto ILHS = LHSExprs.begin();
5626 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005627 for (const Expr *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005628 if ((*IPriv)->getType()->isArrayType()) {
5629 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005630 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5631 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005632 EmitOMPAggregateReduction(
5633 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5634 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5635 emitReductionCombiner(CGF, E);
5636 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005637 } else {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005638 // Emit reduction for array subscript or single variable.
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005639 emitReductionCombiner(CGF, E);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005640 }
Richard Trieucc3949d2016-02-18 22:34:54 +00005641 ++IPriv;
5642 ++ILHS;
5643 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005644 }
5645 Scope.ForceCleanup();
5646 CGF.FinishFunction();
5647 return Fn;
5648}
5649
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005650void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF,
5651 const Expr *ReductionOp,
5652 const Expr *PrivateRef,
5653 const DeclRefExpr *LHS,
5654 const DeclRefExpr *RHS) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005655 if (PrivateRef->getType()->isArrayType()) {
5656 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005657 const auto *LHSVar = cast<VarDecl>(LHS->getDecl());
5658 const auto *RHSVar = cast<VarDecl>(RHS->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005659 EmitOMPAggregateReduction(
5660 CGF, PrivateRef->getType(), LHSVar, RHSVar,
5661 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5662 emitReductionCombiner(CGF, ReductionOp);
5663 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005664 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005665 // Emit reduction for array subscript or single variable.
5666 emitReductionCombiner(CGF, ReductionOp);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005667 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005668}
5669
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005670void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005671 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005672 ArrayRef<const Expr *> LHSExprs,
5673 ArrayRef<const Expr *> RHSExprs,
5674 ArrayRef<const Expr *> ReductionOps,
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005675 ReductionOptionsTy Options) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00005676 if (!CGF.HaveInsertPoint())
5677 return;
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005678
5679 bool WithNowait = Options.WithNowait;
5680 bool SimpleReduction = Options.SimpleReduction;
5681
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005682 // Next code should be emitted for reduction:
5683 //
5684 // static kmp_critical_name lock = { 0 };
5685 //
5686 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
5687 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
5688 // ...
5689 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
5690 // *(Type<n>-1*)rhs[<n>-1]);
5691 // }
5692 //
5693 // ...
5694 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
5695 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5696 // RedList, reduce_func, &<lock>)) {
5697 // case 1:
5698 // ...
5699 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5700 // ...
5701 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5702 // break;
5703 // case 2:
5704 // ...
5705 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5706 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00005707 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005708 // break;
5709 // default:;
5710 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005711 //
5712 // if SimpleReduction is true, only the next code is generated:
5713 // ...
5714 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5715 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005716
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005717 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005718
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005719 if (SimpleReduction) {
5720 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005721 auto IPriv = Privates.begin();
5722 auto ILHS = LHSExprs.begin();
5723 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005724 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005725 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5726 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005727 ++IPriv;
5728 ++ILHS;
5729 ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005730 }
5731 return;
5732 }
5733
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005734 // 1. Build a list of reduction variables.
5735 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005736 auto Size = RHSExprs.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005737 for (const Expr *E : Privates) {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005738 if (E->getType()->isVariablyModifiedType())
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005739 // Reserve place for array size.
5740 ++Size;
5741 }
5742 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005743 QualType ReductionArrayTy =
Richard Smith772e2662019-10-04 01:25:59 +00005744 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005745 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00005746 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005747 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005748 auto IPriv = Privates.begin();
5749 unsigned Idx = 0;
5750 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
James Y Knight751fe282019-02-09 22:22:28 +00005751 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
John McCall7f416cc2015-09-08 08:05:57 +00005752 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005753 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00005754 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
5755 Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005756 if ((*IPriv)->getType()->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005757 // Store array size.
5758 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005759 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005760 llvm::Value *Size = CGF.Builder.CreateIntCast(
5761 CGF.getVLASize(
5762 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
Sander de Smalen891af03a2018-02-03 13:55:59 +00005763 .NumElts,
Alexey Bataev1189bd02016-01-26 12:20:39 +00005764 CGF.SizeTy, /*isSigned=*/false);
5765 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
5766 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005767 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005768 }
5769
5770 // 2. Emit reduce_func().
James Y Knight9871db02019-02-05 16:42:33 +00005771 llvm::Function *ReductionFn = emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005772 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
5773 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005774
5775 // 3. Create static kmp_critical_name lock = { 0 };
Alexey Bataev18fa2322018-05-02 14:20:50 +00005776 std::string Name = getName({"reduction"});
5777 llvm::Value *Lock = getCriticalRegionLock(Name);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005778
5779 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5780 // RedList, reduce_func, &<lock>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005781 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
5782 llvm::Value *ThreadId = getThreadID(CGF, Loc);
5783 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
5784 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Samuel Antao4c8035b2016-12-12 18:00:20 +00005785 ReductionList.getPointer(), CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005786 llvm::Value *Args[] = {
5787 IdentTLoc, // ident_t *<loc>
5788 ThreadId, // i32 <gtid>
5789 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
5790 ReductionArrayTySize, // size_type sizeof(RedList)
5791 RL, // void *RedList
5792 ReductionFn, // void (*) (void *, void *) <reduce_func>
5793 Lock // kmp_critical_name *&<lock>
5794 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005795 llvm::Value *Res = CGF.EmitRuntimeCall(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005796 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
5797 : OMPRTL__kmpc_reduce),
5798 Args);
5799
5800 // 5. Build switch(res)
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005801 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
5802 llvm::SwitchInst *SwInst =
5803 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005804
5805 // 6. Build case 1:
5806 // ...
5807 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5808 // ...
5809 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5810 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005811 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005812 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
5813 CGF.EmitBlock(Case1BB);
5814
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005815 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5816 llvm::Value *EndArgs[] = {
5817 IdentTLoc, // ident_t *<loc>
5818 ThreadId, // i32 <gtid>
5819 Lock // kmp_critical_name *&<lock>
5820 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005821 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5822 CodeGenFunction &CGF, PrePostActionTy &Action) {
5823 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005824 auto IPriv = Privates.begin();
5825 auto ILHS = LHSExprs.begin();
5826 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005827 for (const Expr *E : ReductionOps) {
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005828 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5829 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005830 ++IPriv;
5831 ++ILHS;
5832 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005833 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005834 };
5835 RegionCodeGenTy RCG(CodeGen);
5836 CommonActionTy Action(
5837 nullptr, llvm::None,
5838 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
5839 : OMPRTL__kmpc_end_reduce),
5840 EndArgs);
5841 RCG.setAction(Action);
5842 RCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005843
5844 CGF.EmitBranch(DefaultBB);
5845
5846 // 7. Build case 2:
5847 // ...
5848 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5849 // ...
5850 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005851 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005852 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
5853 CGF.EmitBlock(Case2BB);
5854
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005855 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
5856 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005857 auto ILHS = LHSExprs.begin();
5858 auto IRHS = RHSExprs.begin();
5859 auto IPriv = Privates.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005860 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005861 const Expr *XExpr = nullptr;
5862 const Expr *EExpr = nullptr;
5863 const Expr *UpExpr = nullptr;
5864 BinaryOperatorKind BO = BO_Comma;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005865 if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005866 if (BO->getOpcode() == BO_Assign) {
5867 XExpr = BO->getLHS();
5868 UpExpr = BO->getRHS();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005869 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005870 }
5871 // Try to emit update expression as a simple atomic.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005872 const Expr *RHSExpr = UpExpr;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005873 if (RHSExpr) {
5874 // Analyze RHS part of the whole expression.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005875 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005876 RHSExpr->IgnoreParenImpCasts())) {
5877 // If this is a conditional operator, analyze its condition for
5878 // min/max reduction operator.
5879 RHSExpr = ACO->getCond();
Alexey Bataev69a47792015-05-07 03:54:03 +00005880 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005881 if (const auto *BORHS =
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005882 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
5883 EExpr = BORHS->getRHS();
5884 BO = BORHS->getOpcode();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005885 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005886 }
5887 if (XExpr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005888 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005889 auto &&AtomicRedGen = [BO, VD,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005890 Loc](CodeGenFunction &CGF, const Expr *XExpr,
5891 const Expr *EExpr, const Expr *UpExpr) {
5892 LValue X = CGF.EmitLValue(XExpr);
5893 RValue E;
5894 if (EExpr)
5895 E = CGF.EmitAnyExpr(EExpr);
5896 CGF.EmitOMPAtomicSimpleUpdateExpr(
JF Bastien92f4ef12016-04-06 17:26:42 +00005897 X, E, BO, /*IsXLHSInRHSPart=*/true,
5898 llvm::AtomicOrdering::Monotonic, Loc,
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005899 [&CGF, UpExpr, VD, Loc](RValue XRValue) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005900 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5901 PrivateScope.addPrivate(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005902 VD, [&CGF, VD, XRValue, Loc]() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005903 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5904 CGF.emitOMPSimpleStore(
5905 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
5906 VD->getType().getNonReferenceType(), Loc);
5907 return LHSTemp;
5908 });
5909 (void)PrivateScope.Privatize();
5910 return CGF.EmitAnyExpr(UpExpr);
5911 });
5912 };
5913 if ((*IPriv)->getType()->isArrayType()) {
5914 // Emit atomic reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005915 const auto *RHSVar =
5916 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005917 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
5918 AtomicRedGen, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005919 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005920 // Emit atomic reduction for array subscript or single variable.
5921 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005922 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005923 } else {
5924 // Emit as a critical region.
5925 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
Alexey Bataev18fa2322018-05-02 14:20:50 +00005926 const Expr *, const Expr *) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005927 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev18fa2322018-05-02 14:20:50 +00005928 std::string Name = RT.getName({"atomic_reduction"});
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005929 RT.emitCriticalRegion(
Alexey Bataev18fa2322018-05-02 14:20:50 +00005930 CGF, Name,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005931 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
5932 Action.Enter(CGF);
5933 emitReductionCombiner(CGF, E);
5934 },
5935 Loc);
5936 };
5937 if ((*IPriv)->getType()->isArrayType()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005938 const auto *LHSVar =
5939 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5940 const auto *RHSVar =
5941 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005942 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5943 CritRedGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005944 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005945 CritRedGen(CGF, nullptr, nullptr, nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005946 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005947 }
Richard Trieucc3949d2016-02-18 22:34:54 +00005948 ++ILHS;
5949 ++IRHS;
5950 ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005951 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005952 };
5953 RegionCodeGenTy AtomicRCG(AtomicCodeGen);
5954 if (!WithNowait) {
5955 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
5956 llvm::Value *EndArgs[] = {
5957 IdentTLoc, // ident_t *<loc>
5958 ThreadId, // i32 <gtid>
5959 Lock // kmp_critical_name *&<lock>
5960 };
5961 CommonActionTy Action(nullptr, llvm::None,
5962 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
5963 EndArgs);
5964 AtomicRCG.setAction(Action);
5965 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005966 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005967 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005968 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005969
5970 CGF.EmitBranch(DefaultBB);
5971 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
5972}
5973
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005974/// Generates unique name for artificial threadprivate variables.
Alexey Bataev1c44e152018-03-06 18:59:43 +00005975/// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>"
5976static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix,
5977 const Expr *Ref) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005978 SmallString<256> Buffer;
5979 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev1c44e152018-03-06 18:59:43 +00005980 const clang::DeclRefExpr *DE;
5981 const VarDecl *D = ::getBaseDecl(Ref, DE);
5982 if (!D)
5983 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl());
5984 D = D->getCanonicalDecl();
Alexey Bataev18fa2322018-05-02 14:20:50 +00005985 std::string Name = CGM.getOpenMPRuntime().getName(
5986 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)});
5987 Out << Prefix << Name << "_"
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005988 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005989 return Out.str();
5990}
5991
5992/// Emits reduction initializer function:
5993/// \code
5994/// void @.red_init(void* %arg) {
5995/// %0 = bitcast void* %arg to <type>*
5996/// store <type> <init>, <type>* %0
5997/// ret void
5998/// }
5999/// \endcode
6000static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM,
6001 SourceLocation Loc,
6002 ReductionCodeGen &RCG, unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006003 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006004 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006005 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6006 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006007 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006008 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006009 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006010 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006011 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006012 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006013 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006014 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006015 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006016 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006017 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006018 Address PrivateAddr = CGF.EmitLoadOfPointer(
6019 CGF.GetAddrOfLocalVar(&Param),
6020 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6021 llvm::Value *Size = nullptr;
6022 // If the size of the reduction item is non-constant, load it from global
6023 // threadprivate variable.
6024 if (RCG.getSizes(N).second) {
6025 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6026 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006027 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006028 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6029 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006030 }
6031 RCG.emitAggregateType(CGF, N, Size);
6032 LValue SharedLVal;
6033 // If initializer uses initializer from declare reduction construct, emit a
6034 // pointer to the address of the original reduction item (reuired by reduction
6035 // initializer)
6036 if (RCG.usesReductionInitializer(N)) {
6037 Address SharedAddr =
6038 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6039 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006040 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataev21dab122018-03-09 15:20:30 +00006041 SharedAddr = CGF.EmitLoadOfPointer(
6042 SharedAddr,
6043 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006044 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy);
6045 } else {
6046 SharedLVal = CGF.MakeNaturalAlignAddrLValue(
6047 llvm::ConstantPointerNull::get(CGM.VoidPtrTy),
6048 CGM.getContext().VoidPtrTy);
6049 }
6050 // Emit the initializer:
6051 // %0 = bitcast void* %arg to <type>*
6052 // store <type> <init>, <type>* %0
6053 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal,
6054 [](CodeGenFunction &) { return false; });
6055 CGF.FinishFunction();
6056 return Fn;
6057}
6058
6059/// Emits reduction combiner function:
6060/// \code
6061/// void @.red_comb(void* %arg0, void* %arg1) {
6062/// %lhs = bitcast void* %arg0 to <type>*
6063/// %rhs = bitcast void* %arg1 to <type>*
6064/// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs)
6065/// store <type> %2, <type>* %lhs
6066/// ret void
6067/// }
6068/// \endcode
6069static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM,
6070 SourceLocation Loc,
6071 ReductionCodeGen &RCG, unsigned N,
6072 const Expr *ReductionOp,
6073 const Expr *LHS, const Expr *RHS,
6074 const Expr *PrivateRef) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006075 ASTContext &C = CGM.getContext();
6076 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl());
6077 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006078 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006079 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
6080 C.VoidPtrTy, ImplicitParamDecl::Other);
6081 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6082 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006083 Args.emplace_back(&ParamInOut);
6084 Args.emplace_back(&ParamIn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006085 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006086 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006087 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006088 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006089 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006090 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006091 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006092 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006093 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006094 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006095 llvm::Value *Size = nullptr;
6096 // If the size of the reduction item is non-constant, load it from global
6097 // threadprivate variable.
6098 if (RCG.getSizes(N).second) {
6099 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6100 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006101 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006102 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6103 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006104 }
6105 RCG.emitAggregateType(CGF, N, Size);
6106 // Remap lhs and rhs variables to the addresses of the function arguments.
6107 // %lhs = bitcast void* %arg0 to <type>*
6108 // %rhs = bitcast void* %arg1 to <type>*
6109 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006110 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006111 // Pull out the pointer to the variable.
6112 Address PtrAddr = CGF.EmitLoadOfPointer(
6113 CGF.GetAddrOfLocalVar(&ParamInOut),
6114 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6115 return CGF.Builder.CreateElementBitCast(
6116 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType()));
6117 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006118 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006119 // Pull out the pointer to the variable.
6120 Address PtrAddr = CGF.EmitLoadOfPointer(
6121 CGF.GetAddrOfLocalVar(&ParamIn),
6122 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6123 return CGF.Builder.CreateElementBitCast(
6124 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType()));
6125 });
6126 PrivateScope.Privatize();
6127 // Emit the combiner body:
6128 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs)
6129 // store <type> %2, <type>* %lhs
6130 CGM.getOpenMPRuntime().emitSingleReductionCombiner(
6131 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS),
6132 cast<DeclRefExpr>(RHS));
6133 CGF.FinishFunction();
6134 return Fn;
6135}
6136
6137/// Emits reduction finalizer function:
6138/// \code
6139/// void @.red_fini(void* %arg) {
6140/// %0 = bitcast void* %arg to <type>*
6141/// <destroy>(<type>* %0)
6142/// ret void
6143/// }
6144/// \endcode
6145static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM,
6146 SourceLocation Loc,
6147 ReductionCodeGen &RCG, unsigned N) {
6148 if (!RCG.needCleanups(N))
6149 return nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006150 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006151 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006152 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6153 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006154 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006155 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006156 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006157 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006158 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006159 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006160 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006161 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006162 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006163 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006164 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006165 Address PrivateAddr = CGF.EmitLoadOfPointer(
6166 CGF.GetAddrOfLocalVar(&Param),
6167 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6168 llvm::Value *Size = nullptr;
6169 // If the size of the reduction item is non-constant, load it from global
6170 // threadprivate variable.
6171 if (RCG.getSizes(N).second) {
6172 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6173 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006174 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006175 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6176 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006177 }
6178 RCG.emitAggregateType(CGF, N, Size);
6179 // Emit the finalizer body:
6180 // <destroy>(<type>* %0)
6181 RCG.emitCleanups(CGF, N, PrivateAddr);
6182 CGF.FinishFunction();
6183 return Fn;
6184}
6185
6186llvm::Value *CGOpenMPRuntime::emitTaskReductionInit(
6187 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
6188 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
6189 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty())
6190 return nullptr;
6191
6192 // Build typedef struct:
6193 // kmp_task_red_input {
6194 // void *reduce_shar; // shared reduction item
6195 // size_t reduce_size; // size of data item
6196 // void *reduce_init; // data initialization routine
6197 // void *reduce_fini; // data finalization routine
6198 // void *reduce_comb; // data combiner routine
6199 // kmp_task_red_flags_t flags; // flags for additional info from compiler
6200 // } kmp_task_red_input_t;
6201 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006202 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t");
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006203 RD->startDefinition();
6204 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6205 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType());
6206 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6207 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6208 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6209 const FieldDecl *FlagsFD = addFieldToRecordDecl(
6210 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false));
6211 RD->completeDefinition();
6212 QualType RDType = C.getRecordType(RD);
6213 unsigned Size = Data.ReductionVars.size();
6214 llvm::APInt ArraySize(/*numBits=*/64, Size);
6215 QualType ArrayRDType = C.getConstantArrayType(
Richard Smith772e2662019-10-04 01:25:59 +00006216 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006217 // kmp_task_red_input_t .rd_input.[Size];
6218 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input.");
6219 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies,
6220 Data.ReductionOps);
6221 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) {
6222 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt];
6223 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0),
6224 llvm::ConstantInt::get(CGM.SizeTy, Cnt)};
6225 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP(
6226 TaskRedInput.getPointer(), Idxs,
6227 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc,
6228 ".rd_input.gep.");
6229 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType);
6230 // ElemLVal.reduce_shar = &Shareds[Cnt];
6231 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD);
6232 RCG.emitSharedLValue(CGF, Cnt);
6233 llvm::Value *CastedShared =
6234 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer());
6235 CGF.EmitStoreOfScalar(CastedShared, SharedLVal);
6236 RCG.emitAggregateType(CGF, Cnt);
6237 llvm::Value *SizeValInChars;
6238 llvm::Value *SizeVal;
6239 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt);
6240 // We use delayed creation/initialization for VLAs, array sections and
6241 // custom reduction initializations. It is required because runtime does not
6242 // provide the way to pass the sizes of VLAs/array sections to
6243 // initializer/combiner/finalizer functions and does not pass the pointer to
6244 // original reduction item to the initializer. Instead threadprivate global
6245 // variables are used to store these values and use them in the functions.
6246 bool DelayedCreation = !!SizeVal;
6247 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy,
6248 /*isSigned=*/false);
6249 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD);
6250 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal);
6251 // ElemLVal.reduce_init = init;
6252 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD);
6253 llvm::Value *InitAddr =
6254 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt));
6255 CGF.EmitStoreOfScalar(InitAddr, InitLVal);
6256 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt);
6257 // ElemLVal.reduce_fini = fini;
6258 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD);
6259 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt);
6260 llvm::Value *FiniAddr = Fini
6261 ? CGF.EmitCastToVoidPtr(Fini)
6262 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy);
6263 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal);
6264 // ElemLVal.reduce_comb = comb;
6265 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD);
6266 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction(
6267 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt],
6268 RHSExprs[Cnt], Data.ReductionCopies[Cnt]));
6269 CGF.EmitStoreOfScalar(CombAddr, CombLVal);
6270 // ElemLVal.flags = 0;
6271 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD);
6272 if (DelayedCreation) {
6273 CGF.EmitStoreOfScalar(
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006274 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006275 FlagsLVal);
6276 } else
6277 CGF.EmitNullInitialization(FlagsLVal.getAddress(), FlagsLVal.getType());
6278 }
6279 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void
6280 // *data);
6281 llvm::Value *Args[] = {
6282 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6283 /*isSigned=*/true),
6284 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true),
6285 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(),
6286 CGM.VoidPtrTy)};
6287 return CGF.EmitRuntimeCall(
6288 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args);
6289}
6290
6291void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
6292 SourceLocation Loc,
6293 ReductionCodeGen &RCG,
6294 unsigned N) {
6295 auto Sizes = RCG.getSizes(N);
6296 // Emit threadprivate global variable if the type is non-constant
6297 // (Sizes.second = nullptr).
6298 if (Sizes.second) {
6299 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy,
6300 /*isSigned=*/false);
6301 Address SizeAddr = getAddrOfArtificialThreadPrivate(
6302 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006303 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006304 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false);
6305 }
6306 // Store address of the original reduction item if custom initializer is used.
6307 if (RCG.usesReductionInitializer(N)) {
6308 Address SharedAddr = getAddrOfArtificialThreadPrivate(
6309 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006310 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006311 CGF.Builder.CreateStore(
6312 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6313 RCG.getSharedLValue(N).getPointer(), CGM.VoidPtrTy),
6314 SharedAddr, /*IsVolatile=*/false);
6315 }
6316}
6317
6318Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF,
6319 SourceLocation Loc,
6320 llvm::Value *ReductionsPtr,
6321 LValue SharedLVal) {
6322 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
6323 // *d);
6324 llvm::Value *Args[] = {
6325 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6326 /*isSigned=*/true),
6327 ReductionsPtr,
6328 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(SharedLVal.getPointer(),
6329 CGM.VoidPtrTy)};
6330 return Address(
6331 CGF.EmitRuntimeCall(
6332 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args),
6333 SharedLVal.getAlignment());
6334}
6335
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006336void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
6337 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006338 if (!CGF.HaveInsertPoint())
6339 return;
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006340 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
6341 // global_tid);
6342 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
6343 // Ignore return result until untied tasks are supported.
6344 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00006345 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
6346 Region->emitUntiedSwitch(CGF);
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006347}
6348
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006349void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006350 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00006351 const RegionCodeGenTy &CodeGen,
6352 bool HasCancel) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006353 if (!CGF.HaveInsertPoint())
6354 return;
Alexey Bataev25e5b442015-09-15 12:52:43 +00006355 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006356 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00006357}
6358
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006359namespace {
6360enum RTCancelKind {
6361 CancelNoreq = 0,
6362 CancelParallel = 1,
6363 CancelLoop = 2,
6364 CancelSections = 3,
6365 CancelTaskgroup = 4
6366};
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00006367} // anonymous namespace
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006368
6369static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
6370 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00006371 if (CancelRegion == OMPD_parallel)
6372 CancelKind = CancelParallel;
6373 else if (CancelRegion == OMPD_for)
6374 CancelKind = CancelLoop;
6375 else if (CancelRegion == OMPD_sections)
6376 CancelKind = CancelSections;
6377 else {
6378 assert(CancelRegion == OMPD_taskgroup);
6379 CancelKind = CancelTaskgroup;
6380 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006381 return CancelKind;
6382}
6383
6384void CGOpenMPRuntime::emitCancellationPointCall(
6385 CodeGenFunction &CGF, SourceLocation Loc,
6386 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006387 if (!CGF.HaveInsertPoint())
6388 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006389 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
6390 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006391 if (auto *OMPRegionInfo =
6392 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Jonas Hahnfeldb07931f2017-02-17 18:32:58 +00006393 // For 'cancellation point taskgroup', the task region info may not have a
6394 // cancel. This may instead happen in another adjacent task.
6395 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006396 llvm::Value *Args[] = {
6397 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
6398 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006399 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006400 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006401 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
6402 // if (__kmpc_cancellationpoint()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006403 // exit from construct;
6404 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006405 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6406 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6407 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006408 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6409 CGF.EmitBlock(ExitBB);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006410 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006411 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev25e5b442015-09-15 12:52:43 +00006412 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006413 CGF.EmitBranchThroughCleanup(CancelDest);
6414 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6415 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006416 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006417}
6418
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006419void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00006420 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006421 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006422 if (!CGF.HaveInsertPoint())
6423 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006424 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
6425 // kmp_int32 cncl_kind);
6426 if (auto *OMPRegionInfo =
6427 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006428 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF,
6429 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006430 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev87933c72015-09-18 08:07:34 +00006431 llvm::Value *Args[] = {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006432 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
Alexey Bataev87933c72015-09-18 08:07:34 +00006433 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
6434 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006435 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006436 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
Alexey Bataev87933c72015-09-18 08:07:34 +00006437 // if (__kmpc_cancel()) {
Alexey Bataev87933c72015-09-18 08:07:34 +00006438 // exit from construct;
6439 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006440 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6441 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6442 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev87933c72015-09-18 08:07:34 +00006443 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6444 CGF.EmitBlock(ExitBB);
Alexey Bataev87933c72015-09-18 08:07:34 +00006445 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006446 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev87933c72015-09-18 08:07:34 +00006447 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6448 CGF.EmitBranchThroughCleanup(CancelDest);
6449 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6450 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006451 if (IfCond) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006452 emitOMPIfClause(CGF, IfCond, ThenGen,
6453 [](CodeGenFunction &, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006454 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006455 RegionCodeGenTy ThenRCG(ThenGen);
6456 ThenRCG(CGF);
6457 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006458 }
6459}
Samuel Antaobed3c462015-10-02 16:14:20 +00006460
Samuel Antaoee8fb302016-01-06 13:42:12 +00006461void CGOpenMPRuntime::emitTargetOutlinedFunction(
6462 const OMPExecutableDirective &D, StringRef ParentName,
6463 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006464 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00006465 assert(!ParentName.empty() && "Invalid target region parent name!");
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00006466 HasEmittedTargetRegion = true;
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006467 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
6468 IsOffloadEntry, CodeGen);
6469}
6470
6471void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
6472 const OMPExecutableDirective &D, StringRef ParentName,
6473 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6474 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antao2de62b02016-02-13 23:35:10 +00006475 // Create a unique name for the entry function using the source location
6476 // information of the current target region. The name will be something like:
Samuel Antaoee8fb302016-01-06 13:42:12 +00006477 //
Samuel Antao2de62b02016-02-13 23:35:10 +00006478 // __omp_offloading_DD_FFFF_PP_lBB
Samuel Antaoee8fb302016-01-06 13:42:12 +00006479 //
6480 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
Samuel Antao2de62b02016-02-13 23:35:10 +00006481 // mangled name of the function that encloses the target region and BB is the
6482 // line number of the target region.
Samuel Antaoee8fb302016-01-06 13:42:12 +00006483
6484 unsigned DeviceID;
6485 unsigned FileID;
6486 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00006487 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00006488 Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006489 SmallString<64> EntryFnName;
6490 {
6491 llvm::raw_svector_ostream OS(EntryFnName);
Samuel Antao2de62b02016-02-13 23:35:10 +00006492 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
6493 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00006494 }
6495
Alexey Bataev475a7442018-01-12 19:39:11 +00006496 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006497
Samuel Antaobed3c462015-10-02 16:14:20 +00006498 CodeGenFunction CGF(CGM, true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006499 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
Samuel Antaobed3c462015-10-02 16:14:20 +00006500 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006501
Samuel Antao6d004262016-06-16 18:39:34 +00006502 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006503
6504 // If this target outline function is not an offload entry, we don't need to
6505 // register it.
6506 if (!IsOffloadEntry)
6507 return;
6508
6509 // The target region ID is used by the runtime library to identify the current
6510 // target region, so it only has to be unique and not necessarily point to
6511 // anything. It could be the pointer to the outlined function that implements
6512 // the target region, but we aren't using that so that the compiler doesn't
6513 // need to keep that, and could therefore inline the host function if proven
6514 // worthwhile during optimization. In the other hand, if emitting code for the
6515 // device, the ID has to be the function address so that it can retrieved from
6516 // the offloading entry and launched by the runtime library. We also mark the
6517 // outlined function to have external linkage in case we are emitting code for
6518 // the device, because these functions will be entry points to the device.
6519
6520 if (CGM.getLangOpts().OpenMPIsDevice) {
6521 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
Alexey Bataev9a700172018-05-08 14:16:57 +00006522 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Rafael Espindolacbca4872018-01-11 22:15:12 +00006523 OutlinedFn->setDSOLocal(false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006524 } else {
Alexey Bataevc15ea702018-05-09 18:02:37 +00006525 std::string Name = getName({EntryFnName, "region_id"});
Samuel Antaoee8fb302016-01-06 13:42:12 +00006526 OutlinedFnID = new llvm::GlobalVariable(
6527 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
Alexey Bataev9a700172018-05-08 14:16:57 +00006528 llvm::GlobalValue::WeakAnyLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006529 llvm::Constant::getNullValue(CGM.Int8Ty), Name);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006530 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00006531
6532 // Register the information for the entry associated with this target region.
6533 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
Samuel Antaof83efdb2017-01-05 16:02:49 +00006534 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID,
Alexey Bataev03f270c2018-03-30 18:31:07 +00006535 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion);
Samuel Antaobed3c462015-10-02 16:14:20 +00006536}
6537
Alexey Bataev5c427362019-04-10 19:11:33 +00006538/// Checks if the expression is constant or does not have non-trivial function
6539/// calls.
6540static bool isTrivial(ASTContext &Ctx, const Expr * E) {
6541 // We can skip constant expressions.
6542 // We can skip expressions with trivial calls or simple expressions.
6543 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) ||
6544 !E->hasNonTrivialCall(Ctx)) &&
6545 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true);
6546}
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006547
Alexey Bataev5c427362019-04-10 19:11:33 +00006548const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx,
6549 const Stmt *Body) {
6550 const Stmt *Child = Body->IgnoreContainers();
6551 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) {
6552 Child = nullptr;
6553 for (const Stmt *S : C->body()) {
6554 if (const auto *E = dyn_cast<Expr>(S)) {
6555 if (isTrivial(Ctx, E))
6556 continue;
6557 }
6558 // Some of the statements can be ignored.
6559 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) ||
6560 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S))
6561 continue;
6562 // Analyze declarations.
6563 if (const auto *DS = dyn_cast<DeclStmt>(S)) {
6564 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) {
6565 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6566 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6567 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6568 isa<UsingDirectiveDecl>(D) ||
6569 isa<OMPDeclareReductionDecl>(D) ||
6570 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6571 return true;
6572 const auto *VD = dyn_cast<VarDecl>(D);
6573 if (!VD)
6574 return false;
6575 return VD->isConstexpr() ||
6576 ((VD->getType().isTrivialType(Ctx) ||
6577 VD->getType()->isReferenceType()) &&
6578 (!VD->hasInit() || isTrivial(Ctx, VD->getInit())));
6579 }))
6580 continue;
6581 }
6582 // Found multiple children - cannot get the one child only.
6583 if (Child)
6584 return nullptr;
6585 Child = S;
6586 }
6587 if (Child)
6588 Child = Child->IgnoreContainers();
6589 }
6590 return Child;
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006591}
6592
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006593/// Emit the number of teams for a target directive. Inspect the num_teams
6594/// clause associated with a teams construct combined or closely nested
6595/// with the target directive.
6596///
6597/// Emit a team of size one for directives such as 'target parallel' that
6598/// have no associated teams construct.
6599///
6600/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006601static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006602emitNumTeamsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006603 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006604 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6605 "Clauses associated with the teams directive expected to be emitted "
6606 "only for the host!");
6607 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6608 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6609 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006610 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006611 switch (DirectiveKind) {
6612 case OMPD_target: {
6613 const auto *CS = D.getInnermostCapturedStmt();
6614 const auto *Body =
6615 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
6616 const Stmt *ChildStmt =
6617 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body);
6618 if (const auto *NestedDir =
6619 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6620 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) {
6621 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) {
6622 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6623 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6624 const Expr *NumTeams =
6625 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6626 llvm::Value *NumTeamsVal =
6627 CGF.EmitScalarExpr(NumTeams,
6628 /*IgnoreResultAssign*/ true);
6629 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006630 /*isSigned=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00006631 }
6632 return Bld.getInt32(0);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006633 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006634 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) ||
6635 isOpenMPSimdDirective(NestedDir->getDirectiveKind()))
6636 return Bld.getInt32(1);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006637 return Bld.getInt32(0);
6638 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006639 return nullptr;
Samuel Antaob68e2db2016-03-03 16:20:23 +00006640 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006641 case OMPD_target_teams:
6642 case OMPD_target_teams_distribute:
6643 case OMPD_target_teams_distribute_simd:
6644 case OMPD_target_teams_distribute_parallel_for:
6645 case OMPD_target_teams_distribute_parallel_for_simd: {
6646 if (D.hasClausesOfKind<OMPNumTeamsClause>()) {
6647 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF);
6648 const Expr *NumTeams =
6649 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6650 llvm::Value *NumTeamsVal =
6651 CGF.EmitScalarExpr(NumTeams,
6652 /*IgnoreResultAssign*/ true);
6653 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006654 /*isSigned=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00006655 }
6656 return Bld.getInt32(0);
6657 }
6658 case OMPD_target_parallel:
6659 case OMPD_target_parallel_for:
6660 case OMPD_target_parallel_for_simd:
6661 case OMPD_target_simd:
6662 return Bld.getInt32(1);
6663 case OMPD_parallel:
6664 case OMPD_for:
6665 case OMPD_parallel_for:
6666 case OMPD_parallel_sections:
6667 case OMPD_for_simd:
6668 case OMPD_parallel_for_simd:
6669 case OMPD_cancel:
6670 case OMPD_cancellation_point:
6671 case OMPD_ordered:
6672 case OMPD_threadprivate:
6673 case OMPD_allocate:
6674 case OMPD_task:
6675 case OMPD_simd:
6676 case OMPD_sections:
6677 case OMPD_section:
6678 case OMPD_single:
6679 case OMPD_master:
6680 case OMPD_critical:
6681 case OMPD_taskyield:
6682 case OMPD_barrier:
6683 case OMPD_taskwait:
6684 case OMPD_taskgroup:
6685 case OMPD_atomic:
6686 case OMPD_flush:
6687 case OMPD_teams:
6688 case OMPD_target_data:
6689 case OMPD_target_exit_data:
6690 case OMPD_target_enter_data:
6691 case OMPD_distribute:
6692 case OMPD_distribute_simd:
6693 case OMPD_distribute_parallel_for:
6694 case OMPD_distribute_parallel_for_simd:
6695 case OMPD_teams_distribute:
6696 case OMPD_teams_distribute_simd:
6697 case OMPD_teams_distribute_parallel_for:
6698 case OMPD_teams_distribute_parallel_for_simd:
6699 case OMPD_target_update:
6700 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00006701 case OMPD_declare_variant:
Alexey Bataev5c427362019-04-10 19:11:33 +00006702 case OMPD_declare_target:
6703 case OMPD_end_declare_target:
6704 case OMPD_declare_reduction:
6705 case OMPD_declare_mapper:
6706 case OMPD_taskloop:
6707 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00006708 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00006709 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00006710 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04006711 case OMPD_parallel_master_taskloop_simd:
Alexey Bataev5c427362019-04-10 19:11:33 +00006712 case OMPD_requires:
6713 case OMPD_unknown:
6714 break;
6715 }
6716 llvm_unreachable("Unexpected directive kind.");
6717}
Samuel Antaob68e2db2016-03-03 16:20:23 +00006718
Alexey Bataev5c427362019-04-10 19:11:33 +00006719static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS,
6720 llvm::Value *DefaultThreadLimitVal) {
6721 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6722 CGF.getContext(), CS->getCapturedStmt());
6723 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6724 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) {
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006725 llvm::Value *NumThreads = nullptr;
6726 llvm::Value *CondVal = nullptr;
6727 // Handle if clause. If if clause present, the number of threads is
6728 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6729 if (Dir->hasClausesOfKind<OMPIfClause>()) {
6730 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6731 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6732 const OMPIfClause *IfClause = nullptr;
6733 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) {
6734 if (C->getNameModifier() == OMPD_unknown ||
6735 C->getNameModifier() == OMPD_parallel) {
6736 IfClause = C;
6737 break;
6738 }
6739 }
6740 if (IfClause) {
6741 const Expr *Cond = IfClause->getCondition();
6742 bool Result;
6743 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6744 if (!Result)
6745 return CGF.Builder.getInt32(1);
6746 } else {
6747 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange());
6748 if (const auto *PreInit =
6749 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) {
6750 for (const auto *I : PreInit->decls()) {
6751 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6752 CGF.EmitVarDecl(cast<VarDecl>(*I));
6753 } else {
6754 CodeGenFunction::AutoVarEmission Emission =
6755 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6756 CGF.EmitAutoVarCleanups(Emission);
6757 }
6758 }
6759 }
6760 CondVal = CGF.EvaluateExprAsBool(Cond);
6761 }
6762 }
6763 }
6764 // Check the value of num_threads clause iff if clause was not specified
6765 // or is not evaluated to false.
Alexey Bataev5c427362019-04-10 19:11:33 +00006766 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) {
6767 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6768 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6769 const auto *NumThreadsClause =
6770 Dir->getSingleClause<OMPNumThreadsClause>();
6771 CodeGenFunction::LexicalScope Scope(
6772 CGF, NumThreadsClause->getNumThreads()->getSourceRange());
6773 if (const auto *PreInit =
6774 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6775 for (const auto *I : PreInit->decls()) {
6776 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6777 CGF.EmitVarDecl(cast<VarDecl>(*I));
6778 } else {
6779 CodeGenFunction::AutoVarEmission Emission =
6780 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6781 CGF.EmitAutoVarCleanups(Emission);
6782 }
6783 }
6784 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006785 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads());
Alexey Bataev5c427362019-04-10 19:11:33 +00006786 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006787 /*isSigned=*/false);
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006788 if (DefaultThreadLimitVal)
6789 NumThreads = CGF.Builder.CreateSelect(
6790 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads),
6791 DefaultThreadLimitVal, NumThreads);
6792 } else {
6793 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal
6794 : CGF.Builder.getInt32(0);
Alexey Bataev5c427362019-04-10 19:11:33 +00006795 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006796 // Process condition of the if clause.
6797 if (CondVal) {
6798 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads,
6799 CGF.Builder.getInt32(1));
6800 }
6801 return NumThreads;
Alexey Bataev5c427362019-04-10 19:11:33 +00006802 }
6803 if (isOpenMPSimdDirective(Dir->getDirectiveKind()))
6804 return CGF.Builder.getInt32(1);
6805 return DefaultThreadLimitVal;
6806 }
6807 return DefaultThreadLimitVal ? DefaultThreadLimitVal
6808 : CGF.Builder.getInt32(0);
Samuel Antaob68e2db2016-03-03 16:20:23 +00006809}
6810
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006811/// Emit the number of threads for a target directive. Inspect the
6812/// thread_limit clause associated with a teams construct combined or closely
6813/// nested with the target directive.
6814///
6815/// Emit the num_threads clause for directives such as 'target parallel' that
6816/// have no associated teams construct.
6817///
6818/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006819static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006820emitNumThreadsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006821 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006822 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6823 "Clauses associated with the teams directive expected to be emitted "
6824 "only for the host!");
6825 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6826 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6827 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006828 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006829 llvm::Value *ThreadLimitVal = nullptr;
6830 llvm::Value *NumThreadsVal = nullptr;
6831 switch (DirectiveKind) {
6832 case OMPD_target: {
6833 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6834 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6835 return NumThreads;
6836 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6837 CGF.getContext(), CS->getCapturedStmt());
6838 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6839 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) {
6840 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6841 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6842 const auto *ThreadLimitClause =
6843 Dir->getSingleClause<OMPThreadLimitClause>();
6844 CodeGenFunction::LexicalScope Scope(
6845 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange());
6846 if (const auto *PreInit =
6847 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6848 for (const auto *I : PreInit->decls()) {
6849 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6850 CGF.EmitVarDecl(cast<VarDecl>(*I));
6851 } else {
6852 CodeGenFunction::AutoVarEmission Emission =
6853 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6854 CGF.EmitAutoVarCleanups(Emission);
6855 }
6856 }
6857 }
6858 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6859 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6860 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006861 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006862 }
6863 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) &&
6864 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) {
6865 CS = Dir->getInnermostCapturedStmt();
6866 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6867 CGF.getContext(), CS->getCapturedStmt());
6868 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6869 }
6870 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) &&
6871 !isOpenMPSimdDirective(Dir->getDirectiveKind())) {
6872 CS = Dir->getInnermostCapturedStmt();
6873 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6874 return NumThreads;
6875 }
6876 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind()))
6877 return Bld.getInt32(1);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006878 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006879 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6880 }
6881 case OMPD_target_teams: {
6882 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6883 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6884 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6885 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6886 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6887 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006888 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006889 }
6890 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6891 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6892 return NumThreads;
6893 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6894 CGF.getContext(), CS->getCapturedStmt());
6895 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6896 if (Dir->getDirectiveKind() == OMPD_distribute) {
6897 CS = Dir->getInnermostCapturedStmt();
6898 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6899 return NumThreads;
6900 }
6901 }
6902 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6903 }
6904 case OMPD_target_teams_distribute:
6905 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6906 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6907 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6908 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6909 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6910 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006911 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006912 }
6913 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal);
6914 case OMPD_target_parallel:
6915 case OMPD_target_parallel_for:
6916 case OMPD_target_parallel_for_simd:
6917 case OMPD_target_teams_distribute_parallel_for:
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006918 case OMPD_target_teams_distribute_parallel_for_simd: {
6919 llvm::Value *CondVal = nullptr;
6920 // Handle if clause. If if clause present, the number of threads is
6921 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6922 if (D.hasClausesOfKind<OMPIfClause>()) {
6923 const OMPIfClause *IfClause = nullptr;
6924 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) {
6925 if (C->getNameModifier() == OMPD_unknown ||
6926 C->getNameModifier() == OMPD_parallel) {
6927 IfClause = C;
6928 break;
6929 }
6930 }
6931 if (IfClause) {
6932 const Expr *Cond = IfClause->getCondition();
6933 bool Result;
6934 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6935 if (!Result)
6936 return Bld.getInt32(1);
6937 } else {
6938 CodeGenFunction::RunCleanupsScope Scope(CGF);
6939 CondVal = CGF.EvaluateExprAsBool(Cond);
6940 }
6941 }
6942 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006943 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6944 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6945 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6946 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6947 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6948 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006949 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006950 }
6951 if (D.hasClausesOfKind<OMPNumThreadsClause>()) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006952 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
Alexey Bataev5c427362019-04-10 19:11:33 +00006953 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>();
6954 llvm::Value *NumThreads = CGF.EmitScalarExpr(
6955 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true);
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006956 NumThreadsVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006957 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006958 ThreadLimitVal = ThreadLimitVal
Alexey Bataev5c427362019-04-10 19:11:33 +00006959 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal,
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006960 ThreadLimitVal),
6961 NumThreadsVal, ThreadLimitVal)
6962 : NumThreadsVal;
Alexey Bataev50a1c782017-12-01 21:31:08 +00006963 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006964 if (!ThreadLimitVal)
6965 ThreadLimitVal = Bld.getInt32(0);
6966 if (CondVal)
6967 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1));
6968 return ThreadLimitVal;
6969 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006970 case OMPD_target_teams_distribute_simd:
6971 case OMPD_target_simd:
6972 return Bld.getInt32(1);
6973 case OMPD_parallel:
6974 case OMPD_for:
6975 case OMPD_parallel_for:
6976 case OMPD_parallel_sections:
6977 case OMPD_for_simd:
6978 case OMPD_parallel_for_simd:
6979 case OMPD_cancel:
6980 case OMPD_cancellation_point:
6981 case OMPD_ordered:
6982 case OMPD_threadprivate:
6983 case OMPD_allocate:
6984 case OMPD_task:
6985 case OMPD_simd:
6986 case OMPD_sections:
6987 case OMPD_section:
6988 case OMPD_single:
6989 case OMPD_master:
6990 case OMPD_critical:
6991 case OMPD_taskyield:
6992 case OMPD_barrier:
6993 case OMPD_taskwait:
6994 case OMPD_taskgroup:
6995 case OMPD_atomic:
6996 case OMPD_flush:
6997 case OMPD_teams:
6998 case OMPD_target_data:
6999 case OMPD_target_exit_data:
7000 case OMPD_target_enter_data:
7001 case OMPD_distribute:
7002 case OMPD_distribute_simd:
7003 case OMPD_distribute_parallel_for:
7004 case OMPD_distribute_parallel_for_simd:
7005 case OMPD_teams_distribute:
7006 case OMPD_teams_distribute_simd:
7007 case OMPD_teams_distribute_parallel_for:
7008 case OMPD_teams_distribute_parallel_for_simd:
7009 case OMPD_target_update:
7010 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00007011 case OMPD_declare_variant:
Alexey Bataev5c427362019-04-10 19:11:33 +00007012 case OMPD_declare_target:
7013 case OMPD_end_declare_target:
7014 case OMPD_declare_reduction:
7015 case OMPD_declare_mapper:
7016 case OMPD_taskloop:
7017 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00007018 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00007019 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00007020 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04007021 case OMPD_parallel_master_taskloop_simd:
Alexey Bataev5c427362019-04-10 19:11:33 +00007022 case OMPD_requires:
7023 case OMPD_unknown:
7024 break;
Samuel Antaob68e2db2016-03-03 16:20:23 +00007025 }
Alexey Bataev5c427362019-04-10 19:11:33 +00007026 llvm_unreachable("Unsupported directive kind.");
Samuel Antaob68e2db2016-03-03 16:20:23 +00007027}
7028
Samuel Antao86ace552016-04-27 22:40:57 +00007029namespace {
Alexey Bataevb3638132018-07-19 16:34:13 +00007030LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
7031
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007032// Utility to handle information from clauses associated with a given
Samuel Antao86ace552016-04-27 22:40:57 +00007033// construct that use mappable expressions (e.g. 'map' clause, 'to' clause).
7034// It provides a convenient interface to obtain the information and generate
7035// code for that information.
7036class MappableExprsHandler {
7037public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007038 /// Values for bit flags used to specify the mapping type for
Samuel Antao86ace552016-04-27 22:40:57 +00007039 /// offloading.
Alexey Bataevb3638132018-07-19 16:34:13 +00007040 enum OpenMPOffloadMappingFlags : uint64_t {
7041 /// No flags
7042 OMP_MAP_NONE = 0x0,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007043 /// Allocate memory on the device and move data from host to device.
Samuel Antao86ace552016-04-27 22:40:57 +00007044 OMP_MAP_TO = 0x01,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007045 /// Allocate memory on the device and move data from device to host.
Samuel Antao86ace552016-04-27 22:40:57 +00007046 OMP_MAP_FROM = 0x02,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007047 /// Always perform the requested mapping action on the element, even
Samuel Antao86ace552016-04-27 22:40:57 +00007048 /// if it was already mapped before.
7049 OMP_MAP_ALWAYS = 0x04,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007050 /// Delete the element from the device environment, ignoring the
Samuel Antao86ace552016-04-27 22:40:57 +00007051 /// current reference count associated with the element.
Samuel Antao6782e942016-05-26 16:48:10 +00007052 OMP_MAP_DELETE = 0x08,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007053 /// The element being mapped is a pointer-pointee pair; both the
George Rokos065755d2017-11-07 18:27:04 +00007054 /// pointer and the pointee should be mapped.
7055 OMP_MAP_PTR_AND_OBJ = 0x10,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007056 /// This flags signals that the base address of an entry should be
George Rokos065755d2017-11-07 18:27:04 +00007057 /// passed to the target kernel as an argument.
7058 OMP_MAP_TARGET_PARAM = 0x20,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007059 /// Signal that the runtime library has to return the device pointer
George Rokos065755d2017-11-07 18:27:04 +00007060 /// in the current position for the data being mapped. Used when we have the
7061 /// use_device_ptr clause.
7062 OMP_MAP_RETURN_PARAM = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007063 /// This flag signals that the reference being passed is a pointer to
Samuel Antaod486f842016-05-26 16:53:38 +00007064 /// private data.
George Rokos065755d2017-11-07 18:27:04 +00007065 OMP_MAP_PRIVATE = 0x80,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007066 /// Pass the element to the device by value.
George Rokos065755d2017-11-07 18:27:04 +00007067 OMP_MAP_LITERAL = 0x100,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007068 /// Implicit map
7069 OMP_MAP_IMPLICIT = 0x200,
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007070 /// Close is a hint to the runtime to allocate memory close to
7071 /// the target device.
7072 OMP_MAP_CLOSE = 0x400,
Alexey Bataevb3638132018-07-19 16:34:13 +00007073 /// The 16 MSBs of the flags indicate whether the entry is member of some
7074 /// struct/class.
7075 OMP_MAP_MEMBER_OF = 0xffff000000000000,
7076 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF),
Samuel Antao86ace552016-04-27 22:40:57 +00007077 };
7078
Michael Krused47b9432019-08-05 18:43:21 +00007079 /// Get the offset of the OMP_MAP_MEMBER_OF field.
7080 static unsigned getFlagMemberOffset() {
7081 unsigned Offset = 0;
7082 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1);
7083 Remain = Remain >> 1)
7084 Offset++;
7085 return Offset;
7086 }
7087
Samuel Antaocc10b852016-07-28 14:23:26 +00007088 /// Class that associates information with a base pointer to be passed to the
7089 /// runtime library.
7090 class BasePointerInfo {
7091 /// The base pointer.
7092 llvm::Value *Ptr = nullptr;
7093 /// The base declaration that refers to this device pointer, or null if
7094 /// there is none.
7095 const ValueDecl *DevPtrDecl = nullptr;
7096
7097 public:
7098 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr)
7099 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {}
7100 llvm::Value *operator*() const { return Ptr; }
7101 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; }
7102 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; }
7103 };
7104
Alexey Bataevb3638132018-07-19 16:34:13 +00007105 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>;
7106 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>;
7107 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>;
7108
7109 /// Map between a struct and the its lowest & highest elements which have been
7110 /// mapped.
7111 /// [ValueDecl *] --> {LE(FieldIndex, Pointer),
7112 /// HE(FieldIndex, Pointer)}
7113 struct StructRangeInfoTy {
7114 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = {
7115 0, Address::invalid()};
7116 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = {
7117 0, Address::invalid()};
7118 Address Base = Address::invalid();
7119 };
Samuel Antao86ace552016-04-27 22:40:57 +00007120
7121private:
Alexey Bataevb3638132018-07-19 16:34:13 +00007122 /// Kind that defines how a device pointer has to be returned.
7123 struct MapInfo {
7124 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
7125 OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
Kelvin Lief579432018-12-18 22:18:41 +00007126 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataevb3638132018-07-19 16:34:13 +00007127 bool ReturnDevicePointer = false;
7128 bool IsImplicit = false;
7129
7130 MapInfo() = default;
7131 MapInfo(
7132 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Kelvin Lief579432018-12-18 22:18:41 +00007133 OpenMPMapClauseKind MapType,
7134 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007135 bool ReturnDevicePointer, bool IsImplicit)
Kelvin Lief579432018-12-18 22:18:41 +00007136 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
Alexey Bataevb3638132018-07-19 16:34:13 +00007137 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {}
7138 };
7139
7140 /// If use_device_ptr is used on a pointer which is a struct member and there
7141 /// is no map information about it, then emission of that entry is deferred
7142 /// until the whole struct has been processed.
7143 struct DeferredDevicePtrEntryTy {
7144 const Expr *IE = nullptr;
7145 const ValueDecl *VD = nullptr;
7146
7147 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD)
7148 : IE(IE), VD(VD) {}
7149 };
7150
Michael Krused47b9432019-08-05 18:43:21 +00007151 /// The target directive from where the mappable clauses were extracted. It
7152 /// is either a executable directive or a user-defined mapper directive.
7153 llvm::PointerUnion<const OMPExecutableDirective *,
7154 const OMPDeclareMapperDecl *>
7155 CurDir;
Samuel Antao86ace552016-04-27 22:40:57 +00007156
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007157 /// Function the directive is being generated for.
Samuel Antao86ace552016-04-27 22:40:57 +00007158 CodeGenFunction &CGF;
7159
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007160 /// Set of all first private variables in the current directive.
Alexey Bataevf288cf92019-06-27 18:53:07 +00007161 /// bool data is set to true if the variable is implicitly marked as
7162 /// firstprivate, false otherwise.
7163 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls;
Samuel Antaod486f842016-05-26 16:53:38 +00007164
Samuel Antao6890b092016-07-28 14:25:09 +00007165 /// Map between device pointer declarations and their expression components.
7166 /// The key value for declarations in 'this' is null.
7167 llvm::DenseMap<
7168 const ValueDecl *,
7169 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7170 DevPointersMap;
7171
Samuel Antao86ace552016-04-27 22:40:57 +00007172 llvm::Value *getExprTypeSize(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007173 QualType ExprTy = E->getType().getCanonicalType();
Samuel Antao86ace552016-04-27 22:40:57 +00007174
7175 // Reference types are ignored for mapping purposes.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007176 if (const auto *RefTy = ExprTy->getAs<ReferenceType>())
Samuel Antao86ace552016-04-27 22:40:57 +00007177 ExprTy = RefTy->getPointeeType().getCanonicalType();
7178
7179 // Given that an array section is considered a built-in type, we need to
7180 // do the calculation based on the length of the section instead of relying
7181 // on CGF.getTypeSize(E->getType()).
7182 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) {
7183 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType(
7184 OAE->getBase()->IgnoreParenImpCasts())
7185 .getCanonicalType();
7186
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007187 // If there is no length associated with the expression and lower bound is
7188 // not specified too, that means we are using the whole length of the
7189 // base.
7190 if (!OAE->getLength() && OAE->getColonLoc().isValid() &&
7191 !OAE->getLowerBound())
Samuel Antao86ace552016-04-27 22:40:57 +00007192 return CGF.getTypeSize(BaseTy);
7193
7194 llvm::Value *ElemSize;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007195 if (const auto *PTy = BaseTy->getAs<PointerType>()) {
Samuel Antao86ace552016-04-27 22:40:57 +00007196 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007197 } else {
7198 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr());
Samuel Antao86ace552016-04-27 22:40:57 +00007199 assert(ATy && "Expecting array type if not a pointer type.");
7200 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType());
7201 }
7202
7203 // If we don't have a length at this point, that is because we have an
7204 // array section with a single element.
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007205 if (!OAE->getLength() && OAE->getColonLoc().isInvalid())
Samuel Antao86ace552016-04-27 22:40:57 +00007206 return ElemSize;
7207
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007208 if (const Expr *LenExpr = OAE->getLength()) {
Michael Liaod838cf72019-10-02 00:22:45 +00007209 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr);
7210 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(),
7211 CGF.getContext().getSizeType(),
7212 LenExpr->getExprLoc());
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007213 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize);
7214 }
7215 assert(!OAE->getLength() && OAE->getColonLoc().isValid() &&
7216 OAE->getLowerBound() && "expected array_section[lb:].");
7217 // Size = sizetype - lb * elemtype;
7218 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy);
7219 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound());
7220 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(),
7221 CGF.getContext().getSizeType(),
7222 OAE->getLowerBound()->getExprLoc());
7223 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize);
7224 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal);
7225 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal);
7226 LengthVal = CGF.Builder.CreateSelect(
7227 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0));
7228 return LengthVal;
Samuel Antao86ace552016-04-27 22:40:57 +00007229 }
7230 return CGF.getTypeSize(ExprTy);
7231 }
7232
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007233 /// Return the corresponding bits for a given map clause modifier. Add
Samuel Antao86ace552016-04-27 22:40:57 +00007234 /// a flag marking the map as a pointer if requested. Add a flag marking the
Samuel Antao6782e942016-05-26 16:48:10 +00007235 /// map as the first one of a series of maps that relate to the same map
7236 /// expression.
Kelvin Lief579432018-12-18 22:18:41 +00007237 OpenMPOffloadMappingFlags getMapTypeBits(
7238 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
7239 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const {
Alexey Bataevb3638132018-07-19 16:34:13 +00007240 OpenMPOffloadMappingFlags Bits =
7241 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE;
Samuel Antao86ace552016-04-27 22:40:57 +00007242 switch (MapType) {
7243 case OMPC_MAP_alloc:
Samuel Antao6782e942016-05-26 16:48:10 +00007244 case OMPC_MAP_release:
7245 // alloc and release is the default behavior in the runtime library, i.e.
7246 // if we don't pass any bits alloc/release that is what the runtime is
7247 // going to do. Therefore, we don't need to signal anything for these two
7248 // type modifiers.
Samuel Antao86ace552016-04-27 22:40:57 +00007249 break;
7250 case OMPC_MAP_to:
Alexey Bataevb3638132018-07-19 16:34:13 +00007251 Bits |= OMP_MAP_TO;
Samuel Antao86ace552016-04-27 22:40:57 +00007252 break;
7253 case OMPC_MAP_from:
Alexey Bataevb3638132018-07-19 16:34:13 +00007254 Bits |= OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007255 break;
7256 case OMPC_MAP_tofrom:
Alexey Bataevb3638132018-07-19 16:34:13 +00007257 Bits |= OMP_MAP_TO | OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007258 break;
7259 case OMPC_MAP_delete:
Alexey Bataevb3638132018-07-19 16:34:13 +00007260 Bits |= OMP_MAP_DELETE;
Samuel Antao86ace552016-04-27 22:40:57 +00007261 break;
Alexey Bataevb3638132018-07-19 16:34:13 +00007262 case OMPC_MAP_unknown:
Samuel Antao86ace552016-04-27 22:40:57 +00007263 llvm_unreachable("Unexpected map type!");
Samuel Antao86ace552016-04-27 22:40:57 +00007264 }
7265 if (AddPtrFlag)
George Rokos065755d2017-11-07 18:27:04 +00007266 Bits |= OMP_MAP_PTR_AND_OBJ;
7267 if (AddIsTargetParamFlag)
7268 Bits |= OMP_MAP_TARGET_PARAM;
Kelvin Lief579432018-12-18 22:18:41 +00007269 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always)
7270 != MapModifiers.end())
Samuel Antao86ace552016-04-27 22:40:57 +00007271 Bits |= OMP_MAP_ALWAYS;
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007272 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close)
7273 != MapModifiers.end())
7274 Bits |= OMP_MAP_CLOSE;
Samuel Antao86ace552016-04-27 22:40:57 +00007275 return Bits;
7276 }
7277
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007278 /// Return true if the provided expression is a final array section. A
Samuel Antao86ace552016-04-27 22:40:57 +00007279 /// final array section, is one whose length can't be proved to be one.
7280 bool isFinalArraySectionExpression(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007281 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
Samuel Antao86ace552016-04-27 22:40:57 +00007282
7283 // It is not an array section and therefore not a unity-size one.
7284 if (!OASE)
7285 return false;
7286
7287 // An array section with no colon always refer to a single element.
7288 if (OASE->getColonLoc().isInvalid())
7289 return false;
7290
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007291 const Expr *Length = OASE->getLength();
Samuel Antao86ace552016-04-27 22:40:57 +00007292
7293 // If we don't have a length we have to check if the array has size 1
7294 // for this dimension. Also, we should always expect a length if the
7295 // base type is pointer.
7296 if (!Length) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007297 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType(
7298 OASE->getBase()->IgnoreParenImpCasts())
7299 .getCanonicalType();
7300 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
Samuel Antao86ace552016-04-27 22:40:57 +00007301 return ATy->getSize().getSExtValue() != 1;
7302 // If we don't have a constant dimension length, we have to consider
7303 // the current section as having any size, so it is not necessarily
7304 // unitary. If it happen to be unity size, that's user fault.
7305 return true;
7306 }
7307
7308 // Check if the length evaluates to 1.
Fangrui Song407659a2018-11-30 23:41:18 +00007309 Expr::EvalResult Result;
7310 if (!Length->EvaluateAsInt(Result, CGF.getContext()))
Samuel Antao86ace552016-04-27 22:40:57 +00007311 return true; // Can have more that size 1.
7312
Fangrui Song407659a2018-11-30 23:41:18 +00007313 llvm::APSInt ConstLength = Result.Val.getInt();
Samuel Antao86ace552016-04-27 22:40:57 +00007314 return ConstLength.getSExtValue() != 1;
7315 }
7316
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007317 /// Generate the base pointers, section pointers, sizes and map type
Samuel Antao86ace552016-04-27 22:40:57 +00007318 /// bits for the provided map type, map modifier, and expression components.
7319 /// \a IsFirstComponent should be set to true if the provided set of
7320 /// components is the first associated with a capture.
7321 void generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00007322 OpenMPMapClauseKind MapType,
7323 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Samuel Antao86ace552016-04-27 22:40:57 +00007324 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Samuel Antaocc10b852016-07-28 14:23:26 +00007325 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007326 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
Alexey Bataevb3638132018-07-19 16:34:13 +00007327 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007328 bool IsImplicit,
7329 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7330 OverlappedElements = llvm::None) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007331 // The following summarizes what has to be generated for each map and the
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00007332 // types below. The generated information is expressed in this order:
Samuel Antao86ace552016-04-27 22:40:57 +00007333 // base pointer, section pointer, size, flags
7334 // (to add to the ones that come from the map type and modifier).
7335 //
7336 // double d;
7337 // int i[100];
7338 // float *p;
7339 //
7340 // struct S1 {
7341 // int i;
7342 // float f[50];
7343 // }
7344 // struct S2 {
7345 // int i;
7346 // float f[50];
7347 // S1 s;
7348 // double *p;
7349 // struct S2 *ps;
7350 // }
7351 // S2 s;
7352 // S2 *ps;
7353 //
7354 // map(d)
Alexey Bataevb3638132018-07-19 16:34:13 +00007355 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007356 //
7357 // map(i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007358 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007359 //
7360 // map(i[1:23])
Alexey Bataevb3638132018-07-19 16:34:13 +00007361 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007362 //
7363 // map(p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007364 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007365 //
7366 // map(p[1:24])
Alexey Bataevb3638132018-07-19 16:34:13 +00007367 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007368 //
7369 // map(s)
Alexey Bataevb3638132018-07-19 16:34:13 +00007370 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007371 //
7372 // map(s.i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007373 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007374 //
7375 // map(s.s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007376 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007377 //
7378 // map(s.p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007379 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007380 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007381 // map(to: s.p[:22])
7382 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*)
7383 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**)
7384 // &(s.p), &(s.p[0]), 22*sizeof(double),
7385 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***)
7386 // (*) alloc space for struct members, only this is a target parameter
7387 // (**) map the pointer (nothing to be mapped in this example) (the compiler
7388 // optimizes this entry out, same in the examples below)
7389 // (***) map the pointee (map: to)
Samuel Antao86ace552016-04-27 22:40:57 +00007390 //
7391 // map(s.ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007392 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007393 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007394 // map(from: s.ps->s.i)
7395 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7396 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7397 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007398 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007399 // map(to: s.ps->ps)
7400 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7401 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7402 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007403 //
7404 // map(s.ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007405 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7406 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7407 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7408 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007409 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007410 // map(to: s.ps->ps->s.f[:22])
7411 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7412 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7413 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7414 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007415 //
7416 // map(ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007417 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007418 //
7419 // map(ps->i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007420 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007421 //
7422 // map(ps->s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007423 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007424 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007425 // map(from: ps->p)
7426 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007427 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007428 // map(to: ps->p[:22])
7429 // ps, &(ps->p), sizeof(double*), TARGET_PARAM
7430 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1)
7431 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007432 //
7433 // map(ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007434 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007435 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007436 // map(from: ps->ps->s.i)
7437 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7438 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7439 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007440 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007441 // map(from: ps->ps->ps)
7442 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7443 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7444 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007445 //
7446 // map(ps->ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007447 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7448 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7449 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7450 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007451 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007452 // map(to: ps->ps->ps->s.f[:22])
7453 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7454 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7455 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7456 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
7457 //
7458 // map(to: s.f[:22]) map(from: s.p[:33])
7459 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) +
7460 // sizeof(double*) (**), TARGET_PARAM
7461 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO
7462 // &s, &(s.p), sizeof(double*), MEMBER_OF(1)
7463 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7464 // (*) allocate contiguous space needed to fit all mapped members even if
7465 // we allocate space for members not mapped (in this example,
7466 // s.f[22..49] and s.s are not mapped, yet we must allocate space for
7467 // them as well because they fall between &s.f[0] and &s.p)
7468 //
7469 // map(from: s.f[:22]) map(to: ps->p[:33])
7470 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM
7471 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7472 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*)
7473 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO
7474 // (*) the struct this entry pertains to is the 2nd element in the list of
7475 // arguments, hence MEMBER_OF(2)
7476 //
7477 // map(from: s.f[:22], s.s) map(to: ps->p[:33])
7478 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM
7479 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM
7480 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM
7481 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7482 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*)
7483 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO
7484 // (*) the struct this entry pertains to is the 4th element in the list
7485 // of arguments, hence MEMBER_OF(4)
Samuel Antao86ace552016-04-27 22:40:57 +00007486
7487 // Track if the map information being generated is the first for a capture.
7488 bool IsCaptureFirstInfo = IsFirstComponentList;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007489 // When the variable is on a declare target link or in a to clause with
7490 // unified memory, a reference is needed to hold the host/device address
7491 // of the variable.
7492 bool RequiresReference = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007493
7494 // Scan the components from the base to the complete expression.
7495 auto CI = Components.rbegin();
7496 auto CE = Components.rend();
7497 auto I = CI;
7498
7499 // Track if the map information being generated is the first for a list of
7500 // components.
7501 bool IsExpressionFirstInfo = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00007502 Address BP = Address::invalid();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007503 const Expr *AssocExpr = I->getAssociatedExpression();
7504 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7505 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
Samuel Antao86ace552016-04-27 22:40:57 +00007506
Patrick Lystere13b1e32019-01-02 19:28:48 +00007507 if (isa<MemberExpr>(AssocExpr)) {
Samuel Antao86ace552016-04-27 22:40:57 +00007508 // The base is the 'this' pointer. The content of the pointer is going
7509 // to be the base of the field being mapped.
Alexey Bataevb3638132018-07-19 16:34:13 +00007510 BP = CGF.LoadCXXThisAddress();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007511 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7512 (OASE &&
7513 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
7514 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
Samuel Antao86ace552016-04-27 22:40:57 +00007515 } else {
7516 // The base is the reference to the variable.
7517 // BP = &Var.
Patrick Lystere13b1e32019-01-02 19:28:48 +00007518 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
Alexey Bataev92327c52018-03-26 16:40:55 +00007519 if (const auto *VD =
7520 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7521 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007522 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7523 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7524 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
7525 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) {
7526 RequiresReference = true;
7527 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataev2c1dffe2018-04-16 20:34:41 +00007528 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007529 }
Alexey Bataev92327c52018-03-26 16:40:55 +00007530 }
Samuel Antao86ace552016-04-27 22:40:57 +00007531
7532 // If the variable is a pointer and is being dereferenced (i.e. is not
Nico Webera6916892016-06-10 18:53:04 +00007533 // the last component), the base has to be the pointer itself, not its
Samuel Antao403ffd42016-07-27 22:49:49 +00007534 // reference. References are ignored for mapping purposes.
7535 QualType Ty =
7536 I->getAssociatedDeclaration()->getType().getNonReferenceType();
7537 if (Ty->isAnyPointerType() && std::next(I) != CE) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007538 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
Samuel Antao86ace552016-04-27 22:40:57 +00007539
7540 // We do not need to generate individual map information for the
7541 // pointer, it can be associated with the combined storage.
7542 ++I;
7543 }
7544 }
7545
Alexey Bataevb3638132018-07-19 16:34:13 +00007546 // Track whether a component of the list should be marked as MEMBER_OF some
7547 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry
7548 // in a component list should be marked as MEMBER_OF, all subsequent entries
7549 // do not belong to the base struct. E.g.
7550 // struct S2 s;
7551 // s.ps->ps->ps->f[:]
7552 // (1) (2) (3) (4)
7553 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a
7554 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3)
7555 // is the pointee of ps(2) which is not member of struct s, so it should not
7556 // be marked as such (it is still PTR_AND_OBJ).
7557 // The variable is initialized to false so that PTR_AND_OBJ entries which
7558 // are not struct members are not considered (e.g. array of pointers to
7559 // data).
7560 bool ShouldBeMemberOf = false;
7561
7562 // Variable keeping track of whether or not we have encountered a component
7563 // in the component list which is a member expression. Useful when we have a
7564 // pointer or a final array section, in which case it is the previous
7565 // component in the list which tells us whether we have a member expression.
7566 // E.g. X.f[:]
7567 // While processing the final array section "[:]" it is "f" which tells us
7568 // whether we are dealing with a member of a declared struct.
7569 const MemberExpr *EncounteredME = nullptr;
7570
Samuel Antao86ace552016-04-27 22:40:57 +00007571 for (; I != CE; ++I) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007572 // If the current component is member of a struct (parent struct) mark it.
7573 if (!EncounteredME) {
7574 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7575 // If we encounter a PTR_AND_OBJ entry from now on it should be marked
7576 // as MEMBER_OF the parent struct.
7577 if (EncounteredME)
7578 ShouldBeMemberOf = true;
7579 }
7580
Samuel Antao86ace552016-04-27 22:40:57 +00007581 auto Next = std::next(I);
7582
7583 // We need to generate the addresses and sizes if this is the last
7584 // component, if the component is a pointer or if it is an array section
7585 // whose length can't be proved to be one. If this is a pointer, it
7586 // becomes the base address for the following components.
7587
7588 // A final array section, is one whose length can't be proved to be one.
7589 bool IsFinalArraySection =
7590 isFinalArraySectionExpression(I->getAssociatedExpression());
7591
7592 // Get information on whether the element is a pointer. Have to do a
7593 // special treatment for array sections given that they are built-in
7594 // types.
7595 const auto *OASE =
7596 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression());
7597 bool IsPointer =
Alexey Bataevb3638132018-07-19 16:34:13 +00007598 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE)
7599 .getCanonicalType()
7600 ->isAnyPointerType()) ||
Samuel Antao86ace552016-04-27 22:40:57 +00007601 I->getAssociatedExpression()->getType()->isAnyPointerType();
7602
7603 if (Next == CE || IsPointer || IsFinalArraySection) {
Samuel Antao86ace552016-04-27 22:40:57 +00007604 // If this is not the last component, we expect the pointer to be
7605 // associated with an array expression or member expression.
7606 assert((Next == CE ||
7607 isa<MemberExpr>(Next->getAssociatedExpression()) ||
7608 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||
7609 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) &&
7610 "Unexpected expression");
7611
Alexey Bataevb3638132018-07-19 16:34:13 +00007612 Address LB =
7613 CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getAddress();
Samuel Antao86ace552016-04-27 22:40:57 +00007614
Alexey Bataevb3638132018-07-19 16:34:13 +00007615 // If this component is a pointer inside the base struct then we don't
7616 // need to create any entry for it - it will be combined with the object
7617 // it is pointing to into a single PTR_AND_OBJ entry.
7618 bool IsMemberPointer =
7619 IsPointer && EncounteredME &&
7620 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) ==
7621 EncounteredME);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007622 if (!OverlappedElements.empty()) {
7623 // Handle base element with the info for overlapped elements.
7624 assert(!PartialStruct.Base.isValid() && "The base element is set.");
7625 assert(Next == CE &&
7626 "Expected last element for the overlapped elements.");
7627 assert(!IsPointer &&
7628 "Unexpected base element with the pointer type.");
7629 // Mark the whole struct as the struct that requires allocation on the
7630 // device.
7631 PartialStruct.LowestElem = {0, LB};
7632 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(
7633 I->getAssociatedExpression()->getType());
7634 Address HB = CGF.Builder.CreateConstGEP(
7635 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB,
7636 CGF.VoidPtrTy),
James Y Knight751fe282019-02-09 22:22:28 +00007637 TypeSize.getQuantity() - 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007638 PartialStruct.HighestElem = {
7639 std::numeric_limits<decltype(
7640 PartialStruct.HighestElem.first)>::max(),
7641 HB};
7642 PartialStruct.Base = BP;
7643 // Emit data for non-overlapped data.
7644 OpenMPOffloadMappingFlags Flags =
7645 OMP_MAP_MEMBER_OF |
Kelvin Lief579432018-12-18 22:18:41 +00007646 getMapTypeBits(MapType, MapModifiers, IsImplicit,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007647 /*AddPtrFlag=*/false,
7648 /*AddIsTargetParamFlag=*/false);
7649 LB = BP;
7650 llvm::Value *Size = nullptr;
7651 // Do bitcopy of all non-overlapped structure elements.
7652 for (OMPClauseMappableExprCommon::MappableExprComponentListRef
7653 Component : OverlappedElements) {
7654 Address ComponentLB = Address::invalid();
7655 for (const OMPClauseMappableExprCommon::MappableComponent &MC :
7656 Component) {
7657 if (MC.getAssociatedDeclaration()) {
7658 ComponentLB =
7659 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
7660 .getAddress();
7661 Size = CGF.Builder.CreatePtrDiff(
7662 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()),
7663 CGF.EmitCastToVoidPtr(LB.getPointer()));
7664 break;
7665 }
7666 }
7667 BasePointers.push_back(BP.getPointer());
7668 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007669 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty,
7670 /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007671 Types.push_back(Flags);
James Y Knight751fe282019-02-09 22:22:28 +00007672 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007673 }
7674 BasePointers.push_back(BP.getPointer());
7675 Pointers.push_back(LB.getPointer());
7676 Size = CGF.Builder.CreatePtrDiff(
7677 CGF.EmitCastToVoidPtr(
James Y Knight751fe282019-02-09 22:22:28 +00007678 CGF.Builder.CreateConstGEP(HB, 1).getPointer()),
Alexey Bataeve82445f2018-09-20 13:54:02 +00007679 CGF.EmitCastToVoidPtr(LB.getPointer()));
Alexey Bataeva90fc662019-06-25 16:00:43 +00007680 Sizes.push_back(
7681 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007682 Types.push_back(Flags);
7683 break;
7684 }
7685 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
Alexey Bataevb3638132018-07-19 16:34:13 +00007686 if (!IsMemberPointer) {
7687 BasePointers.push_back(BP.getPointer());
7688 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007689 Sizes.push_back(
7690 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Samuel Antao03a3cec2016-07-27 22:52:16 +00007691
Alexey Bataevb3638132018-07-19 16:34:13 +00007692 // We need to add a pointer flag for each map that comes from the
7693 // same expression except for the first one. We also need to signal
7694 // this map is the first one that relates with the current capture
7695 // (there is a set of entries for each capture).
7696 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
Kelvin Lief579432018-12-18 22:18:41 +00007697 MapType, MapModifiers, IsImplicit,
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007698 !IsExpressionFirstInfo || RequiresReference,
7699 IsCaptureFirstInfo && !RequiresReference);
Alexey Bataevb3638132018-07-19 16:34:13 +00007700
7701 if (!IsExpressionFirstInfo) {
7702 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007703 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags.
Alexey Bataevb3638132018-07-19 16:34:13 +00007704 if (IsPointer)
7705 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS |
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007706 OMP_MAP_DELETE | OMP_MAP_CLOSE);
Alexey Bataevb3638132018-07-19 16:34:13 +00007707
7708 if (ShouldBeMemberOf) {
7709 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag
7710 // should be later updated with the correct value of MEMBER_OF.
7711 Flags |= OMP_MAP_MEMBER_OF;
7712 // From now on, all subsequent PTR_AND_OBJ entries should not be
7713 // marked as MEMBER_OF.
7714 ShouldBeMemberOf = false;
7715 }
7716 }
7717
7718 Types.push_back(Flags);
Samuel Antao03a3cec2016-07-27 22:52:16 +00007719 }
7720
Alexey Bataevb3638132018-07-19 16:34:13 +00007721 // If we have encountered a member expression so far, keep track of the
7722 // mapped member. If the parent is "*this", then the value declaration
7723 // is nullptr.
7724 if (EncounteredME) {
7725 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl());
7726 unsigned FieldIndex = FD->getFieldIndex();
Samuel Antao03a3cec2016-07-27 22:52:16 +00007727
Alexey Bataevb3638132018-07-19 16:34:13 +00007728 // Update info about the lowest and highest elements for this struct
7729 if (!PartialStruct.Base.isValid()) {
7730 PartialStruct.LowestElem = {FieldIndex, LB};
7731 PartialStruct.HighestElem = {FieldIndex, LB};
7732 PartialStruct.Base = BP;
7733 } else if (FieldIndex < PartialStruct.LowestElem.first) {
7734 PartialStruct.LowestElem = {FieldIndex, LB};
7735 } else if (FieldIndex > PartialStruct.HighestElem.first) {
7736 PartialStruct.HighestElem = {FieldIndex, LB};
7737 }
7738 }
Samuel Antao86ace552016-04-27 22:40:57 +00007739
7740 // If we have a final array section, we are done with this expression.
7741 if (IsFinalArraySection)
7742 break;
7743
7744 // The pointer becomes the base for the next element.
7745 if (Next != CE)
7746 BP = LB;
7747
7748 IsExpressionFirstInfo = false;
7749 IsCaptureFirstInfo = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007750 }
7751 }
7752 }
7753
Alexey Bataevb3638132018-07-19 16:34:13 +00007754 /// Return the adjusted map modifiers if the declaration a capture refers to
7755 /// appears in a first-private clause. This is expected to be used only with
7756 /// directives that start with 'target'.
7757 MappableExprsHandler::OpenMPOffloadMappingFlags
7758 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const {
7759 assert(Cap.capturesVariable() && "Expected capture by reference only!");
7760
7761 // A first private variable captured by reference will use only the
7762 // 'private ptr' and 'map to' flag. Return the right flags if the captured
7763 // declaration is known as first-private in this handler.
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007764 if (FirstPrivateDecls.count(Cap.getCapturedVar())) {
7765 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) &&
7766 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef)
7767 return MappableExprsHandler::OMP_MAP_ALWAYS |
7768 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataevc2b831f2019-04-02 16:03:40 +00007769 if (Cap.getCapturedVar()->getType()->isAnyPointerType())
7770 return MappableExprsHandler::OMP_MAP_TO |
7771 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ;
Alexey Bataevb3638132018-07-19 16:34:13 +00007772 return MappableExprsHandler::OMP_MAP_PRIVATE |
7773 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007774 }
Alexey Bataevb3638132018-07-19 16:34:13 +00007775 return MappableExprsHandler::OMP_MAP_TO |
7776 MappableExprsHandler::OMP_MAP_FROM;
7777 }
7778
7779 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) {
Michael Krused47b9432019-08-05 18:43:21 +00007780 // Rotate by getFlagMemberOffset() bits.
Alexey Bataevb3638132018-07-19 16:34:13 +00007781 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1)
Michael Krused47b9432019-08-05 18:43:21 +00007782 << getFlagMemberOffset());
Alexey Bataevb3638132018-07-19 16:34:13 +00007783 }
7784
7785 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags,
7786 OpenMPOffloadMappingFlags MemberOfFlag) {
7787 // If the entry is PTR_AND_OBJ but has not been marked with the special
7788 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be
7789 // marked as MEMBER_OF.
7790 if ((Flags & OMP_MAP_PTR_AND_OBJ) &&
7791 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF))
7792 return;
7793
7794 // Reset the placeholder value to prepare the flag for the assignment of the
7795 // proper MEMBER_OF value.
7796 Flags &= ~OMP_MAP_MEMBER_OF;
7797 Flags |= MemberOfFlag;
7798 }
7799
Alexey Bataeve82445f2018-09-20 13:54:02 +00007800 void getPlainLayout(const CXXRecordDecl *RD,
7801 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
7802 bool AsBase) const {
7803 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD);
7804
7805 llvm::StructType *St =
7806 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType();
7807
7808 unsigned NumElements = St->getNumElements();
7809 llvm::SmallVector<
7810 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
7811 RecordLayout(NumElements);
7812
7813 // Fill bases.
7814 for (const auto &I : RD->bases()) {
7815 if (I.isVirtual())
7816 continue;
7817 const auto *Base = I.getType()->getAsCXXRecordDecl();
7818 // Ignore empty bases.
7819 if (Base->isEmpty() || CGF.getContext()
7820 .getASTRecordLayout(Base)
7821 .getNonVirtualSize()
7822 .isZero())
7823 continue;
7824
7825 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
7826 RecordLayout[FieldIndex] = Base;
7827 }
7828 // Fill in virtual bases.
7829 for (const auto &I : RD->vbases()) {
7830 const auto *Base = I.getType()->getAsCXXRecordDecl();
7831 // Ignore empty bases.
7832 if (Base->isEmpty())
7833 continue;
7834 unsigned FieldIndex = RL.getVirtualBaseIndex(Base);
7835 if (RecordLayout[FieldIndex])
7836 continue;
7837 RecordLayout[FieldIndex] = Base;
7838 }
7839 // Fill in all the fields.
7840 assert(!RD->isUnion() && "Unexpected union.");
7841 for (const auto *Field : RD->fields()) {
7842 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
7843 // will fill in later.)
Richard Smith78b239e2019-06-20 20:44:45 +00007844 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) {
Alexey Bataeve82445f2018-09-20 13:54:02 +00007845 unsigned FieldIndex = RL.getLLVMFieldNo(Field);
7846 RecordLayout[FieldIndex] = Field;
7847 }
7848 }
7849 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
7850 &Data : RecordLayout) {
7851 if (Data.isNull())
7852 continue;
7853 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>())
7854 getPlainLayout(Base, Layout, /*AsBase=*/true);
7855 else
7856 Layout.push_back(Data.get<const FieldDecl *>());
7857 }
7858 }
7859
Alexey Bataevb3638132018-07-19 16:34:13 +00007860public:
7861 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
Michael Krused47b9432019-08-05 18:43:21 +00007862 : CurDir(&Dir), CGF(CGF) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007863 // Extract firstprivate clause information.
7864 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>())
7865 for (const auto *D : C->varlists())
Alexey Bataevf288cf92019-06-27 18:53:07 +00007866 FirstPrivateDecls.try_emplace(
7867 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit());
Alexey Bataevb3638132018-07-19 16:34:13 +00007868 // Extract device pointer clause information.
7869 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
7870 for (auto L : C->component_lists())
7871 DevPointersMap[L.first].push_back(L.second);
7872 }
7873
Michael Krused47b9432019-08-05 18:43:21 +00007874 /// Constructor for the declare mapper directive.
7875 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF)
7876 : CurDir(&Dir), CGF(CGF) {}
7877
Alexey Bataevb3638132018-07-19 16:34:13 +00007878 /// Generate code for the combined entry if we have a partially mapped struct
7879 /// and take care of the mapping flags of the arguments corresponding to
7880 /// individual struct members.
7881 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers,
7882 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7883 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes,
7884 const StructRangeInfoTy &PartialStruct) const {
7885 // Base is the base of the struct
7886 BasePointers.push_back(PartialStruct.Base.getPointer());
7887 // Pointer is the address of the lowest element
7888 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer();
7889 Pointers.push_back(LB);
7890 // Size is (addr of {highest+1} element) - (addr of lowest element)
7891 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer();
7892 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1);
7893 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy);
7894 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy);
7895 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00007896 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00007897 /*isSigned=*/false);
Alexey Bataevb3638132018-07-19 16:34:13 +00007898 Sizes.push_back(Size);
7899 // Map type is always TARGET_PARAM
7900 Types.push_back(OMP_MAP_TARGET_PARAM);
7901 // Remove TARGET_PARAM flag from the first element
7902 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM;
7903
7904 // All other current entries will be MEMBER_OF the combined entry
7905 // (except for PTR_AND_OBJ entries which do not have a placeholder value
7906 // 0xFFFF in the MEMBER_OF field).
7907 OpenMPOffloadMappingFlags MemberOfFlag =
7908 getMemberOfFlag(BasePointers.size() - 1);
7909 for (auto &M : CurTypes)
7910 setCorrectMemberOfFlag(M, MemberOfFlag);
7911 }
7912
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007913 /// Generate all the base pointers, section pointers, sizes and map
Samuel Antaocc10b852016-07-28 14:23:26 +00007914 /// types for the extracted mappable expressions. Also, for each item that
7915 /// relates with a device pointer, a pair of the relevant declaration and
7916 /// index where it occurs is appended to the device pointers info array.
7917 void generateAllInfo(MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007918 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7919 MapFlagsArrayTy &Types) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007920 // We have to process the component lists that relate with the same
7921 // declaration in a single chunk so that we can generate the map flags
7922 // correctly. Therefore, we organize all lists in a map.
Alexey Bataev5d1c3f62017-06-27 15:46:42 +00007923 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
Samuel Antao8d2d7302016-05-26 18:30:22 +00007924
7925 // Helper function to fill the information map for the different supported
7926 // clauses.
Samuel Antaocc10b852016-07-28 14:23:26 +00007927 auto &&InfoGen = [&Info](
7928 const ValueDecl *D,
7929 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
Kelvin Lief579432018-12-18 22:18:41 +00007930 OpenMPMapClauseKind MapType,
7931 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007932 bool ReturnDevicePointer, bool IsImplicit) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007933 const ValueDecl *VD =
7934 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
Kelvin Lief579432018-12-18 22:18:41 +00007935 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007936 IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00007937 };
Samuel Antao8d2d7302016-05-26 18:30:22 +00007938
Michael Krused47b9432019-08-05 18:43:21 +00007939 assert(CurDir.is<const OMPExecutableDirective *>() &&
7940 "Expect a executable directive");
7941 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
7942 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007943 for (const auto &L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007944 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(),
Alexey Bataevb3638132018-07-19 16:34:13 +00007945 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007946 }
Michael Krused47b9432019-08-05 18:43:21 +00007947 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007948 for (const auto &L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007949 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007950 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007951 }
Michael Krused47b9432019-08-05 18:43:21 +00007952 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007953 for (const auto &L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007954 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007955 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007956 }
Samuel Antao86ace552016-04-27 22:40:57 +00007957
Samuel Antaocc10b852016-07-28 14:23:26 +00007958 // Look at the use_device_ptr clause information and mark the existing map
7959 // entries as such. If there is no map information for an entry in the
7960 // use_device_ptr list, we create one with map type 'alloc' and zero size
Alexey Bataevb3638132018-07-19 16:34:13 +00007961 // section. It is the user fault if that was not mapped before. If there is
7962 // no map information and the pointer is a struct member, then we defer the
7963 // emission of that entry until the whole struct has been processed.
7964 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>>
7965 DeferredInfo;
7966
Alexey Bataevb3638132018-07-19 16:34:13 +00007967 for (const auto *C :
Michael Krused47b9432019-08-05 18:43:21 +00007968 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007969 for (const auto &L : C->component_lists()) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007970 assert(!L.second.empty() && "Not expecting empty list of components!");
7971 const ValueDecl *VD = L.second.back().getAssociatedDeclaration();
7972 VD = cast<ValueDecl>(VD->getCanonicalDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007973 const Expr *IE = L.second.back().getAssociatedExpression();
Samuel Antaocc10b852016-07-28 14:23:26 +00007974 // If the first component is a member expression, we have to look into
7975 // 'this', which maps to null in the map of map information. Otherwise
7976 // look directly for the information.
7977 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
7978
7979 // We potentially have map information for this declaration already.
7980 // Look for the first set of components that refer to it.
7981 if (It != Info.end()) {
7982 auto CI = std::find_if(
7983 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) {
7984 return MI.Components.back().getAssociatedDeclaration() == VD;
7985 });
7986 // If we found a map entry, signal that the pointer has to be returned
7987 // and move on to the next declaration.
7988 if (CI != It->second.end()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007989 CI->ReturnDevicePointer = true;
Samuel Antaocc10b852016-07-28 14:23:26 +00007990 continue;
7991 }
7992 }
7993
7994 // We didn't find any match in our map information - generate a zero
Alexey Bataevb3638132018-07-19 16:34:13 +00007995 // size array section - if the pointer is a struct member we defer this
7996 // action until the whole struct has been processed.
Alexey Bataevb3638132018-07-19 16:34:13 +00007997 if (isa<MemberExpr>(IE)) {
7998 // Insert the pointer into Info to be processed by
7999 // generateInfoForComponentList. Because it is a member pointer
8000 // without a pointee, no entry will be generated for it, therefore
8001 // we need to generate one after the whole struct has been processed.
8002 // Nonetheless, generateInfoForComponentList must be called to take
8003 // the pointer into account for the calculation of the range of the
8004 // partial struct.
Kelvin Lief579432018-12-18 22:18:41 +00008005 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00008006 /*ReturnDevicePointer=*/false, C->isImplicit());
8007 DeferredInfo[nullptr].emplace_back(IE, VD);
8008 } else {
Michael Krused47b9432019-08-05 18:43:21 +00008009 llvm::Value *Ptr =
8010 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc());
Alexey Bataevb3638132018-07-19 16:34:13 +00008011 BasePointers.emplace_back(Ptr, VD);
8012 Pointers.push_back(Ptr);
Michael Krused47b9432019-08-05 18:43:21 +00008013 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00008014 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM);
8015 }
Samuel Antaocc10b852016-07-28 14:23:26 +00008016 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008017 }
Samuel Antaocc10b852016-07-28 14:23:26 +00008018
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008019 for (const auto &M : Info) {
Samuel Antao86ace552016-04-27 22:40:57 +00008020 // We need to know when we generate information for the first component
8021 // associated with a capture, because the mapping flags depend on it.
8022 bool IsFirstComponentList = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00008023
8024 // Temporary versions of arrays
8025 MapBaseValuesArrayTy CurBasePointers;
8026 MapValuesArrayTy CurPointers;
8027 MapValuesArrayTy CurSizes;
8028 MapFlagsArrayTy CurTypes;
8029 StructRangeInfoTy PartialStruct;
8030
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008031 for (const MapInfo &L : M.second) {
Samuel Antao86ace552016-04-27 22:40:57 +00008032 assert(!L.Components.empty() &&
8033 "Not expecting declaration with no component lists.");
Samuel Antaocc10b852016-07-28 14:23:26 +00008034
8035 // Remember the current base pointer index.
Alexey Bataevb3638132018-07-19 16:34:13 +00008036 unsigned CurrentBasePointersIdx = CurBasePointers.size();
Michael Krused47b9432019-08-05 18:43:21 +00008037 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8038 CurBasePointers, CurPointers, CurSizes,
8039 CurTypes, PartialStruct,
8040 IsFirstComponentList, L.IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00008041
8042 // If this entry relates with a device pointer, set the relevant
8043 // declaration and add the 'return pointer' flag.
Alexey Bataevb3638132018-07-19 16:34:13 +00008044 if (L.ReturnDevicePointer) {
8045 assert(CurBasePointers.size() > CurrentBasePointersIdx &&
Samuel Antaocc10b852016-07-28 14:23:26 +00008046 "Unexpected number of mapped base pointers.");
8047
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008048 const ValueDecl *RelevantVD =
8049 L.Components.back().getAssociatedDeclaration();
Samuel Antaocc10b852016-07-28 14:23:26 +00008050 assert(RelevantVD &&
8051 "No relevant declaration related with device pointer??");
8052
Alexey Bataevb3638132018-07-19 16:34:13 +00008053 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD);
8054 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008055 }
Samuel Antao86ace552016-04-27 22:40:57 +00008056 IsFirstComponentList = false;
8057 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008058
8059 // Append any pending zero-length pointers which are struct members and
8060 // used with use_device_ptr.
8061 auto CI = DeferredInfo.find(M.first);
8062 if (CI != DeferredInfo.end()) {
8063 for (const DeferredDevicePtrEntryTy &L : CI->second) {
8064 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer();
8065 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar(
8066 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc());
8067 CurBasePointers.emplace_back(BasePtr, L.VD);
8068 CurPointers.push_back(Ptr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008069 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00008070 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder
8071 // value MEMBER_OF=FFFF so that the entry is later updated with the
8072 // correct value of MEMBER_OF.
8073 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM |
8074 OMP_MAP_MEMBER_OF);
8075 }
8076 }
8077
8078 // If there is an entry in PartialStruct it means we have a struct with
8079 // individual members mapped. Emit an extra combined entry.
8080 if (PartialStruct.Base.isValid())
8081 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8082 PartialStruct);
8083
8084 // We need to append the results of this capture to what we already have.
8085 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8086 Pointers.append(CurPointers.begin(), CurPointers.end());
8087 Sizes.append(CurSizes.begin(), CurSizes.end());
8088 Types.append(CurTypes.begin(), CurTypes.end());
Samuel Antao86ace552016-04-27 22:40:57 +00008089 }
8090 }
8091
Michael Krused47b9432019-08-05 18:43:21 +00008092 /// Generate all the base pointers, section pointers, sizes and map types for
8093 /// the extracted map clauses of user-defined mapper.
8094 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers,
8095 MapValuesArrayTy &Pointers,
8096 MapValuesArrayTy &Sizes,
8097 MapFlagsArrayTy &Types) const {
8098 assert(CurDir.is<const OMPDeclareMapperDecl *>() &&
8099 "Expect a declare mapper directive");
8100 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>();
8101 // We have to process the component lists that relate with the same
8102 // declaration in a single chunk so that we can generate the map flags
8103 // correctly. Therefore, we organize all lists in a map.
8104 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
8105
8106 // Helper function to fill the information map for the different supported
8107 // clauses.
8108 auto &&InfoGen = [&Info](
8109 const ValueDecl *D,
8110 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
8111 OpenMPMapClauseKind MapType,
8112 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8113 bool ReturnDevicePointer, bool IsImplicit) {
8114 const ValueDecl *VD =
8115 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
8116 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
8117 IsImplicit);
8118 };
8119
8120 for (const auto *C : CurMapperDir->clauselists()) {
8121 const auto *MC = cast<OMPMapClause>(C);
8122 for (const auto &L : MC->component_lists()) {
8123 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(),
8124 /*ReturnDevicePointer=*/false, MC->isImplicit());
8125 }
8126 }
8127
8128 for (const auto &M : Info) {
8129 // We need to know when we generate information for the first component
8130 // associated with a capture, because the mapping flags depend on it.
8131 bool IsFirstComponentList = true;
8132
8133 // Temporary versions of arrays
8134 MapBaseValuesArrayTy CurBasePointers;
8135 MapValuesArrayTy CurPointers;
8136 MapValuesArrayTy CurSizes;
8137 MapFlagsArrayTy CurTypes;
8138 StructRangeInfoTy PartialStruct;
8139
8140 for (const MapInfo &L : M.second) {
8141 assert(!L.Components.empty() &&
8142 "Not expecting declaration with no component lists.");
8143 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8144 CurBasePointers, CurPointers, CurSizes,
8145 CurTypes, PartialStruct,
8146 IsFirstComponentList, L.IsImplicit);
8147 IsFirstComponentList = false;
8148 }
8149
8150 // If there is an entry in PartialStruct it means we have a struct with
8151 // individual members mapped. Emit an extra combined entry.
8152 if (PartialStruct.Base.isValid())
8153 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8154 PartialStruct);
8155
8156 // We need to append the results of this capture to what we already have.
8157 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8158 Pointers.append(CurPointers.begin(), CurPointers.end());
8159 Sizes.append(CurSizes.begin(), CurSizes.end());
8160 Types.append(CurTypes.begin(), CurTypes.end());
8161 }
8162 }
8163
Alexey Bataev60705422018-10-30 15:50:12 +00008164 /// Emit capture info for lambdas for variables captured by reference.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008165 void generateInfoForLambdaCaptures(
8166 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers,
8167 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
8168 MapFlagsArrayTy &Types,
8169 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008170 const auto *RD = VD->getType()
8171 .getCanonicalType()
8172 .getNonReferenceType()
8173 ->getAsCXXRecordDecl();
8174 if (!RD || !RD->isLambda())
8175 return;
8176 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD));
8177 LValue VDLVal = CGF.MakeAddrLValue(
8178 VDAddr, VD->getType().getCanonicalType().getNonReferenceType());
8179 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
8180 FieldDecl *ThisCapture = nullptr;
8181 RD->getCaptureFields(Captures, ThisCapture);
8182 if (ThisCapture) {
8183 LValue ThisLVal =
8184 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture);
Alexey Bataev969dbc02018-11-08 15:47:39 +00008185 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture);
8186 LambdaPointers.try_emplace(ThisLVal.getPointer(), VDLVal.getPointer());
8187 BasePointers.push_back(ThisLVal.getPointer());
8188 Pointers.push_back(ThisLValVal.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00008189 Sizes.push_back(
8190 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8191 CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008192 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008193 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8194 }
8195 for (const LambdaCapture &LC : RD->captures()) {
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008196 if (!LC.capturesVariable())
Alexey Bataev60705422018-10-30 15:50:12 +00008197 continue;
8198 const VarDecl *VD = LC.getCapturedVar();
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008199 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType())
8200 continue;
Alexey Bataev60705422018-10-30 15:50:12 +00008201 auto It = Captures.find(VD);
8202 assert(It != Captures.end() && "Found lambda capture without field.");
8203 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second);
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008204 if (LC.getCaptureKind() == LCK_ByRef) {
8205 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second);
8206 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer());
8207 BasePointers.push_back(VarLVal.getPointer());
8208 Pointers.push_back(VarLValVal.getPointer());
8209 Sizes.push_back(CGF.Builder.CreateIntCast(
8210 CGF.getTypeSize(
8211 VD->getType().getCanonicalType().getNonReferenceType()),
8212 CGF.Int64Ty, /*isSigned=*/true));
8213 } else {
8214 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation());
8215 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer());
8216 BasePointers.push_back(VarLVal.getPointer());
8217 Pointers.push_back(VarRVal.getScalarVal());
8218 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0));
8219 }
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008220 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008221 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8222 }
8223 }
8224
8225 /// Set correct indices for lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008226 void adjustMemberOfForLambdaCaptures(
8227 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
8228 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
8229 MapFlagsArrayTy &Types) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008230 for (unsigned I = 0, E = Types.size(); I < E; ++I) {
8231 // Set correct member_of idx for all implicit lambda captures.
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008232 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008233 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT))
8234 continue;
Alexey Bataev969dbc02018-11-08 15:47:39 +00008235 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]);
8236 assert(BasePtr && "Unable to find base lambda address.");
Alexey Bataev60705422018-10-30 15:50:12 +00008237 int TgtIdx = -1;
8238 for (unsigned J = I; J > 0; --J) {
8239 unsigned Idx = J - 1;
8240 if (Pointers[Idx] != BasePtr)
8241 continue;
8242 TgtIdx = Idx;
8243 break;
8244 }
8245 assert(TgtIdx != -1 && "Unable to find parent lambda.");
8246 // All other current entries will be MEMBER_OF the combined entry
8247 // (except for PTR_AND_OBJ entries which do not have a placeholder value
8248 // 0xFFFF in the MEMBER_OF field).
8249 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx);
8250 setCorrectMemberOfFlag(Types[I], MemberOfFlag);
8251 }
8252 }
8253
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008254 /// Generate the base pointers, section pointers, sizes and map types
Samuel Antao86ace552016-04-27 22:40:57 +00008255 /// associated to a given capture.
8256 void generateInfoForCapture(const CapturedStmt::Capture *Cap,
Samuel Antao6890b092016-07-28 14:25:09 +00008257 llvm::Value *Arg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008258 MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00008259 MapValuesArrayTy &Pointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008260 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
8261 StructRangeInfoTy &PartialStruct) const {
Samuel Antao86ace552016-04-27 22:40:57 +00008262 assert(!Cap->capturesVariableArrayType() &&
8263 "Not expecting to generate map info for a variable array type!");
8264
Samuel Antao6890b092016-07-28 14:25:09 +00008265 // We need to know when we generating information for the first component
Alexey Bataevb3638132018-07-19 16:34:13 +00008266 const ValueDecl *VD = Cap->capturesThis()
8267 ? nullptr
8268 : Cap->getCapturedVar()->getCanonicalDecl();
Samuel Antao86ace552016-04-27 22:40:57 +00008269
Samuel Antao6890b092016-07-28 14:25:09 +00008270 // If this declaration appears in a is_device_ptr clause we just have to
8271 // pass the pointer by value. If it is a reference to a declaration, we just
Alexey Bataevb3638132018-07-19 16:34:13 +00008272 // pass its value.
8273 if (DevPointersMap.count(VD)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008274 BasePointers.emplace_back(Arg, VD);
Samuel Antao6890b092016-07-28 14:25:09 +00008275 Pointers.push_back(Arg);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008276 Sizes.push_back(
8277 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8278 CGF.Int64Ty, /*isSigned=*/true));
George Rokos065755d2017-11-07 18:27:04 +00008279 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM);
Samuel Antao6890b092016-07-28 14:25:09 +00008280 return;
8281 }
8282
Alexey Bataeve82445f2018-09-20 13:54:02 +00008283 using MapData =
8284 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
Kelvin Lief579432018-12-18 22:18:41 +00008285 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008286 SmallVector<MapData, 4> DeclComponentLists;
Michael Krused47b9432019-08-05 18:43:21 +00008287 assert(CurDir.is<const OMPExecutableDirective *>() &&
8288 "Expect a executable directive");
8289 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
8290 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008291 for (const auto &L : C->decl_component_lists(VD)) {
Samuel Antao86ace552016-04-27 22:40:57 +00008292 assert(L.first == VD &&
8293 "We got information for the wrong declaration??");
8294 assert(!L.second.empty() &&
8295 "Not expecting declaration with no component lists.");
Alexey Bataeve82445f2018-09-20 13:54:02 +00008296 DeclComponentLists.emplace_back(L.second, C->getMapType(),
Kelvin Lief579432018-12-18 22:18:41 +00008297 C->getMapTypeModifiers(),
Alexey Bataeve82445f2018-09-20 13:54:02 +00008298 C->isImplicit());
Samuel Antao86ace552016-04-27 22:40:57 +00008299 }
Alexey Bataeve82445f2018-09-20 13:54:02 +00008300 }
8301
8302 // Find overlapping elements (including the offset from the base element).
8303 llvm::SmallDenseMap<
8304 const MapData *,
8305 llvm::SmallVector<
8306 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>,
8307 4>
8308 OverlappedData;
8309 size_t Count = 0;
8310 for (const MapData &L : DeclComponentLists) {
8311 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8312 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008313 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008314 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008315 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008316 ++Count;
8317 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) {
8318 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1;
Kelvin Lief579432018-12-18 22:18:41 +00008319 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008320 auto CI = Components.rbegin();
8321 auto CE = Components.rend();
8322 auto SI = Components1.rbegin();
8323 auto SE = Components1.rend();
8324 for (; CI != CE && SI != SE; ++CI, ++SI) {
8325 if (CI->getAssociatedExpression()->getStmtClass() !=
8326 SI->getAssociatedExpression()->getStmtClass())
8327 break;
8328 // Are we dealing with different variables/fields?
8329 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
8330 break;
8331 }
8332 // Found overlapping if, at least for one component, reached the head of
8333 // the components list.
8334 if (CI == CE || SI == SE) {
8335 assert((CI != CE || SI != SE) &&
8336 "Unexpected full match of the mapping components.");
8337 const MapData &BaseData = CI == CE ? L : L1;
8338 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData =
8339 SI == SE ? Components : Components1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008340 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData);
8341 OverlappedElements.getSecond().push_back(SubData);
8342 }
8343 }
8344 }
8345 // Sort the overlapped elements for each item.
8346 llvm::SmallVector<const FieldDecl *, 4> Layout;
8347 if (!OverlappedData.empty()) {
8348 if (const auto *CRD =
8349 VD->getType().getCanonicalType()->getAsCXXRecordDecl())
8350 getPlainLayout(CRD, Layout, /*AsBase=*/false);
8351 else {
8352 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl();
8353 Layout.append(RD->field_begin(), RD->field_end());
8354 }
8355 }
8356 for (auto &Pair : OverlappedData) {
8357 llvm::sort(
8358 Pair.getSecond(),
8359 [&Layout](
8360 OMPClauseMappableExprCommon::MappableExprComponentListRef First,
8361 OMPClauseMappableExprCommon::MappableExprComponentListRef
8362 Second) {
8363 auto CI = First.rbegin();
8364 auto CE = First.rend();
8365 auto SI = Second.rbegin();
8366 auto SE = Second.rend();
8367 for (; CI != CE && SI != SE; ++CI, ++SI) {
8368 if (CI->getAssociatedExpression()->getStmtClass() !=
8369 SI->getAssociatedExpression()->getStmtClass())
8370 break;
8371 // Are we dealing with different variables/fields?
8372 if (CI->getAssociatedDeclaration() !=
8373 SI->getAssociatedDeclaration())
8374 break;
8375 }
Richard Trieu5061e832018-09-21 21:20:33 +00008376
8377 // Lists contain the same elements.
8378 if (CI == CE && SI == SE)
8379 return false;
8380
8381 // List with less elements is less than list with more elements.
8382 if (CI == CE || SI == SE)
8383 return CI == CE;
8384
Alexey Bataeve82445f2018-09-20 13:54:02 +00008385 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
8386 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
8387 if (FD1->getParent() == FD2->getParent())
8388 return FD1->getFieldIndex() < FD2->getFieldIndex();
8389 const auto It =
8390 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) {
8391 return FD == FD1 || FD == FD2;
8392 });
8393 return *It == FD1;
8394 });
8395 }
8396
8397 // Associated with a capture, because the mapping flags depend on it.
8398 // Go through all of the elements with the overlapped elements.
8399 for (const auto &Pair : OverlappedData) {
8400 const MapData &L = *Pair.getFirst();
8401 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8402 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008403 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008404 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008405 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008406 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
8407 OverlappedComponents = Pair.getSecond();
8408 bool IsFirstComponentList = true;
Kelvin Lief579432018-12-18 22:18:41 +00008409 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008410 BasePointers, Pointers, Sizes, Types,
8411 PartialStruct, IsFirstComponentList,
8412 IsImplicit, OverlappedComponents);
8413 }
8414 // Go through other elements without overlapped elements.
8415 bool IsFirstComponentList = OverlappedData.empty();
8416 for (const MapData &L : DeclComponentLists) {
8417 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8418 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008419 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008420 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008421 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008422 auto It = OverlappedData.find(&L);
8423 if (It == OverlappedData.end())
Kelvin Lief579432018-12-18 22:18:41 +00008424 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008425 BasePointers, Pointers, Sizes, Types,
8426 PartialStruct, IsFirstComponentList,
8427 IsImplicit);
8428 IsFirstComponentList = false;
8429 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008430 }
Samuel Antao86ace552016-04-27 22:40:57 +00008431
Alexey Bataevb3638132018-07-19 16:34:13 +00008432 /// Generate the base pointers, section pointers, sizes and map types
8433 /// associated with the declare target link variables.
8434 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers,
8435 MapValuesArrayTy &Pointers,
8436 MapValuesArrayTy &Sizes,
8437 MapFlagsArrayTy &Types) const {
Michael Krused47b9432019-08-05 18:43:21 +00008438 assert(CurDir.is<const OMPExecutableDirective *>() &&
8439 "Expect a executable directive");
8440 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
Alexey Bataevb3638132018-07-19 16:34:13 +00008441 // Map other list items in the map clause which are not captured variables
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00008442 // but "declare target link" global variables.
Michael Krused47b9432019-08-05 18:43:21 +00008443 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00008444 for (const auto &L : C->component_lists()) {
8445 if (!L.first)
8446 continue;
8447 const auto *VD = dyn_cast<VarDecl>(L.first);
8448 if (!VD)
8449 continue;
8450 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00008451 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00008452 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
8453 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)
Alexey Bataevb3638132018-07-19 16:34:13 +00008454 continue;
8455 StructRangeInfoTy PartialStruct;
8456 generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00008457 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008458 Pointers, Sizes, Types, PartialStruct,
8459 /*IsFirstComponentList=*/true, C->isImplicit());
8460 assert(!PartialStruct.Base.isValid() &&
8461 "No partial structs for declare target link expected.");
8462 }
8463 }
Samuel Antao86ace552016-04-27 22:40:57 +00008464 }
Samuel Antaod486f842016-05-26 16:53:38 +00008465
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008466 /// Generate the default map information for a given capture \a CI,
Samuel Antaod486f842016-05-26 16:53:38 +00008467 /// record field declaration \a RI and captured value \a CV.
Samuel Antaocc10b852016-07-28 14:23:26 +00008468 void generateDefaultMapInfo(const CapturedStmt::Capture &CI,
8469 const FieldDecl &RI, llvm::Value *CV,
8470 MapBaseValuesArrayTy &CurBasePointers,
8471 MapValuesArrayTy &CurPointers,
8472 MapValuesArrayTy &CurSizes,
Alexey Bataevb3638132018-07-19 16:34:13 +00008473 MapFlagsArrayTy &CurMapTypes) const {
Alexey Bataevf288cf92019-06-27 18:53:07 +00008474 bool IsImplicit = true;
Samuel Antaod486f842016-05-26 16:53:38 +00008475 // Do the default mapping.
8476 if (CI.capturesThis()) {
8477 CurBasePointers.push_back(CV);
8478 CurPointers.push_back(CV);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008479 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr());
Alexey Bataeva90fc662019-06-25 16:00:43 +00008480 CurSizes.push_back(
8481 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()),
8482 CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008483 // Default map type.
Samuel Antaocc10b852016-07-28 14:23:26 +00008484 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM);
Samuel Antaod486f842016-05-26 16:53:38 +00008485 } else if (CI.capturesVariableByCopy()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008486 CurBasePointers.push_back(CV);
8487 CurPointers.push_back(CV);
Samuel Antaod486f842016-05-26 16:53:38 +00008488 if (!RI.getType()->isAnyPointerType()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008489 // We have to signal to the runtime captures passed by value that are
8490 // not pointers.
George Rokos065755d2017-11-07 18:27:04 +00008491 CurMapTypes.push_back(OMP_MAP_LITERAL);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008492 CurSizes.push_back(CGF.Builder.CreateIntCast(
8493 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008494 } else {
8495 // Pointers are implicitly mapped with a zero size and no flags
8496 // (other than first map that is added for all implicit maps).
Alexey Bataevb3638132018-07-19 16:34:13 +00008497 CurMapTypes.push_back(OMP_MAP_NONE);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008498 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
Samuel Antaod486f842016-05-26 16:53:38 +00008499 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008500 const VarDecl *VD = CI.getCapturedVar();
8501 auto I = FirstPrivateDecls.find(VD);
8502 if (I != FirstPrivateDecls.end())
8503 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008504 } else {
8505 assert(CI.capturesVariable() && "Expected captured reference.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008506 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr());
Samuel Antaod486f842016-05-26 16:53:38 +00008507 QualType ElementType = PtrTy->getPointeeType();
Alexey Bataeva90fc662019-06-25 16:00:43 +00008508 CurSizes.push_back(CGF.Builder.CreateIntCast(
8509 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008510 // The default map type for a scalar/complex type is 'to' because by
8511 // default the value doesn't have to be retrieved. For an aggregate
8512 // type, the default is 'tofrom'.
Alexey Bataevb3638132018-07-19 16:34:13 +00008513 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI));
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008514 const VarDecl *VD = CI.getCapturedVar();
Alexey Bataevf288cf92019-06-27 18:53:07 +00008515 auto I = FirstPrivateDecls.find(VD);
8516 if (I != FirstPrivateDecls.end() &&
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008517 VD->getType().isConstant(CGF.getContext())) {
8518 llvm::Constant *Addr =
8519 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD);
8520 // Copy the value of the original variable to the new global copy.
8521 CGF.Builder.CreateMemCpy(
8522 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(),
8523 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)),
Rui Ueyama49a3ad22019-07-16 04:46:31 +00008524 CurSizes.back(), /*IsVolatile=*/false);
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008525 // Use new global variable as the base pointers.
8526 CurBasePointers.push_back(Addr);
8527 CurPointers.push_back(Addr);
8528 } else {
8529 CurBasePointers.push_back(CV);
Alexey Bataevf288cf92019-06-27 18:53:07 +00008530 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) {
Alexey Bataevc2b831f2019-04-02 16:03:40 +00008531 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue(
8532 CV, ElementType, CGF.getContext().getDeclAlign(VD),
8533 AlignmentSource::Decl));
8534 CurPointers.push_back(PtrAddr.getPointer());
8535 } else {
8536 CurPointers.push_back(CV);
8537 }
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008538 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008539 if (I != FirstPrivateDecls.end())
8540 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008541 }
George Rokos065755d2017-11-07 18:27:04 +00008542 // Every default map produces a single argument which is a target parameter.
8543 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM;
Alexey Bataevb3638132018-07-19 16:34:13 +00008544
8545 // Add flag stating this is an implicit map.
Alexey Bataevf288cf92019-06-27 18:53:07 +00008546 if (IsImplicit)
8547 CurMapTypes.back() |= OMP_MAP_IMPLICIT;
Samuel Antaod486f842016-05-26 16:53:38 +00008548 }
Samuel Antao86ace552016-04-27 22:40:57 +00008549};
Samuel Antaodf158d52016-04-27 22:58:19 +00008550} // anonymous namespace
8551
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008552/// Emit the arrays used to pass the captures and map information to the
Samuel Antaodf158d52016-04-27 22:58:19 +00008553/// offloading runtime library. If there is no map or capture information,
8554/// return nullptr by reference.
8555static void
Samuel Antaocc10b852016-07-28 14:23:26 +00008556emitOffloadingArrays(CodeGenFunction &CGF,
8557 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers,
Samuel Antaodf158d52016-04-27 22:58:19 +00008558 MappableExprsHandler::MapValuesArrayTy &Pointers,
8559 MappableExprsHandler::MapValuesArrayTy &Sizes,
Samuel Antaocc10b852016-07-28 14:23:26 +00008560 MappableExprsHandler::MapFlagsArrayTy &MapTypes,
8561 CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008562 CodeGenModule &CGM = CGF.CGM;
8563 ASTContext &Ctx = CGF.getContext();
Samuel Antaodf158d52016-04-27 22:58:19 +00008564
Samuel Antaocc10b852016-07-28 14:23:26 +00008565 // Reset the array information.
8566 Info.clearArrayInfo();
8567 Info.NumberOfPtrs = BasePointers.size();
Samuel Antaodf158d52016-04-27 22:58:19 +00008568
Samuel Antaocc10b852016-07-28 14:23:26 +00008569 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008570 // Detect if we have any capture size requiring runtime evaluation of the
8571 // size so that a constant array could be eventually used.
8572 bool hasRuntimeEvaluationCaptureSize = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008573 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008574 if (!isa<llvm::Constant>(S)) {
8575 hasRuntimeEvaluationCaptureSize = true;
8576 break;
8577 }
8578
Samuel Antaocc10b852016-07-28 14:23:26 +00008579 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true);
Richard Smith772e2662019-10-04 01:25:59 +00008580 QualType PointerArrayType = Ctx.getConstantArrayType(
8581 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal,
8582 /*IndexTypeQuals=*/0);
Samuel Antaodf158d52016-04-27 22:58:19 +00008583
Samuel Antaocc10b852016-07-28 14:23:26 +00008584 Info.BasePointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008585 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
Samuel Antaocc10b852016-07-28 14:23:26 +00008586 Info.PointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008587 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
8588
8589 // If we don't have any VLA types or other types that require runtime
8590 // evaluation, we can use a constant array for the map sizes, otherwise we
8591 // need to fill up the arrays as we do for the pointers.
Alexey Bataeva90fc662019-06-25 16:00:43 +00008592 QualType Int64Ty =
8593 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Samuel Antaodf158d52016-04-27 22:58:19 +00008594 if (hasRuntimeEvaluationCaptureSize) {
Richard Smith772e2662019-10-04 01:25:59 +00008595 QualType SizeArrayType = Ctx.getConstantArrayType(
8596 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal,
8597 /*IndexTypeQuals=*/0);
Samuel Antaocc10b852016-07-28 14:23:26 +00008598 Info.SizesArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008599 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
8600 } else {
8601 // We expect all the sizes to be constant, so we collect them to create
8602 // a constant array.
8603 SmallVector<llvm::Constant *, 16> ConstSizes;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008604 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008605 ConstSizes.push_back(cast<llvm::Constant>(S));
8606
8607 auto *SizesArrayInit = llvm::ConstantArray::get(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008608 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008609 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008610 auto *SizesArrayGbl = new llvm::GlobalVariable(
8611 CGM.getModule(), SizesArrayInit->getType(),
8612 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008613 SizesArrayInit, Name);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008614 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008615 Info.SizesArray = SizesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008616 }
8617
8618 // The map types are always constant so we don't need to generate code to
8619 // fill arrays. Instead, we create an array constant.
Alexey Bataevb3638132018-07-19 16:34:13 +00008620 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0);
8621 llvm::copy(MapTypes, Mapping.begin());
Samuel Antaodf158d52016-04-27 22:58:19 +00008622 llvm::Constant *MapTypesArrayInit =
Alexey Bataevb3638132018-07-19 16:34:13 +00008623 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008624 std::string MaptypesName =
8625 CGM.getOpenMPRuntime().getName({"offload_maptypes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008626 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
8627 CGM.getModule(), MapTypesArrayInit->getType(),
8628 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008629 MapTypesArrayInit, MaptypesName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008630 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008631 Info.MapTypesArray = MapTypesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008632
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008633 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) {
8634 llvm::Value *BPVal = *BasePointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008635 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008636 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008637 Info.BasePointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008638 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8639 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008640 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8641 CGF.Builder.CreateStore(BPVal, BPAddr);
8642
Samuel Antaocc10b852016-07-28 14:23:26 +00008643 if (Info.requiresDevicePointerInfo())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008644 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl())
Alexey Bataev43a919f2018-04-13 17:48:43 +00008645 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr);
Samuel Antaocc10b852016-07-28 14:23:26 +00008646
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008647 llvm::Value *PVal = Pointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008648 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008649 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008650 Info.PointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008651 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8652 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008653 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8654 CGF.Builder.CreateStore(PVal, PAddr);
8655
8656 if (hasRuntimeEvaluationCaptureSize) {
8657 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008658 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008659 Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008660 /*Idx0=*/0,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008661 /*Idx1=*/I);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008662 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty));
Samuel Antaodf158d52016-04-27 22:58:19 +00008663 CGF.Builder.CreateStore(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008664 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true),
Samuel Antaodf158d52016-04-27 22:58:19 +00008665 SAddr);
8666 }
8667 }
8668 }
8669}
Michael Krused47b9432019-08-05 18:43:21 +00008670
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008671/// Emit the arguments to be passed to the runtime library based on the
Samuel Antaodf158d52016-04-27 22:58:19 +00008672/// arrays of pointers, sizes and map types.
8673static void emitOffloadingArraysArgument(
8674 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg,
8675 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008676 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008677 CodeGenModule &CGM = CGF.CGM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008678 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008679 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008680 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8681 Info.BasePointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008682 /*Idx0=*/0, /*Idx1=*/0);
8683 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008684 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8685 Info.PointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008686 /*Idx0=*/0,
8687 /*Idx1=*/0);
8688 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008689 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008690 /*Idx0=*/0, /*Idx1=*/0);
8691 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
George Rokos63bc9d62017-11-21 18:25:12 +00008692 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008693 Info.MapTypesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008694 /*Idx0=*/0,
8695 /*Idx1=*/0);
8696 } else {
8697 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
8698 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008699 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008700 MapTypesArrayArg =
George Rokos63bc9d62017-11-21 18:25:12 +00008701 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008702 }
Samuel Antao86ace552016-04-27 22:40:57 +00008703}
8704
Alexey Bataev7bb33532019-01-07 21:30:43 +00008705/// Check for inner distribute directive.
8706static const OMPExecutableDirective *
8707getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
8708 const auto *CS = D.getInnermostCapturedStmt();
8709 const auto *Body =
8710 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00008711 const Stmt *ChildStmt =
8712 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
Alexey Bataev7bb33532019-01-07 21:30:43 +00008713
Alexey Bataev5c427362019-04-10 19:11:33 +00008714 if (const auto *NestedDir =
8715 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008716 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind();
8717 switch (D.getDirectiveKind()) {
8718 case OMPD_target:
8719 if (isOpenMPDistributeDirective(DKind))
8720 return NestedDir;
8721 if (DKind == OMPD_teams) {
8722 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
8723 /*IgnoreCaptured=*/true);
8724 if (!Body)
8725 return nullptr;
Alexey Bataev5c427362019-04-10 19:11:33 +00008726 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
8727 if (const auto *NND =
8728 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008729 DKind = NND->getDirectiveKind();
8730 if (isOpenMPDistributeDirective(DKind))
8731 return NND;
8732 }
8733 }
8734 return nullptr;
8735 case OMPD_target_teams:
8736 if (isOpenMPDistributeDirective(DKind))
8737 return NestedDir;
8738 return nullptr;
8739 case OMPD_target_parallel:
8740 case OMPD_target_simd:
8741 case OMPD_target_parallel_for:
8742 case OMPD_target_parallel_for_simd:
8743 return nullptr;
8744 case OMPD_target_teams_distribute:
8745 case OMPD_target_teams_distribute_simd:
8746 case OMPD_target_teams_distribute_parallel_for:
8747 case OMPD_target_teams_distribute_parallel_for_simd:
8748 case OMPD_parallel:
8749 case OMPD_for:
8750 case OMPD_parallel_for:
8751 case OMPD_parallel_sections:
8752 case OMPD_for_simd:
8753 case OMPD_parallel_for_simd:
8754 case OMPD_cancel:
8755 case OMPD_cancellation_point:
8756 case OMPD_ordered:
8757 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00008758 case OMPD_allocate:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008759 case OMPD_task:
8760 case OMPD_simd:
8761 case OMPD_sections:
8762 case OMPD_section:
8763 case OMPD_single:
8764 case OMPD_master:
8765 case OMPD_critical:
8766 case OMPD_taskyield:
8767 case OMPD_barrier:
8768 case OMPD_taskwait:
8769 case OMPD_taskgroup:
8770 case OMPD_atomic:
8771 case OMPD_flush:
8772 case OMPD_teams:
8773 case OMPD_target_data:
8774 case OMPD_target_exit_data:
8775 case OMPD_target_enter_data:
8776 case OMPD_distribute:
8777 case OMPD_distribute_simd:
8778 case OMPD_distribute_parallel_for:
8779 case OMPD_distribute_parallel_for_simd:
8780 case OMPD_teams_distribute:
8781 case OMPD_teams_distribute_simd:
8782 case OMPD_teams_distribute_parallel_for:
8783 case OMPD_teams_distribute_parallel_for_simd:
8784 case OMPD_target_update:
8785 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00008786 case OMPD_declare_variant:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008787 case OMPD_declare_target:
8788 case OMPD_end_declare_target:
8789 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00008790 case OMPD_declare_mapper:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008791 case OMPD_taskloop:
8792 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00008793 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00008794 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00008795 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04008796 case OMPD_parallel_master_taskloop_simd:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008797 case OMPD_requires:
8798 case OMPD_unknown:
8799 llvm_unreachable("Unexpected directive.");
8800 }
8801 }
8802
8803 return nullptr;
8804}
8805
Michael Krused47b9432019-08-05 18:43:21 +00008806/// Emit the user-defined mapper function. The code generation follows the
8807/// pattern in the example below.
8808/// \code
8809/// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle,
8810/// void *base, void *begin,
8811/// int64_t size, int64_t type) {
8812/// // Allocate space for an array section first.
8813/// if (size > 1 && !maptype.IsDelete)
8814/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
8815/// size*sizeof(Ty), clearToFrom(type));
8816/// // Map members.
8817/// for (unsigned i = 0; i < size; i++) {
8818/// // For each component specified by this mapper:
8819/// for (auto c : all_components) {
8820/// if (c.hasMapper())
8821/// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size,
8822/// c.arg_type);
8823/// else
8824/// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base,
8825/// c.arg_begin, c.arg_size, c.arg_type);
8826/// }
8827/// }
8828/// // Delete the array section.
8829/// if (size > 1 && maptype.IsDelete)
8830/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
8831/// size*sizeof(Ty), clearToFrom(type));
8832/// }
8833/// \endcode
8834void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D,
8835 CodeGenFunction *CGF) {
8836 if (UDMMap.count(D) > 0)
8837 return;
8838 ASTContext &C = CGM.getContext();
8839 QualType Ty = D->getType();
8840 QualType PtrTy = C.getPointerType(Ty).withRestrict();
8841 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
8842 auto *MapperVarDecl =
8843 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl());
8844 SourceLocation Loc = D->getLocation();
8845 CharUnits ElementSize = C.getTypeSizeInChars(Ty);
8846
8847 // Prepare mapper function arguments and attributes.
8848 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
8849 C.VoidPtrTy, ImplicitParamDecl::Other);
8850 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
8851 ImplicitParamDecl::Other);
8852 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
8853 C.VoidPtrTy, ImplicitParamDecl::Other);
8854 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
8855 ImplicitParamDecl::Other);
8856 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
8857 ImplicitParamDecl::Other);
8858 FunctionArgList Args;
8859 Args.push_back(&HandleArg);
8860 Args.push_back(&BaseArg);
8861 Args.push_back(&BeginArg);
8862 Args.push_back(&SizeArg);
8863 Args.push_back(&TypeArg);
8864 const CGFunctionInfo &FnInfo =
8865 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
8866 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
8867 SmallString<64> TyStr;
8868 llvm::raw_svector_ostream Out(TyStr);
8869 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out);
8870 std::string Name = getName({"omp_mapper", TyStr, D->getName()});
8871 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
8872 Name, &CGM.getModule());
8873 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
8874 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
8875 // Start the mapper function code generation.
8876 CodeGenFunction MapperCGF(CGM);
8877 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
8878 // Compute the starting and end addreses of array elements.
8879 llvm::Value *Size = MapperCGF.EmitLoadOfScalar(
8880 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false,
8881 C.getPointerType(Int64Ty), Loc);
8882 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast(
8883 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(),
8884 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy)));
8885 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size);
8886 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar(
8887 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false,
8888 C.getPointerType(Int64Ty), Loc);
8889 // Prepare common arguments for array initiation and deletion.
8890 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar(
8891 MapperCGF.GetAddrOfLocalVar(&HandleArg),
8892 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8893 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar(
8894 MapperCGF.GetAddrOfLocalVar(&BaseArg),
8895 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8896 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar(
8897 MapperCGF.GetAddrOfLocalVar(&BeginArg),
8898 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8899
8900 // Emit array initiation if this is an array section and \p MapType indicates
8901 // that memory allocation is required.
8902 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head");
8903 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
8904 ElementSize, HeadBB, /*IsInit=*/true);
8905
8906 // Emit a for loop to iterate through SizeArg of elements and map all of them.
8907
8908 // Emit the loop header block.
8909 MapperCGF.EmitBlock(HeadBB);
8910 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body");
8911 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done");
8912 // Evaluate whether the initial condition is satisfied.
8913 llvm::Value *IsEmpty =
8914 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty");
8915 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
8916 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock();
8917
8918 // Emit the loop body block.
8919 MapperCGF.EmitBlock(BodyBB);
8920 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI(
8921 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent");
8922 PtrPHI->addIncoming(PtrBegin, EntryBB);
8923 Address PtrCurrent =
8924 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg)
8925 .getAlignment()
8926 .alignmentOfArrayElement(ElementSize));
8927 // Privatize the declared variable of mapper to be the current array element.
8928 CodeGenFunction::OMPPrivateScope Scope(MapperCGF);
8929 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() {
8930 return MapperCGF
8931 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>())
8932 .getAddress();
8933 });
8934 (void)Scope.Privatize();
8935
8936 // Get map clause information. Fill up the arrays with all mapped variables.
8937 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
8938 MappableExprsHandler::MapValuesArrayTy Pointers;
8939 MappableExprsHandler::MapValuesArrayTy Sizes;
8940 MappableExprsHandler::MapFlagsArrayTy MapTypes;
8941 MappableExprsHandler MEHandler(*D, MapperCGF);
8942 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes);
8943
8944 // Call the runtime API __tgt_mapper_num_components to get the number of
8945 // pre-existing components.
8946 llvm::Value *OffloadingArgs[] = {Handle};
8947 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall(
8948 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs);
8949 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl(
8950 PreviousSize,
8951 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset()));
8952
8953 // Fill up the runtime mapper handle for all components.
8954 for (unsigned I = 0; I < BasePointers.size(); ++I) {
8955 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast(
8956 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
8957 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast(
8958 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
8959 llvm::Value *CurSizeArg = Sizes[I];
8960
8961 // Extract the MEMBER_OF field from the map type.
8962 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member");
8963 MapperCGF.EmitBlock(MemberBB);
8964 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]);
8965 llvm::Value *Member = MapperCGF.Builder.CreateAnd(
8966 OriMapType,
8967 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF));
8968 llvm::BasicBlock *MemberCombineBB =
8969 MapperCGF.createBasicBlock("omp.member.combine");
8970 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type");
8971 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member);
8972 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB);
8973 // Add the number of pre-existing components to the MEMBER_OF field if it
8974 // is valid.
8975 MapperCGF.EmitBlock(MemberCombineBB);
8976 llvm::Value *CombinedMember =
8977 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
8978 // Do nothing if it is not a member of previous components.
8979 MapperCGF.EmitBlock(TypeBB);
8980 llvm::PHINode *MemberMapType =
8981 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype");
8982 MemberMapType->addIncoming(OriMapType, MemberBB);
8983 MemberMapType->addIncoming(CombinedMember, MemberCombineBB);
8984
8985 // Combine the map type inherited from user-defined mapper with that
8986 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM
8987 // bits of the \a MapType, which is the input argument of the mapper
8988 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM
8989 // bits of MemberMapType.
8990 // [OpenMP 5.0], 1.2.6. map-type decay.
8991 // | alloc | to | from | tofrom | release | delete
8992 // ----------------------------------------------------------
8993 // alloc | alloc | alloc | alloc | alloc | release | delete
8994 // to | alloc | to | alloc | to | release | delete
8995 // from | alloc | alloc | from | from | release | delete
8996 // tofrom | alloc | to | from | tofrom | release | delete
8997 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd(
8998 MapType,
8999 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO |
9000 MappableExprsHandler::OMP_MAP_FROM));
9001 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc");
9002 llvm::BasicBlock *AllocElseBB =
9003 MapperCGF.createBasicBlock("omp.type.alloc.else");
9004 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to");
9005 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else");
9006 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from");
9007 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end");
9008 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom);
9009 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
9010 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM.
9011 MapperCGF.EmitBlock(AllocBB);
9012 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd(
9013 MemberMapType,
9014 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9015 MappableExprsHandler::OMP_MAP_FROM)));
9016 MapperCGF.Builder.CreateBr(EndBB);
9017 MapperCGF.EmitBlock(AllocElseBB);
9018 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ(
9019 LeftToFrom,
9020 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO));
9021 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
9022 // In case of to, clear OMP_MAP_FROM.
9023 MapperCGF.EmitBlock(ToBB);
9024 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd(
9025 MemberMapType,
9026 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM));
9027 MapperCGF.Builder.CreateBr(EndBB);
9028 MapperCGF.EmitBlock(ToElseBB);
9029 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ(
9030 LeftToFrom,
9031 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM));
9032 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB);
9033 // In case of from, clear OMP_MAP_TO.
9034 MapperCGF.EmitBlock(FromBB);
9035 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd(
9036 MemberMapType,
9037 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO));
9038 // In case of tofrom, do nothing.
9039 MapperCGF.EmitBlock(EndBB);
9040 llvm::PHINode *CurMapType =
9041 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype");
9042 CurMapType->addIncoming(AllocMapType, AllocBB);
9043 CurMapType->addIncoming(ToMapType, ToBB);
9044 CurMapType->addIncoming(FromMapType, FromBB);
9045 CurMapType->addIncoming(MemberMapType, ToElseBB);
9046
9047 // TODO: call the corresponding mapper function if a user-defined mapper is
9048 // associated with this map clause.
9049 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9050 // data structure.
9051 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg,
9052 CurSizeArg, CurMapType};
9053 MapperCGF.EmitRuntimeCall(
9054 createRuntimeFunction(OMPRTL__tgt_push_mapper_component),
9055 OffloadingArgs);
9056 }
9057
9058 // Update the pointer to point to the next element that needs to be mapped,
9059 // and check whether we have mapped all elements.
9060 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32(
9061 PtrPHI, /*Idx0=*/1, "omp.arraymap.next");
9062 PtrPHI->addIncoming(PtrNext, BodyBB);
9063 llvm::Value *IsDone =
9064 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone");
9065 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit");
9066 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
9067
9068 MapperCGF.EmitBlock(ExitBB);
9069 // Emit array deletion if this is an array section and \p MapType indicates
9070 // that deletion is required.
9071 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
9072 ElementSize, DoneBB, /*IsInit=*/false);
9073
9074 // Emit the function exit block.
9075 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true);
9076 MapperCGF.FinishFunction();
9077 UDMMap.try_emplace(D, Fn);
9078 if (CGF) {
9079 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn);
9080 Decls.second.push_back(D);
9081 }
9082}
9083
9084/// Emit the array initialization or deletion portion for user-defined mapper
9085/// code generation. First, it evaluates whether an array section is mapped and
9086/// whether the \a MapType instructs to delete this section. If \a IsInit is
9087/// true, and \a MapType indicates to not delete this array, array
9088/// initialization code is generated. If \a IsInit is false, and \a MapType
9089/// indicates to not this array, array deletion code is generated.
9090void CGOpenMPRuntime::emitUDMapperArrayInitOrDel(
9091 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base,
9092 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType,
9093 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) {
9094 StringRef Prefix = IsInit ? ".init" : ".del";
9095
9096 // Evaluate if this is an array section.
9097 llvm::BasicBlock *IsDeleteBB =
9098 MapperCGF.createBasicBlock("omp.array" + Prefix + ".evaldelete");
9099 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.array" + Prefix);
9100 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE(
9101 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray");
9102 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB);
9103
9104 // Evaluate if we are going to delete this section.
9105 MapperCGF.EmitBlock(IsDeleteBB);
9106 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd(
9107 MapType,
9108 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE));
9109 llvm::Value *DeleteCond;
9110 if (IsInit) {
9111 DeleteCond = MapperCGF.Builder.CreateIsNull(
9112 DeleteBit, "omp.array" + Prefix + ".delete");
9113 } else {
9114 DeleteCond = MapperCGF.Builder.CreateIsNotNull(
9115 DeleteBit, "omp.array" + Prefix + ".delete");
9116 }
9117 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB);
9118
9119 MapperCGF.EmitBlock(BodyBB);
9120 // Get the array size by multiplying element size and element number (i.e., \p
9121 // Size).
9122 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul(
9123 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
9124 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves
9125 // memory allocation/deletion purpose only.
9126 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd(
9127 MapType,
9128 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9129 MappableExprsHandler::OMP_MAP_FROM)));
9130 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9131 // data structure.
9132 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg};
9133 MapperCGF.EmitRuntimeCall(
9134 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs);
9135}
9136
Alexey Bataev7bb33532019-01-07 21:30:43 +00009137void CGOpenMPRuntime::emitTargetNumIterationsCall(
Alexey Bataevec7946e2019-09-23 14:06:51 +00009138 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9139 llvm::Value *DeviceID,
9140 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9141 const OMPLoopDirective &D)>
9142 SizeEmitter) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00009143 OpenMPDirectiveKind Kind = D.getDirectiveKind();
9144 const OMPExecutableDirective *TD = &D;
9145 // Get nested teams distribute kind directive, if any.
9146 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind))
9147 TD = getNestedDistributeDirective(CGM.getContext(), D);
9148 if (!TD)
9149 return;
9150 const auto *LD = cast<OMPLoopDirective>(TD);
Alexey Bataevec7946e2019-09-23 14:06:51 +00009151 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF,
Alexey Bataev7bb33532019-01-07 21:30:43 +00009152 PrePostActionTy &) {
Alexey Bataevec7946e2019-09-23 14:06:51 +00009153 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) {
9154 llvm::Value *Args[] = {DeviceID, NumIterations};
9155 CGF.EmitRuntimeCall(
9156 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args);
9157 }
Alexey Bataev7bb33532019-01-07 21:30:43 +00009158 };
9159 emitInlinedDirective(CGF, OMPD_unknown, CodeGen);
9160}
9161
Alexey Bataevec7946e2019-09-23 14:06:51 +00009162void CGOpenMPRuntime::emitTargetCall(
9163 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9164 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
9165 const Expr *Device,
9166 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9167 const OMPLoopDirective &D)>
9168 SizeEmitter) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00009169 if (!CGF.HaveInsertPoint())
9170 return;
Samuel Antaobed3c462015-10-02 16:14:20 +00009171
Samuel Antaoee8fb302016-01-06 13:42:12 +00009172 assert(OutlinedFn && "Invalid outlined function!");
9173
Alexey Bataev8451efa2018-01-15 19:06:12 +00009174 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>();
9175 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
Alexey Bataev475a7442018-01-12 19:39:11 +00009176 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009177 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF,
9178 PrePostActionTy &) {
9179 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9180 };
9181 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen);
Samuel Antao86ace552016-04-27 22:40:57 +00009182
Alexey Bataev8451efa2018-01-15 19:06:12 +00009183 CodeGenFunction::OMPTargetDataInfo InputInfo;
9184 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobed3c462015-10-02 16:14:20 +00009185 // Fill up the pointer arrays and transfer execution to the device.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009186 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo,
Alexey Bataevec7946e2019-09-23 14:06:51 +00009187 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars,
9188 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobed3c462015-10-02 16:14:20 +00009189 // On top of the arrays that were filled up, the target offloading call
9190 // takes as arguments the device id as well as the host pointer. The host
9191 // pointer is used by the runtime library to identify the current target
9192 // region, so it only has to be unique and not necessarily point to
9193 // anything. It could be the pointer to the outlined function that
9194 // implements the target region, but we aren't using that so that the
9195 // compiler doesn't need to keep that, and could therefore inline the host
9196 // function if proven worthwhile during optimization.
9197
Samuel Antaoee8fb302016-01-06 13:42:12 +00009198 // From this point on, we need to have an ID of the target region defined.
9199 assert(OutlinedFnID && "Invalid outlined function ID!");
Samuel Antaobed3c462015-10-02 16:14:20 +00009200
9201 // Emit device ID if any.
9202 llvm::Value *DeviceID;
George Rokos63bc9d62017-11-21 18:25:12 +00009203 if (Device) {
Samuel Antaobed3c462015-10-02 16:14:20 +00009204 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009205 CGF.Int64Ty, /*isSigned=*/true);
9206 } else {
9207 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9208 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009209
Samuel Antaodf158d52016-04-27 22:58:19 +00009210 // Emit the number of elements in the offloading arrays.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009211 llvm::Value *PointerNum =
9212 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaodf158d52016-04-27 22:58:19 +00009213
Samuel Antaob68e2db2016-03-03 16:20:23 +00009214 // Return value of the runtime offloading call.
9215 llvm::Value *Return;
9216
Alexey Bataev5c427362019-04-10 19:11:33 +00009217 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D);
9218 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009219
Alexey Bataevec7946e2019-09-23 14:06:51 +00009220 // Emit tripcount for the target loop-based directive.
9221 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter);
9222
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009223 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00009224 // The target region is an outlined function launched by the runtime
9225 // via calls __tgt_target() or __tgt_target_teams().
9226 //
9227 // __tgt_target() launches a target region with one team and one thread,
9228 // executing a serial region. This master thread may in turn launch
9229 // more threads within its team upon encountering a parallel region,
9230 // however, no additional teams can be launched on the device.
9231 //
9232 // __tgt_target_teams() launches a target region with one or more teams,
9233 // each with one or more threads. This call is required for target
9234 // constructs such as:
9235 // 'target teams'
9236 // 'target' / 'teams'
9237 // 'target teams distribute parallel for'
9238 // 'target parallel'
9239 // and so on.
9240 //
9241 // Note that on the host and CPU targets, the runtime implementation of
9242 // these calls simply call the outlined function without forking threads.
9243 // The outlined functions themselves have runtime calls to
9244 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by
9245 // the compiler in emitTeamsCall() and emitParallelCall().
9246 //
9247 // In contrast, on the NVPTX target, the implementation of
9248 // __tgt_target_teams() launches a GPU kernel with the requested number
9249 // of teams and threads so no additional calls to the runtime are required.
Samuel Antaob68e2db2016-03-03 16:20:23 +00009250 if (NumTeams) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00009251 // If we have NumTeams defined this means that we have an enclosed teams
9252 // region. Therefore we also expect to have NumThreads defined. These two
9253 // values should be defined in the presence of a teams directive,
9254 // regardless of having any clauses associated. If the user is using teams
9255 // but no clauses, these two values will be the default that should be
9256 // passed to the runtime library - a 32-bit integer with the value zero.
9257 assert(NumThreads && "Thread limit expression should be available along "
9258 "with number of teams.");
Alexey Bataev8451efa2018-01-15 19:06:12 +00009259 llvm::Value *OffloadingArgs[] = {DeviceID,
9260 OutlinedFnID,
9261 PointerNum,
9262 InputInfo.BasePointersArray.getPointer(),
9263 InputInfo.PointersArray.getPointer(),
9264 InputInfo.SizesArray.getPointer(),
9265 MapTypesArray,
9266 NumTeams,
9267 NumThreads};
Samuel Antaob68e2db2016-03-03 16:20:23 +00009268 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00009269 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait
9270 : OMPRTL__tgt_target_teams),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009271 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009272 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009273 llvm::Value *OffloadingArgs[] = {DeviceID,
9274 OutlinedFnID,
9275 PointerNum,
9276 InputInfo.BasePointersArray.getPointer(),
9277 InputInfo.PointersArray.getPointer(),
9278 InputInfo.SizesArray.getPointer(),
9279 MapTypesArray};
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009280 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00009281 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait
9282 : OMPRTL__tgt_target),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009283 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009284 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009285
Alexey Bataev2a007e02017-10-02 14:20:58 +00009286 // Check the error code and execute the host version if required.
9287 llvm::BasicBlock *OffloadFailedBlock =
9288 CGF.createBasicBlock("omp_offload.failed");
9289 llvm::BasicBlock *OffloadContBlock =
9290 CGF.createBasicBlock("omp_offload.cont");
9291 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return);
9292 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
9293
9294 CGF.EmitBlock(OffloadFailedBlock);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009295 if (RequiresOuterTask) {
9296 CapturedVars.clear();
9297 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9298 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009299 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev2a007e02017-10-02 14:20:58 +00009300 CGF.EmitBranch(OffloadContBlock);
9301
9302 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00009303 };
9304
Samuel Antaoee8fb302016-01-06 13:42:12 +00009305 // Notify that the host version must be executed.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009306 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars,
9307 RequiresOuterTask](CodeGenFunction &CGF,
9308 PrePostActionTy &) {
9309 if (RequiresOuterTask) {
9310 CapturedVars.clear();
9311 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9312 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009313 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009314 };
9315
9316 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray,
9317 &CapturedVars, RequiresOuterTask,
9318 &CS](CodeGenFunction &CGF, PrePostActionTy &) {
9319 // Fill up the arrays with all the captured variables.
9320 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
9321 MappableExprsHandler::MapValuesArrayTy Pointers;
9322 MappableExprsHandler::MapValuesArrayTy Sizes;
9323 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9324
Alexey Bataev8451efa2018-01-15 19:06:12 +00009325 // Get mappable expression information.
9326 MappableExprsHandler MEHandler(D, CGF);
Alexey Bataev969dbc02018-11-08 15:47:39 +00009327 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
Alexey Bataev8451efa2018-01-15 19:06:12 +00009328
9329 auto RI = CS.getCapturedRecordDecl()->field_begin();
9330 auto CV = CapturedVars.begin();
9331 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
9332 CE = CS.capture_end();
9333 CI != CE; ++CI, ++RI, ++CV) {
Alexey Bataevb3638132018-07-19 16:34:13 +00009334 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers;
9335 MappableExprsHandler::MapValuesArrayTy CurPointers;
9336 MappableExprsHandler::MapValuesArrayTy CurSizes;
9337 MappableExprsHandler::MapFlagsArrayTy CurMapTypes;
9338 MappableExprsHandler::StructRangeInfoTy PartialStruct;
Alexey Bataev8451efa2018-01-15 19:06:12 +00009339
9340 // VLA sizes are passed to the outlined region by copy and do not have map
9341 // information associated.
9342 if (CI->capturesVariableArrayType()) {
9343 CurBasePointers.push_back(*CV);
9344 CurPointers.push_back(*CV);
Alexey Bataeva90fc662019-06-25 16:00:43 +00009345 CurSizes.push_back(CGF.Builder.CreateIntCast(
9346 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev8451efa2018-01-15 19:06:12 +00009347 // Copy to the device as an argument. No need to retrieve it.
9348 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL |
Alexey Bataevf288cf92019-06-27 18:53:07 +00009349 MappableExprsHandler::OMP_MAP_TARGET_PARAM |
9350 MappableExprsHandler::OMP_MAP_IMPLICIT);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009351 } else {
9352 // If we have any information in the map clause, we use it, otherwise we
9353 // just do a default mapping.
9354 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00009355 CurSizes, CurMapTypes, PartialStruct);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009356 if (CurBasePointers.empty())
9357 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers,
9358 CurPointers, CurSizes, CurMapTypes);
Alexey Bataev60705422018-10-30 15:50:12 +00009359 // Generate correct mapping for variables captured by reference in
9360 // lambdas.
9361 if (CI->capturesVariable())
Alexey Bataev969dbc02018-11-08 15:47:39 +00009362 MEHandler.generateInfoForLambdaCaptures(
9363 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes,
9364 CurMapTypes, LambdaPointers);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009365 }
9366 // We expect to have at least an element of information for this capture.
9367 assert(!CurBasePointers.empty() &&
9368 "Non-existing map pointer for capture!");
9369 assert(CurBasePointers.size() == CurPointers.size() &&
9370 CurBasePointers.size() == CurSizes.size() &&
9371 CurBasePointers.size() == CurMapTypes.size() &&
9372 "Inconsistent map information sizes!");
9373
Alexey Bataevb3638132018-07-19 16:34:13 +00009374 // If there is an entry in PartialStruct it means we have a struct with
9375 // individual members mapped. Emit an extra combined entry.
9376 if (PartialStruct.Base.isValid())
9377 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes,
9378 CurMapTypes, PartialStruct);
9379
Alexey Bataev8451efa2018-01-15 19:06:12 +00009380 // We need to append the results of this capture to what we already have.
9381 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
9382 Pointers.append(CurPointers.begin(), CurPointers.end());
9383 Sizes.append(CurSizes.begin(), CurSizes.end());
9384 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end());
9385 }
Alexey Bataev60705422018-10-30 15:50:12 +00009386 // Adjust MEMBER_OF flags for the lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00009387 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers,
9388 Pointers, MapTypes);
Alexey Bataev92327c52018-03-26 16:40:55 +00009389 // Map other list items in the map clause which are not captured variables
9390 // but "declare target link" global variables.
Alexey Bataevb3638132018-07-19 16:34:13 +00009391 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes,
9392 MapTypes);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009393
9394 TargetDataInfo Info;
9395 // Fill up the arrays and create the arguments.
9396 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
9397 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
9398 Info.PointersArray, Info.SizesArray,
9399 Info.MapTypesArray, Info);
9400 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
9401 InputInfo.BasePointersArray =
9402 Address(Info.BasePointersArray, CGM.getPointerAlign());
9403 InputInfo.PointersArray =
9404 Address(Info.PointersArray, CGM.getPointerAlign());
9405 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign());
9406 MapTypesArray = Info.MapTypesArray;
9407 if (RequiresOuterTask)
9408 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
9409 else
9410 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
9411 };
9412
9413 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask](
9414 CodeGenFunction &CGF, PrePostActionTy &) {
9415 if (RequiresOuterTask) {
9416 CodeGenFunction::OMPTargetDataInfo InputInfo;
9417 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo);
9418 } else {
9419 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen);
9420 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009421 };
9422
9423 // If we have a target function ID it means that we need to support
9424 // offloading, otherwise, just execute on the host. We need to execute on host
9425 // regardless of the conditional in the if clause if, e.g., the user do not
9426 // specify target triples.
9427 if (OutlinedFnID) {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009428 if (IfCond) {
9429 emitOMPIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
9430 } else {
9431 RegionCodeGenTy ThenRCG(TargetThenGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00009432 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00009433 }
9434 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009435 RegionCodeGenTy ElseRCG(TargetElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00009436 ElseRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00009437 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009438}
Samuel Antaoee8fb302016-01-06 13:42:12 +00009439
9440void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
9441 StringRef ParentName) {
9442 if (!S)
9443 return;
9444
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009445 // Codegen OMP target directives that offload compute to the device.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009446 bool RequiresDeviceCodegen =
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009447 isa<OMPExecutableDirective>(S) &&
9448 isOpenMPTargetExecutionDirective(
9449 cast<OMPExecutableDirective>(S)->getDirectiveKind());
Samuel Antaoee8fb302016-01-06 13:42:12 +00009450
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009451 if (RequiresDeviceCodegen) {
9452 const auto &E = *cast<OMPExecutableDirective>(S);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009453 unsigned DeviceID;
9454 unsigned FileID;
9455 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009456 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID,
Samuel Antao2de62b02016-02-13 23:35:10 +00009457 FileID, Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009458
9459 // Is this a target region that should not be emitted as an entry point? If
9460 // so just signal we are done with this target region.
Samuel Antao2de62b02016-02-13 23:35:10 +00009461 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
9462 ParentName, Line))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009463 return;
9464
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009465 switch (E.getDirectiveKind()) {
9466 case OMPD_target:
9467 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName,
9468 cast<OMPTargetDirective>(E));
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009469 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009470 case OMPD_target_parallel:
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009471 CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009472 CGM, ParentName, cast<OMPTargetParallelDirective>(E));
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009473 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009474 case OMPD_target_teams:
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009475 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009476 CGM, ParentName, cast<OMPTargetTeamsDirective>(E));
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009477 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009478 case OMPD_target_teams_distribute:
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009479 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009480 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E));
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009481 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009482 case OMPD_target_teams_distribute_simd:
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009483 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009484 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E));
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009485 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009486 case OMPD_target_parallel_for:
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009487 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009488 CGM, ParentName, cast<OMPTargetParallelForDirective>(E));
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009489 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009490 case OMPD_target_parallel_for_simd:
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009491 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009492 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E));
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009493 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009494 case OMPD_target_simd:
Alexey Bataevf8365372017-11-17 17:57:25 +00009495 CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009496 CGM, ParentName, cast<OMPTargetSimdDirective>(E));
Alexey Bataevf8365372017-11-17 17:57:25 +00009497 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009498 case OMPD_target_teams_distribute_parallel_for:
Carlo Bertolli52978c32018-01-03 21:12:44 +00009499 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
9500 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009501 cast<OMPTargetTeamsDistributeParallelForDirective>(E));
Carlo Bertolli52978c32018-01-03 21:12:44 +00009502 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009503 case OMPD_target_teams_distribute_parallel_for_simd:
Alexey Bataev647dd842018-01-15 20:59:40 +00009504 CodeGenFunction::
9505 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
9506 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009507 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E));
Alexey Bataev647dd842018-01-15 20:59:40 +00009508 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009509 case OMPD_parallel:
9510 case OMPD_for:
9511 case OMPD_parallel_for:
9512 case OMPD_parallel_sections:
9513 case OMPD_for_simd:
9514 case OMPD_parallel_for_simd:
9515 case OMPD_cancel:
9516 case OMPD_cancellation_point:
9517 case OMPD_ordered:
9518 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00009519 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009520 case OMPD_task:
9521 case OMPD_simd:
9522 case OMPD_sections:
9523 case OMPD_section:
9524 case OMPD_single:
9525 case OMPD_master:
9526 case OMPD_critical:
9527 case OMPD_taskyield:
9528 case OMPD_barrier:
9529 case OMPD_taskwait:
9530 case OMPD_taskgroup:
9531 case OMPD_atomic:
9532 case OMPD_flush:
9533 case OMPD_teams:
9534 case OMPD_target_data:
9535 case OMPD_target_exit_data:
9536 case OMPD_target_enter_data:
9537 case OMPD_distribute:
9538 case OMPD_distribute_simd:
9539 case OMPD_distribute_parallel_for:
9540 case OMPD_distribute_parallel_for_simd:
9541 case OMPD_teams_distribute:
9542 case OMPD_teams_distribute_simd:
9543 case OMPD_teams_distribute_parallel_for:
9544 case OMPD_teams_distribute_parallel_for_simd:
9545 case OMPD_target_update:
9546 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00009547 case OMPD_declare_variant:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009548 case OMPD_declare_target:
9549 case OMPD_end_declare_target:
9550 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00009551 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009552 case OMPD_taskloop:
9553 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00009554 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00009555 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00009556 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04009557 case OMPD_parallel_master_taskloop_simd:
Kelvin Li1408f912018-09-26 04:28:39 +00009558 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009559 case OMPD_unknown:
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009560 llvm_unreachable("Unknown target directive for OpenMP device codegen.");
9561 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009562 return;
9563 }
9564
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009565 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
Alexey Bataev475a7442018-01-12 19:39:11 +00009566 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009567 return;
9568
9569 scanForTargetRegionsFunctions(
Alexey Bataev475a7442018-01-12 19:39:11 +00009570 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009571 return;
9572 }
9573
9574 // If this is a lambda function, look into its body.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009575 if (const auto *L = dyn_cast<LambdaExpr>(S))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009576 S = L->getBody();
9577
9578 // Keep looking for target regions recursively.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009579 for (const Stmt *II : S->children())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009580 scanForTargetRegionsFunctions(II, ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009581}
9582
9583bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009584 // If emitting code for the host, we do not process FD here. Instead we do
9585 // the normal code generation.
Alexey Bataev729e2422019-08-23 16:11:14 +00009586 if (!CGM.getLangOpts().OpenMPIsDevice) {
9587 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) {
9588 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9589 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9590 // Do not emit device_type(nohost) functions for the host.
9591 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
9592 return true;
9593 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009594 return false;
Alexey Bataev729e2422019-08-23 16:11:14 +00009595 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009596
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009597 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009598 StringRef Name = CGM.getMangledName(GD);
9599 // Try to detect target regions in the function.
Alexey Bataev729e2422019-08-23 16:11:14 +00009600 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009601 scanForTargetRegionsFunctions(FD->getBody(), Name);
Alexey Bataev729e2422019-08-23 16:11:14 +00009602 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9603 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9604 // Do not emit device_type(nohost) functions for the host.
9605 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
9606 return true;
9607 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009608
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009609 // Do not to emit function if it is not marked as declare target.
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009610 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009611 AlreadyEmittedTargetFunctions.count(Name) == 0;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009612}
9613
9614bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
9615 if (!CGM.getLangOpts().OpenMPIsDevice)
9616 return false;
9617
9618 // Check if there are Ctors/Dtors in this declaration and look for target
9619 // regions in it. We use the complete variant to produce the kernel name
9620 // mangling.
9621 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009622 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
9623 for (const CXXConstructorDecl *Ctor : RD->ctors()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009624 StringRef ParentName =
9625 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
9626 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
9627 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009628 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009629 StringRef ParentName =
9630 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
9631 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
9632 }
9633 }
9634
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009635 // Do not to emit variable if it is not marked as declare target.
Alexey Bataev92327c52018-03-26 16:40:55 +00009636 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009637 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
9638 cast<VarDecl>(GD.getDecl()));
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009639 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
9640 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9641 HasRequiresUnifiedSharedMemory)) {
Alexey Bataevd01b7492018-08-15 19:45:12 +00009642 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009643 return true;
9644 }
9645 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009646}
9647
Alexey Bataev1af5bd52019-03-05 17:47:18 +00009648llvm::Constant *
9649CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF,
9650 const VarDecl *VD) {
9651 assert(VD->getType().isConstant(CGM.getContext()) &&
9652 "Expected constant variable.");
9653 StringRef VarName;
9654 llvm::Constant *Addr;
9655 llvm::GlobalValue::LinkageTypes Linkage;
9656 QualType Ty = VD->getType();
9657 SmallString<128> Buffer;
9658 {
9659 unsigned DeviceID;
9660 unsigned FileID;
9661 unsigned Line;
9662 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID,
9663 FileID, Line);
9664 llvm::raw_svector_ostream OS(Buffer);
9665 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID)
9666 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
9667 VarName = OS.str();
9668 }
9669 Linkage = llvm::GlobalValue::InternalLinkage;
9670 Addr =
9671 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName,
9672 getDefaultFirstprivateAddressSpace());
9673 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage);
9674 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty);
9675 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr));
9676 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9677 VarName, Addr, VarSize,
9678 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage);
9679 return Addr;
9680}
9681
Alexey Bataev03f270c2018-03-30 18:31:07 +00009682void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
9683 llvm::Constant *Addr) {
Alexey Bataev36724b72019-10-03 16:46:49 +00009684 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
9685 !CGM.getLangOpts().OpenMPIsDevice)
Alexey Bataev4db9dc62019-09-23 15:53:51 +00009686 return;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009687 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9688 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
9689 if (!Res) {
9690 if (CGM.getLangOpts().OpenMPIsDevice) {
9691 // Register non-target variables being emitted in device code (debug info
9692 // may cause this).
9693 StringRef VarName = CGM.getMangledName(VD);
9694 EmittedNonTargetVariables.try_emplace(VarName, Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009695 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009696 return;
Alexey Bataev03f270c2018-03-30 18:31:07 +00009697 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009698 // Register declare target variables.
9699 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
9700 StringRef VarName;
9701 CharUnits VarSize;
9702 llvm::GlobalValue::LinkageTypes Linkage;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009703
9704 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9705 !HasRequiresUnifiedSharedMemory) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009706 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9707 VarName = CGM.getMangledName(VD);
9708 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) {
9709 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType());
9710 assert(!VarSize.isZero() && "Expected non-zero size of the variable");
9711 } else {
9712 VarSize = CharUnits::Zero();
9713 }
9714 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
9715 // Temp solution to prevent optimizations of the internal variables.
9716 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) {
9717 std::string RefName = getName({VarName, "ref"});
9718 if (!CGM.GetGlobalValue(RefName)) {
9719 llvm::Constant *AddrRef =
9720 getOrCreateInternalVariable(Addr->getType(), RefName);
9721 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef);
9722 GVAddrRef->setConstant(/*Val=*/true);
9723 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage);
9724 GVAddrRef->setInitializer(Addr);
9725 CGM.addCompilerUsedGlobal(GVAddrRef);
9726 }
9727 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009728 } else {
9729 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
9730 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9731 HasRequiresUnifiedSharedMemory)) &&
9732 "Declare target attribute must link or to with unified memory.");
9733 if (*Res == OMPDeclareTargetDeclAttr::MT_Link)
9734 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink;
9735 else
9736 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9737
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009738 if (CGM.getLangOpts().OpenMPIsDevice) {
9739 VarName = Addr->getName();
9740 Addr = nullptr;
9741 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009742 VarName = getAddrOfDeclareTargetVar(VD).getName();
9743 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009744 }
9745 VarSize = CGM.getPointerSize();
9746 Linkage = llvm::GlobalValue::WeakAnyLinkage;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009747 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009748
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009749 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9750 VarName, Addr, VarSize, Flags, Linkage);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009751}
9752
Samuel Antaoee8fb302016-01-06 13:42:12 +00009753bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009754 if (isa<FunctionDecl>(GD.getDecl()) ||
9755 isa<OMPDeclareReductionDecl>(GD.getDecl()))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009756 return emitTargetFunctions(GD);
9757
9758 return emitTargetGlobalVariable(GD);
9759}
9760
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009761void CGOpenMPRuntime::emitDeferredTargetDecls() const {
9762 for (const VarDecl *VD : DeferredGlobalVariables) {
9763 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009764 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009765 if (!Res)
9766 continue;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009767 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9768 !HasRequiresUnifiedSharedMemory) {
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009769 CGM.EmitGlobal(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009770 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009771 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
9772 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9773 HasRequiresUnifiedSharedMemory)) &&
9774 "Expected link clause or to clause with unified memory.");
9775 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009776 }
9777 }
9778}
9779
Alexey Bataev60705422018-10-30 15:50:12 +00009780void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas(
9781 CodeGenFunction &CGF, const OMPExecutableDirective &D) const {
9782 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) &&
9783 " Expected target-based directive.");
9784}
9785
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009786void CGOpenMPRuntime::checkArchForUnifiedAddressing(
9787 const OMPRequiresDecl *D) {
9788 for (const OMPClause *Clause : D->clauselists()) {
9789 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
9790 HasRequiresUnifiedSharedMemory = true;
9791 break;
9792 }
9793 }
9794}
9795
Alexey Bataevc5687252019-03-21 19:35:27 +00009796bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD,
9797 LangAS &AS) {
9798 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())
9799 return false;
9800 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
9801 switch(A->getAllocatorType()) {
9802 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
9803 // Not supported, fallback to the default mem space.
9804 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
9805 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
9806 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
9807 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
9808 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
9809 case OMPAllocateDeclAttr::OMPConstMemAlloc:
9810 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
9811 AS = LangAS::Default;
9812 return true;
9813 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
9814 llvm_unreachable("Expected predefined allocator for the variables with the "
9815 "static storage.");
9816 }
9817 return false;
9818}
9819
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00009820bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const {
9821 return HasRequiresUnifiedSharedMemory;
9822}
9823
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009824CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
9825 CodeGenModule &CGM)
9826 : CGM(CGM) {
9827 if (CGM.getLangOpts().OpenMPIsDevice) {
9828 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
9829 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
9830 }
9831}
9832
9833CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() {
9834 if (CGM.getLangOpts().OpenMPIsDevice)
9835 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
9836}
9837
Alexey Bataev6d944102018-05-02 15:45:28 +00009838bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009839 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal)
9840 return true;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009841
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009842 StringRef Name = CGM.getMangledName(GD);
Alexey Bataev6d944102018-05-02 15:45:28 +00009843 const auto *D = cast<FunctionDecl>(GD.getDecl());
Alexey Bataev34f8a702018-03-28 14:28:54 +00009844 // Do not to emit function if it is marked as declare target as it was already
9845 // emitted.
Alexey Bataev97b72212018-08-14 18:31:20 +00009846 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009847 if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) {
9848 if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name)))
Alexey Bataev34f8a702018-03-28 14:28:54 +00009849 return !F->isDeclaration();
9850 return false;
9851 }
9852 return true;
9853 }
9854
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009855 return !AlreadyEmittedTargetFunctions.insert(Name).second;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009856}
9857
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009858llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() {
9859 // If we don't have entries or if we are emitting code for the device, we
9860 // don't need to do anything.
9861 if (CGM.getLangOpts().OMPTargetTriples.empty() ||
9862 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice ||
9863 (OffloadEntriesInfoManager.empty() &&
9864 !HasEmittedDeclareTargetRegion &&
9865 !HasEmittedTargetRegion))
9866 return nullptr;
9867
9868 // Create and register the function that handles the requires directives.
9869 ASTContext &C = CGM.getContext();
9870
9871 llvm::Function *RequiresRegFn;
9872 {
9873 CodeGenFunction CGF(CGM);
9874 const auto &FI = CGM.getTypes().arrangeNullaryFunction();
9875 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
9876 std::string ReqName = getName({"omp_offloading", "requires_reg"});
9877 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI);
9878 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {});
9879 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE;
9880 // TODO: check for other requires clauses.
9881 // The requires directive takes effect only when a target region is
9882 // present in the compilation unit. Otherwise it is ignored and not
9883 // passed to the runtime. This avoids the runtime from throwing an error
9884 // for mismatching requires clauses across compilation units that don't
9885 // contain at least 1 target region.
9886 assert((HasEmittedTargetRegion ||
9887 HasEmittedDeclareTargetRegion ||
9888 !OffloadEntriesInfoManager.empty()) &&
9889 "Target or declare target region expected.");
9890 if (HasRequiresUnifiedSharedMemory)
9891 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY;
9892 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires),
9893 llvm::ConstantInt::get(CGM.Int64Ty, Flags));
9894 CGF.FinishFunction();
9895 }
9896 return RequiresRegFn;
9897}
9898
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009899void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
9900 const OMPExecutableDirective &D,
9901 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00009902 llvm::Function *OutlinedFn,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009903 ArrayRef<llvm::Value *> CapturedVars) {
9904 if (!CGF.HaveInsertPoint())
9905 return;
9906
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009907 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009908 CodeGenFunction::RunCleanupsScope Scope(CGF);
9909
9910 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
9911 llvm::Value *Args[] = {
9912 RTLoc,
9913 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
9914 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
9915 llvm::SmallVector<llvm::Value *, 16> RealArgs;
9916 RealArgs.append(std::begin(Args), std::end(Args));
9917 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
9918
James Y Knight9871db02019-02-05 16:42:33 +00009919 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009920 CGF.EmitRuntimeCall(RTLFn, RealArgs);
9921}
9922
9923void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
Carlo Bertollic6872252016-04-04 15:55:02 +00009924 const Expr *NumTeams,
9925 const Expr *ThreadLimit,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009926 SourceLocation Loc) {
9927 if (!CGF.HaveInsertPoint())
9928 return;
9929
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009930 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009931
Carlo Bertollic6872252016-04-04 15:55:02 +00009932 llvm::Value *NumTeamsVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009933 NumTeams
Carlo Bertollic6872252016-04-04 15:55:02 +00009934 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
9935 CGF.CGM.Int32Ty, /* isSigned = */ true)
9936 : CGF.Builder.getInt32(0);
9937
9938 llvm::Value *ThreadLimitVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009939 ThreadLimit
Carlo Bertollic6872252016-04-04 15:55:02 +00009940 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
9941 CGF.CGM.Int32Ty, /* isSigned = */ true)
9942 : CGF.Builder.getInt32(0);
9943
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009944 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
Carlo Bertollic6872252016-04-04 15:55:02 +00009945 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
9946 ThreadLimitVal};
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009947 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams),
9948 PushNumTeamsArgs);
9949}
Samuel Antaodf158d52016-04-27 22:58:19 +00009950
Samuel Antaocc10b852016-07-28 14:23:26 +00009951void CGOpenMPRuntime::emitTargetDataCalls(
9952 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
9953 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009954 if (!CGF.HaveInsertPoint())
9955 return;
9956
Samuel Antaocc10b852016-07-28 14:23:26 +00009957 // Action used to replace the default codegen action and turn privatization
9958 // off.
9959 PrePostActionTy NoPrivAction;
Samuel Antaodf158d52016-04-27 22:58:19 +00009960
9961 // Generate the code for the opening of the data environment. Capture all the
9962 // arguments of the runtime call by reference because they are used in the
9963 // closing of the region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009964 auto &&BeginThenGen = [this, &D, Device, &Info,
9965 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009966 // Fill up the arrays with all the mapped variables.
Samuel Antaocc10b852016-07-28 14:23:26 +00009967 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
Samuel Antaodf158d52016-04-27 22:58:19 +00009968 MappableExprsHandler::MapValuesArrayTy Pointers;
9969 MappableExprsHandler::MapValuesArrayTy Sizes;
9970 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9971
9972 // Get map clause information.
9973 MappableExprsHandler MCHandler(D, CGF);
9974 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
Samuel Antaodf158d52016-04-27 22:58:19 +00009975
9976 // Fill up the arrays and create the arguments.
Samuel Antaocc10b852016-07-28 14:23:26 +00009977 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +00009978
9979 llvm::Value *BasePointersArrayArg = nullptr;
9980 llvm::Value *PointersArrayArg = nullptr;
9981 llvm::Value *SizesArrayArg = nullptr;
9982 llvm::Value *MapTypesArrayArg = nullptr;
9983 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00009984 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +00009985
9986 // Emit device ID if any.
9987 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +00009988 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009989 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009990 CGF.Int64Ty, /*isSigned=*/true);
9991 } else {
9992 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9993 }
Samuel Antaodf158d52016-04-27 22:58:19 +00009994
9995 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009996 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +00009997
9998 llvm::Value *OffloadingArgs[] = {
9999 DeviceID, PointerNum, BasePointersArrayArg,
10000 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010001 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin),
Samuel Antaodf158d52016-04-27 22:58:19 +000010002 OffloadingArgs);
Samuel Antaocc10b852016-07-28 14:23:26 +000010003
10004 // If device pointer privatization is required, emit the body of the region
10005 // here. It will have to be duplicated: with and without privatization.
10006 if (!Info.CaptureDeviceAddrMap.empty())
10007 CodeGen(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010008 };
10009
10010 // Generate code for the closing of the data region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010011 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF,
10012 PrePostActionTy &) {
Samuel Antaocc10b852016-07-28 14:23:26 +000010013 assert(Info.isValid() && "Invalid data environment closing arguments.");
Samuel Antaodf158d52016-04-27 22:58:19 +000010014
10015 llvm::Value *BasePointersArrayArg = nullptr;
10016 llvm::Value *PointersArrayArg = nullptr;
10017 llvm::Value *SizesArrayArg = nullptr;
10018 llvm::Value *MapTypesArrayArg = nullptr;
10019 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +000010020 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +000010021
10022 // Emit device ID if any.
10023 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010024 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +000010025 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010026 CGF.Int64Ty, /*isSigned=*/true);
10027 } else {
10028 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10029 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010030
10031 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010032 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +000010033
10034 llvm::Value *OffloadingArgs[] = {
10035 DeviceID, PointerNum, BasePointersArrayArg,
10036 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010037 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end),
Samuel Antaodf158d52016-04-27 22:58:19 +000010038 OffloadingArgs);
10039 };
10040
Samuel Antaocc10b852016-07-28 14:23:26 +000010041 // If we need device pointer privatization, we need to emit the body of the
10042 // region with no privatization in the 'else' branch of the conditional.
10043 // Otherwise, we don't have to do anything.
10044 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF,
10045 PrePostActionTy &) {
10046 if (!Info.CaptureDeviceAddrMap.empty()) {
10047 CodeGen.setAction(NoPrivAction);
10048 CodeGen(CGF);
10049 }
10050 };
10051
10052 // We don't have to do anything to close the region if the if clause evaluates
10053 // to false.
10054 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
Samuel Antaodf158d52016-04-27 22:58:19 +000010055
10056 if (IfCond) {
Samuel Antaocc10b852016-07-28 14:23:26 +000010057 emitOMPIfClause(CGF, IfCond, BeginThenGen, BeginElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +000010058 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +000010059 RegionCodeGenTy RCG(BeginThenGen);
10060 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010061 }
10062
Samuel Antaocc10b852016-07-28 14:23:26 +000010063 // If we don't require privatization of device pointers, we emit the body in
10064 // between the runtime calls. This avoids duplicating the body code.
10065 if (Info.CaptureDeviceAddrMap.empty()) {
10066 CodeGen.setAction(NoPrivAction);
10067 CodeGen(CGF);
10068 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010069
10070 if (IfCond) {
Samuel Antaocc10b852016-07-28 14:23:26 +000010071 emitOMPIfClause(CGF, IfCond, EndThenGen, EndElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +000010072 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +000010073 RegionCodeGenTy RCG(EndThenGen);
10074 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010075 }
10076}
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010077
Samuel Antao8d2d7302016-05-26 18:30:22 +000010078void CGOpenMPRuntime::emitTargetDataStandAloneCall(
Samuel Antao8dd66282016-04-27 23:14:30 +000010079 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10080 const Expr *Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010081 if (!CGF.HaveInsertPoint())
10082 return;
10083
Samuel Antao8dd66282016-04-27 23:14:30 +000010084 assert((isa<OMPTargetEnterDataDirective>(D) ||
Samuel Antao8d2d7302016-05-26 18:30:22 +000010085 isa<OMPTargetExitDataDirective>(D) ||
10086 isa<OMPTargetUpdateDirective>(D)) &&
10087 "Expecting either target enter, exit data, or update directives.");
Samuel Antao8dd66282016-04-27 23:14:30 +000010088
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010089 CodeGenFunction::OMPTargetDataInfo InputInfo;
10090 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010091 // Generate the code for the opening of the data environment.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010092 auto &&ThenGen = [this, &D, Device, &InputInfo,
10093 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010094 // Emit device ID if any.
10095 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010096 if (Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010097 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010098 CGF.Int64Ty, /*isSigned=*/true);
10099 } else {
10100 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10101 }
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010102
10103 // Emit the number of elements in the offloading arrays.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010104 llvm::Constant *PointerNum =
10105 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010106
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010107 llvm::Value *OffloadingArgs[] = {DeviceID,
10108 PointerNum,
10109 InputInfo.BasePointersArray.getPointer(),
10110 InputInfo.PointersArray.getPointer(),
10111 InputInfo.SizesArray.getPointer(),
10112 MapTypesArray};
Samuel Antao8d2d7302016-05-26 18:30:22 +000010113
Samuel Antao8d2d7302016-05-26 18:30:22 +000010114 // Select the right runtime function call for each expected standalone
10115 // directive.
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010116 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Samuel Antao8d2d7302016-05-26 18:30:22 +000010117 OpenMPRTLFunction RTLFn;
10118 switch (D.getDirectiveKind()) {
Samuel Antao8d2d7302016-05-26 18:30:22 +000010119 case OMPD_target_enter_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010120 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait
10121 : OMPRTL__tgt_target_data_begin;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010122 break;
10123 case OMPD_target_exit_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010124 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait
10125 : OMPRTL__tgt_target_data_end;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010126 break;
10127 case OMPD_target_update:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010128 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait
10129 : OMPRTL__tgt_target_data_update;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010130 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010131 case OMPD_parallel:
10132 case OMPD_for:
10133 case OMPD_parallel_for:
10134 case OMPD_parallel_sections:
10135 case OMPD_for_simd:
10136 case OMPD_parallel_for_simd:
10137 case OMPD_cancel:
10138 case OMPD_cancellation_point:
10139 case OMPD_ordered:
10140 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +000010141 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010142 case OMPD_task:
10143 case OMPD_simd:
10144 case OMPD_sections:
10145 case OMPD_section:
10146 case OMPD_single:
10147 case OMPD_master:
10148 case OMPD_critical:
10149 case OMPD_taskyield:
10150 case OMPD_barrier:
10151 case OMPD_taskwait:
10152 case OMPD_taskgroup:
10153 case OMPD_atomic:
10154 case OMPD_flush:
10155 case OMPD_teams:
10156 case OMPD_target_data:
10157 case OMPD_distribute:
10158 case OMPD_distribute_simd:
10159 case OMPD_distribute_parallel_for:
10160 case OMPD_distribute_parallel_for_simd:
10161 case OMPD_teams_distribute:
10162 case OMPD_teams_distribute_simd:
10163 case OMPD_teams_distribute_parallel_for:
10164 case OMPD_teams_distribute_parallel_for_simd:
10165 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +000010166 case OMPD_declare_variant:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010167 case OMPD_declare_target:
10168 case OMPD_end_declare_target:
10169 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +000010170 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010171 case OMPD_taskloop:
10172 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +000010173 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +000010174 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +000010175 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -040010176 case OMPD_parallel_master_taskloop_simd:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010177 case OMPD_target:
10178 case OMPD_target_simd:
10179 case OMPD_target_teams_distribute:
10180 case OMPD_target_teams_distribute_simd:
10181 case OMPD_target_teams_distribute_parallel_for:
10182 case OMPD_target_teams_distribute_parallel_for_simd:
10183 case OMPD_target_teams:
10184 case OMPD_target_parallel:
10185 case OMPD_target_parallel_for:
10186 case OMPD_target_parallel_for_simd:
Kelvin Li1408f912018-09-26 04:28:39 +000010187 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010188 case OMPD_unknown:
10189 llvm_unreachable("Unexpected standalone target data directive.");
10190 break;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010191 }
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010192 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010193 };
10194
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010195 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray](
10196 CodeGenFunction &CGF, PrePostActionTy &) {
10197 // Fill up the arrays with all the mapped variables.
10198 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
10199 MappableExprsHandler::MapValuesArrayTy Pointers;
10200 MappableExprsHandler::MapValuesArrayTy Sizes;
10201 MappableExprsHandler::MapFlagsArrayTy MapTypes;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010202
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010203 // Get map clause information.
10204 MappableExprsHandler MEHandler(D, CGF);
10205 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
10206
10207 TargetDataInfo Info;
10208 // Fill up the arrays and create the arguments.
10209 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
10210 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
10211 Info.PointersArray, Info.SizesArray,
10212 Info.MapTypesArray, Info);
10213 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
10214 InputInfo.BasePointersArray =
10215 Address(Info.BasePointersArray, CGM.getPointerAlign());
10216 InputInfo.PointersArray =
10217 Address(Info.PointersArray, CGM.getPointerAlign());
10218 InputInfo.SizesArray =
10219 Address(Info.SizesArray, CGM.getPointerAlign());
10220 MapTypesArray = Info.MapTypesArray;
10221 if (D.hasClausesOfKind<OMPDependClause>())
10222 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
10223 else
Alexey Bataev768f1f22018-01-09 19:59:25 +000010224 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010225 };
10226
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010227 if (IfCond) {
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010228 emitOMPIfClause(CGF, IfCond, TargetThenGen,
10229 [](CodeGenFunction &CGF, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010230 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010231 RegionCodeGenTy ThenRCG(TargetThenGen);
10232 ThenRCG(CGF);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010233 }
10234}
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010235
10236namespace {
10237 /// Kind of parameter in a function with 'declare simd' directive.
10238 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector };
10239 /// Attribute set of the parameter.
10240 struct ParamAttrTy {
10241 ParamKindTy Kind = Vector;
10242 llvm::APSInt StrideOrArg;
10243 llvm::APSInt Alignment;
10244 };
10245} // namespace
10246
10247static unsigned evaluateCDTSize(const FunctionDecl *FD,
10248 ArrayRef<ParamAttrTy> ParamAttrs) {
10249 // Every vector variant of a SIMD-enabled function has a vector length (VLEN).
10250 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument
10251 // of that clause. The VLEN value must be power of 2.
10252 // In other case the notion of the function`s "characteristic data type" (CDT)
10253 // is used to compute the vector length.
10254 // CDT is defined in the following order:
10255 // a) For non-void function, the CDT is the return type.
10256 // b) If the function has any non-uniform, non-linear parameters, then the
10257 // CDT is the type of the first such parameter.
10258 // c) If the CDT determined by a) or b) above is struct, union, or class
10259 // type which is pass-by-value (except for the type that maps to the
10260 // built-in complex data type), the characteristic data type is int.
10261 // d) If none of the above three cases is applicable, the CDT is int.
10262 // The VLEN is then determined based on the CDT and the size of vector
10263 // register of that ISA for which current vector version is generated. The
10264 // VLEN is computed using the formula below:
10265 // VLEN = sizeof(vector_register) / sizeof(CDT),
10266 // where vector register size specified in section 3.2.1 Registers and the
10267 // Stack Frame of original AMD64 ABI document.
10268 QualType RetType = FD->getReturnType();
10269 if (RetType.isNull())
10270 return 0;
10271 ASTContext &C = FD->getASTContext();
10272 QualType CDT;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010273 if (!RetType.isNull() && !RetType->isVoidType()) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010274 CDT = RetType;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010275 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010276 unsigned Offset = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010277 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010278 if (ParamAttrs[Offset].Kind == Vector)
10279 CDT = C.getPointerType(C.getRecordType(MD->getParent()));
10280 ++Offset;
10281 }
10282 if (CDT.isNull()) {
10283 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10284 if (ParamAttrs[I + Offset].Kind == Vector) {
10285 CDT = FD->getParamDecl(I)->getType();
10286 break;
10287 }
10288 }
10289 }
10290 }
10291 if (CDT.isNull())
10292 CDT = C.IntTy;
10293 CDT = CDT->getCanonicalTypeUnqualified();
10294 if (CDT->isRecordType() || CDT->isUnionType())
10295 CDT = C.IntTy;
10296 return C.getTypeSize(CDT);
10297}
10298
10299static void
10300emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
Benjamin Kramer81cb4b72016-11-24 16:01:20 +000010301 const llvm::APSInt &VLENVal,
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010302 ArrayRef<ParamAttrTy> ParamAttrs,
10303 OMPDeclareSimdDeclAttr::BranchStateTy State) {
10304 struct ISADataTy {
10305 char ISA;
10306 unsigned VecRegSize;
10307 };
10308 ISADataTy ISAData[] = {
10309 {
10310 'b', 128
10311 }, // SSE
10312 {
10313 'c', 256
10314 }, // AVX
10315 {
10316 'd', 256
10317 }, // AVX2
10318 {
10319 'e', 512
10320 }, // AVX512
10321 };
10322 llvm::SmallVector<char, 2> Masked;
10323 switch (State) {
10324 case OMPDeclareSimdDeclAttr::BS_Undefined:
10325 Masked.push_back('N');
10326 Masked.push_back('M');
10327 break;
10328 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10329 Masked.push_back('N');
10330 break;
10331 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10332 Masked.push_back('M');
10333 break;
10334 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010335 for (char Mask : Masked) {
10336 for (const ISADataTy &Data : ISAData) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010337 SmallString<256> Buffer;
10338 llvm::raw_svector_ostream Out(Buffer);
10339 Out << "_ZGV" << Data.ISA << Mask;
10340 if (!VLENVal) {
Simon Pilgrim823a99c2019-05-22 13:02:19 +000010341 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs);
10342 assert(NumElts && "Non-zero simdlen/cdtsize expected");
10343 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010344 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010345 Out << VLENVal;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010346 }
10347 for (const ParamAttrTy &ParamAttr : ParamAttrs) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010348 switch (ParamAttr.Kind){
10349 case LinearWithVarStride:
10350 Out << 's' << ParamAttr.StrideOrArg;
10351 break;
10352 case Linear:
10353 Out << 'l';
10354 if (!!ParamAttr.StrideOrArg)
10355 Out << ParamAttr.StrideOrArg;
10356 break;
10357 case Uniform:
10358 Out << 'u';
10359 break;
10360 case Vector:
10361 Out << 'v';
10362 break;
10363 }
10364 if (!!ParamAttr.Alignment)
10365 Out << 'a' << ParamAttr.Alignment;
10366 }
10367 Out << '_' << Fn->getName();
10368 Fn->addFnAttr(Out.str());
10369 }
10370 }
10371}
10372
Alexey Bataeva0a22642019-04-16 13:56:21 +000010373// This are the Functions that are needed to mangle the name of the
10374// vector functions generated by the compiler, according to the rules
10375// defined in the "Vector Function ABI specifications for AArch64",
10376// available at
10377// https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi.
10378
10379/// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI.
10380///
10381/// TODO: Need to implement the behavior for reference marked with a
10382/// var or no linear modifiers (1.b in the section). For this, we
10383/// need to extend ParamKindTy to support the linear modifiers.
10384static bool getAArch64MTV(QualType QT, ParamKindTy Kind) {
10385 QT = QT.getCanonicalType();
10386
10387 if (QT->isVoidType())
10388 return false;
10389
10390 if (Kind == ParamKindTy::Uniform)
10391 return false;
10392
10393 if (Kind == ParamKindTy::Linear)
10394 return false;
10395
10396 // TODO: Handle linear references with modifiers
10397
10398 if (Kind == ParamKindTy::LinearWithVarStride)
10399 return false;
10400
10401 return true;
10402}
10403
10404/// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
10405static bool getAArch64PBV(QualType QT, ASTContext &C) {
10406 QT = QT.getCanonicalType();
10407 unsigned Size = C.getTypeSize(QT);
10408
10409 // Only scalars and complex within 16 bytes wide set PVB to true.
10410 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
10411 return false;
10412
10413 if (QT->isFloatingType())
10414 return true;
10415
10416 if (QT->isIntegerType())
10417 return true;
10418
10419 if (QT->isPointerType())
10420 return true;
10421
10422 // TODO: Add support for complex types (section 3.1.2, item 2).
10423
10424 return false;
10425}
10426
10427/// Computes the lane size (LS) of a return type or of an input parameter,
10428/// as defined by `LS(P)` in 3.2.1 of the AAVFABI.
10429/// TODO: Add support for references, section 3.2.1, item 1.
10430static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) {
10431 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) {
10432 QualType PTy = QT.getCanonicalType()->getPointeeType();
10433 if (getAArch64PBV(PTy, C))
10434 return C.getTypeSize(PTy);
10435 }
10436 if (getAArch64PBV(QT, C))
10437 return C.getTypeSize(QT);
10438
10439 return C.getTypeSize(C.getUIntPtrType());
10440}
10441
10442// Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the
10443// signature of the scalar function, as defined in 3.2.2 of the
10444// AAVFABI.
10445static std::tuple<unsigned, unsigned, bool>
10446getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) {
10447 QualType RetType = FD->getReturnType().getCanonicalType();
10448
10449 ASTContext &C = FD->getASTContext();
10450
10451 bool OutputBecomesInput = false;
10452
10453 llvm::SmallVector<unsigned, 8> Sizes;
10454 if (!RetType->isVoidType()) {
10455 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C));
10456 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {}))
10457 OutputBecomesInput = true;
10458 }
10459 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10460 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType();
10461 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C));
10462 }
10463
10464 assert(!Sizes.empty() && "Unable to determine NDS and WDS.");
10465 // The LS of a function parameter / return value can only be a power
10466 // of 2, starting from 8 bits, up to 128.
10467 assert(std::all_of(Sizes.begin(), Sizes.end(),
10468 [](unsigned Size) {
10469 return Size == 8 || Size == 16 || Size == 32 ||
10470 Size == 64 || Size == 128;
10471 }) &&
10472 "Invalid size");
10473
10474 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)),
10475 *std::max_element(std::begin(Sizes), std::end(Sizes)),
10476 OutputBecomesInput);
10477}
10478
10479/// Mangle the parameter part of the vector function name according to
10480/// their OpenMP classification. The mangling function is defined in
10481/// section 3.5 of the AAVFABI.
10482static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) {
10483 SmallString<256> Buffer;
10484 llvm::raw_svector_ostream Out(Buffer);
10485 for (const auto &ParamAttr : ParamAttrs) {
10486 switch (ParamAttr.Kind) {
10487 case LinearWithVarStride:
10488 Out << "ls" << ParamAttr.StrideOrArg;
10489 break;
10490 case Linear:
10491 Out << 'l';
10492 // Don't print the step value if it is not present or if it is
10493 // equal to 1.
10494 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1)
10495 Out << ParamAttr.StrideOrArg;
10496 break;
10497 case Uniform:
10498 Out << 'u';
10499 break;
10500 case Vector:
10501 Out << 'v';
10502 break;
10503 }
10504
10505 if (!!ParamAttr.Alignment)
10506 Out << 'a' << ParamAttr.Alignment;
10507 }
10508
10509 return Out.str();
10510}
10511
10512// Function used to add the attribute. The parameter `VLEN` is
10513// templated to allow the use of "x" when targeting scalable functions
10514// for SVE.
10515template <typename T>
10516static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix,
10517 char ISA, StringRef ParSeq,
10518 StringRef MangledName, bool OutputBecomesInput,
10519 llvm::Function *Fn) {
10520 SmallString<256> Buffer;
10521 llvm::raw_svector_ostream Out(Buffer);
10522 Out << Prefix << ISA << LMask << VLEN;
10523 if (OutputBecomesInput)
10524 Out << "v";
10525 Out << ParSeq << "_" << MangledName;
10526 Fn->addFnAttr(Out.str());
10527}
10528
10529// Helper function to generate the Advanced SIMD names depending on
10530// the value of the NDS when simdlen is not present.
10531static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask,
10532 StringRef Prefix, char ISA,
10533 StringRef ParSeq, StringRef MangledName,
10534 bool OutputBecomesInput,
10535 llvm::Function *Fn) {
10536 switch (NDS) {
10537 case 8:
10538 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10539 OutputBecomesInput, Fn);
10540 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName,
10541 OutputBecomesInput, Fn);
10542 break;
10543 case 16:
10544 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10545 OutputBecomesInput, Fn);
10546 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10547 OutputBecomesInput, Fn);
10548 break;
10549 case 32:
10550 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10551 OutputBecomesInput, Fn);
10552 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10553 OutputBecomesInput, Fn);
10554 break;
10555 case 64:
10556 case 128:
10557 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10558 OutputBecomesInput, Fn);
10559 break;
10560 default:
10561 llvm_unreachable("Scalar type is too wide.");
10562 }
10563}
10564
10565/// Emit vector function attributes for AArch64, as defined in the AAVFABI.
10566static void emitAArch64DeclareSimdFunction(
10567 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN,
10568 ArrayRef<ParamAttrTy> ParamAttrs,
10569 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
10570 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) {
10571
10572 // Get basic data for building the vector signature.
10573 const auto Data = getNDSWDS(FD, ParamAttrs);
10574 const unsigned NDS = std::get<0>(Data);
10575 const unsigned WDS = std::get<1>(Data);
10576 const bool OutputBecomesInput = std::get<2>(Data);
10577
10578 // Check the values provided via `simdlen` by the user.
10579 // 1. A `simdlen(1)` doesn't produce vector signatures,
10580 if (UserVLEN == 1) {
10581 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10582 DiagnosticsEngine::Warning,
10583 "The clause simdlen(1) has no effect when targeting aarch64.");
10584 CGM.getDiags().Report(SLoc, DiagID);
10585 return;
10586 }
10587
10588 // 2. Section 3.3.1, item 1: user input must be a power of 2 for
10589 // Advanced SIMD output.
10590 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
10591 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10592 DiagnosticsEngine::Warning, "The value specified in simdlen must be a "
10593 "power of 2 when targeting Advanced SIMD.");
10594 CGM.getDiags().Report(SLoc, DiagID);
10595 return;
10596 }
10597
10598 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural
10599 // limits.
10600 if (ISA == 's' && UserVLEN != 0) {
10601 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
10602 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10603 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit "
10604 "lanes in the architectural constraints "
10605 "for SVE (min is 128-bit, max is "
10606 "2048-bit, by steps of 128-bit)");
10607 CGM.getDiags().Report(SLoc, DiagID) << WDS;
10608 return;
10609 }
10610 }
10611
10612 // Sort out parameter sequence.
10613 const std::string ParSeq = mangleVectorParameters(ParamAttrs);
10614 StringRef Prefix = "_ZGV";
10615 // Generate simdlen from user input (if any).
10616 if (UserVLEN) {
10617 if (ISA == 's') {
10618 // SVE generates only a masked function.
10619 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10620 OutputBecomesInput, Fn);
10621 } else {
10622 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10623 // Advanced SIMD generates one or two functions, depending on
10624 // the `[not]inbranch` clause.
10625 switch (State) {
10626 case OMPDeclareSimdDeclAttr::BS_Undefined:
10627 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10628 OutputBecomesInput, Fn);
10629 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10630 OutputBecomesInput, Fn);
10631 break;
10632 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10633 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10634 OutputBecomesInput, Fn);
10635 break;
10636 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10637 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10638 OutputBecomesInput, Fn);
10639 break;
10640 }
10641 }
10642 } else {
10643 // If no user simdlen is provided, follow the AAVFABI rules for
10644 // generating the vector length.
10645 if (ISA == 's') {
10646 // SVE, section 3.4.1, item 1.
10647 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName,
10648 OutputBecomesInput, Fn);
10649 } else {
10650 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10651 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or
10652 // two vector names depending on the use of the clause
10653 // `[not]inbranch`.
10654 switch (State) {
10655 case OMPDeclareSimdDeclAttr::BS_Undefined:
10656 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10657 OutputBecomesInput, Fn);
10658 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10659 OutputBecomesInput, Fn);
10660 break;
10661 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10662 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10663 OutputBecomesInput, Fn);
10664 break;
10665 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10666 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10667 OutputBecomesInput, Fn);
10668 break;
10669 }
10670 }
10671 }
10672}
10673
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010674void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
10675 llvm::Function *Fn) {
10676 ASTContext &C = CGM.getContext();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010677 FD = FD->getMostRecentDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010678 // Map params to their positions in function decl.
10679 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
10680 if (isa<CXXMethodDecl>(FD))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010681 ParamPositions.try_emplace(FD, 0);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010682 unsigned ParamPos = ParamPositions.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010683 for (const ParmVarDecl *P : FD->parameters()) {
10684 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010685 ++ParamPos;
10686 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010687 while (FD) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010688 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010689 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
10690 // Mark uniform parameters.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010691 for (const Expr *E : Attr->uniforms()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010692 E = E->IgnoreParenImpCasts();
10693 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010694 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010695 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010696 } else {
10697 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10698 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010699 Pos = ParamPositions[PVD];
10700 }
10701 ParamAttrs[Pos].Kind = Uniform;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010702 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010703 // Get alignment info.
10704 auto NI = Attr->alignments_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010705 for (const Expr *E : Attr->aligneds()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010706 E = E->IgnoreParenImpCasts();
10707 unsigned Pos;
10708 QualType ParmTy;
10709 if (isa<CXXThisExpr>(E)) {
10710 Pos = ParamPositions[FD];
10711 ParmTy = E->getType();
10712 } else {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010713 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10714 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010715 Pos = ParamPositions[PVD];
10716 ParmTy = PVD->getType();
10717 }
10718 ParamAttrs[Pos].Alignment =
10719 (*NI)
10720 ? (*NI)->EvaluateKnownConstInt(C)
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010721 : llvm::APSInt::getUnsigned(
10722 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy))
10723 .getQuantity());
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010724 ++NI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010725 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010726 // Mark linear parameters.
10727 auto SI = Attr->steps_begin();
10728 auto MI = Attr->modifiers_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010729 for (const Expr *E : Attr->linears()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010730 E = E->IgnoreParenImpCasts();
10731 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010732 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010733 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010734 } else {
10735 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10736 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010737 Pos = ParamPositions[PVD];
10738 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010739 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010740 ParamAttr.Kind = Linear;
10741 if (*SI) {
Fangrui Song407659a2018-11-30 23:41:18 +000010742 Expr::EvalResult Result;
10743 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010744 if (const auto *DRE =
10745 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
10746 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010747 ParamAttr.Kind = LinearWithVarStride;
10748 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(
10749 ParamPositions[StridePVD->getCanonicalDecl()]);
10750 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010751 }
Fangrui Song407659a2018-11-30 23:41:18 +000010752 } else {
10753 ParamAttr.StrideOrArg = Result.Val.getInt();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010754 }
10755 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010756 ++SI;
10757 ++MI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010758 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010759 llvm::APSInt VLENVal;
Alexey Bataeva0a22642019-04-16 13:56:21 +000010760 SourceLocation ExprLoc;
10761 const Expr *VLENExpr = Attr->getSimdlen();
10762 if (VLENExpr) {
10763 VLENVal = VLENExpr->EvaluateKnownConstInt(C);
10764 ExprLoc = VLENExpr->getExprLoc();
10765 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010766 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
10767 if (CGM.getTriple().getArch() == llvm::Triple::x86 ||
Alexey Bataeva0a22642019-04-16 13:56:21 +000010768 CGM.getTriple().getArch() == llvm::Triple::x86_64) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010769 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
Alexey Bataeva0a22642019-04-16 13:56:21 +000010770 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) {
10771 unsigned VLEN = VLENVal.getExtValue();
10772 StringRef MangledName = Fn->getName();
10773 if (CGM.getTarget().hasFeature("sve"))
10774 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10775 MangledName, 's', 128, Fn, ExprLoc);
10776 if (CGM.getTarget().hasFeature("neon"))
10777 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10778 MangledName, 'n', 128, Fn, ExprLoc);
10779 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010780 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010781 FD = FD->getPreviousDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010782 }
10783}
Alexey Bataev8b427062016-05-25 12:36:08 +000010784
10785namespace {
10786/// Cleanup action for doacross support.
10787class DoacrossCleanupTy final : public EHScopeStack::Cleanup {
10788public:
10789 static const int DoacrossFinArgs = 2;
10790
10791private:
James Y Knight9871db02019-02-05 16:42:33 +000010792 llvm::FunctionCallee RTLFn;
Alexey Bataev8b427062016-05-25 12:36:08 +000010793 llvm::Value *Args[DoacrossFinArgs];
10794
10795public:
James Y Knight9871db02019-02-05 16:42:33 +000010796 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
10797 ArrayRef<llvm::Value *> CallArgs)
Alexey Bataev8b427062016-05-25 12:36:08 +000010798 : RTLFn(RTLFn) {
10799 assert(CallArgs.size() == DoacrossFinArgs);
10800 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10801 }
10802 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10803 if (!CGF.HaveInsertPoint())
10804 return;
10805 CGF.EmitRuntimeCall(RTLFn, Args);
10806 }
10807};
10808} // namespace
10809
10810void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000010811 const OMPLoopDirective &D,
10812 ArrayRef<Expr *> NumIterations) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010813 if (!CGF.HaveInsertPoint())
10814 return;
10815
10816 ASTContext &C = CGM.getContext();
10817 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
10818 RecordDecl *RD;
10819 if (KmpDimTy.isNull()) {
10820 // Build struct kmp_dim { // loop bounds info casted to kmp_int64
10821 // kmp_int64 lo; // lower
10822 // kmp_int64 up; // upper
10823 // kmp_int64 st; // stride
10824 // };
10825 RD = C.buildImplicitRecord("kmp_dim");
10826 RD->startDefinition();
10827 addFieldToRecordDecl(C, RD, Int64Ty);
10828 addFieldToRecordDecl(C, RD, Int64Ty);
10829 addFieldToRecordDecl(C, RD, Int64Ty);
10830 RD->completeDefinition();
10831 KmpDimTy = C.getRecordType(RD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010832 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010833 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010834 }
Alexey Bataevf138fda2018-08-13 19:04:24 +000010835 llvm::APInt Size(/*numBits=*/32, NumIterations.size());
10836 QualType ArrayTy =
Richard Smith772e2662019-10-04 01:25:59 +000010837 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0);
Alexey Bataev8b427062016-05-25 12:36:08 +000010838
Alexey Bataevf138fda2018-08-13 19:04:24 +000010839 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
10840 CGF.EmitNullInitialization(DimsAddr, ArrayTy);
Alexey Bataev8b427062016-05-25 12:36:08 +000010841 enum { LowerFD = 0, UpperFD, StrideFD };
10842 // Fill dims with data.
Alexey Bataevf138fda2018-08-13 19:04:24 +000010843 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +000010844 LValue DimsLVal = CGF.MakeAddrLValue(
10845 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010846 // dims.upper = num_iterations;
10847 LValue UpperLVal = CGF.EmitLValueForField(
10848 DimsLVal, *std::next(RD->field_begin(), UpperFD));
10849 llvm::Value *NumIterVal =
10850 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]),
10851 D.getNumIterations()->getType(), Int64Ty,
10852 D.getNumIterations()->getExprLoc());
10853 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
10854 // dims.stride = 1;
10855 LValue StrideLVal = CGF.EmitLValueForField(
10856 DimsLVal, *std::next(RD->field_begin(), StrideFD));
10857 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
10858 StrideLVal);
10859 }
Alexey Bataev8b427062016-05-25 12:36:08 +000010860
10861 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
10862 // kmp_int32 num_dims, struct kmp_dim * dims);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010863 llvm::Value *Args[] = {
10864 emitUpdateLocation(CGF, D.getBeginLoc()),
10865 getThreadID(CGF, D.getBeginLoc()),
10866 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()),
10867 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knight751fe282019-02-09 22:22:28 +000010868 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(),
Alexey Bataevf138fda2018-08-13 19:04:24 +000010869 CGM.VoidPtrTy)};
Alexey Bataev8b427062016-05-25 12:36:08 +000010870
James Y Knight9871db02019-02-05 16:42:33 +000010871 llvm::FunctionCallee RTLFn =
10872 createRuntimeFunction(OMPRTL__kmpc_doacross_init);
Alexey Bataev8b427062016-05-25 12:36:08 +000010873 CGF.EmitRuntimeCall(RTLFn, Args);
10874 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
Stephen Kelly1c301dc2018-08-09 21:09:38 +000010875 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())};
James Y Knight9871db02019-02-05 16:42:33 +000010876 llvm::FunctionCallee FiniRTLFn =
10877 createRuntimeFunction(OMPRTL__kmpc_doacross_fini);
Alexey Bataev8b427062016-05-25 12:36:08 +000010878 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
10879 llvm::makeArrayRef(FiniArgs));
10880}
10881
10882void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
10883 const OMPDependClause *C) {
10884 QualType Int64Ty =
10885 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010886 llvm::APInt Size(/*numBits=*/32, C->getNumLoops());
10887 QualType ArrayTy = CGM.getContext().getConstantArrayType(
Richard Smith772e2662019-10-04 01:25:59 +000010888 Int64Ty, Size, nullptr, ArrayType::Normal, 0);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010889 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr");
10890 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) {
10891 const Expr *CounterVal = C->getLoopData(I);
10892 assert(CounterVal);
10893 llvm::Value *CntVal = CGF.EmitScalarConversion(
10894 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
10895 CounterVal->getExprLoc());
James Y Knight751fe282019-02-09 22:22:28 +000010896 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I),
10897 /*Volatile=*/false, Int64Ty);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010898 }
10899 llvm::Value *Args[] = {
10900 emitUpdateLocation(CGF, C->getBeginLoc()),
10901 getThreadID(CGF, C->getBeginLoc()),
James Y Knight751fe282019-02-09 22:22:28 +000010902 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()};
James Y Knight9871db02019-02-05 16:42:33 +000010903 llvm::FunctionCallee RTLFn;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010904 if (C->getDependencyKind() == OMPC_DEPEND_source) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010905 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010906 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010907 assert(C->getDependencyKind() == OMPC_DEPEND_sink);
10908 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait);
10909 }
10910 CGF.EmitRuntimeCall(RTLFn, Args);
10911}
10912
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010913void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000010914 llvm::FunctionCallee Callee,
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010915 ArrayRef<llvm::Value *> Args) const {
10916 assert(Loc.isValid() && "Outlined function call location must be valid.");
Alexey Bataev3c595a62017-08-14 15:01:03 +000010917 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
10918
James Y Knight9871db02019-02-05 16:42:33 +000010919 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010920 if (Fn->doesNotThrow()) {
Alexey Bataev3c595a62017-08-14 15:01:03 +000010921 CGF.EmitNounwindRuntimeCall(Fn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010922 return;
10923 }
10924 }
Alexey Bataev3c595a62017-08-14 15:01:03 +000010925 CGF.EmitRuntimeCall(Callee, Args);
10926}
10927
10928void CGOpenMPRuntime::emitOutlinedFunctionCall(
James Y Knight9871db02019-02-05 16:42:33 +000010929 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn,
Alexey Bataev3c595a62017-08-14 15:01:03 +000010930 ArrayRef<llvm::Value *> Args) const {
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010931 emitCall(CGF, Loc, OutlinedFn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010932}
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010933
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +000010934void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) {
10935 if (const auto *FD = dyn_cast<FunctionDecl>(D))
10936 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
10937 HasEmittedDeclareTargetRegion = true;
10938}
10939
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010940Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
10941 const VarDecl *NativeParam,
10942 const VarDecl *TargetParam) const {
10943 return CGF.GetAddrOfLocalVar(NativeParam);
10944}
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010945
Alexey Bataev4f680db2019-03-19 16:41:16 +000010946namespace {
10947/// Cleanup action for allocate support.
10948class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup {
10949public:
10950 static const int CleanupArgs = 3;
10951
10952private:
10953 llvm::FunctionCallee RTLFn;
10954 llvm::Value *Args[CleanupArgs];
10955
10956public:
10957 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
10958 ArrayRef<llvm::Value *> CallArgs)
10959 : RTLFn(RTLFn) {
10960 assert(CallArgs.size() == CleanupArgs &&
10961 "Size of arguments does not match.");
10962 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10963 }
10964 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10965 if (!CGF.HaveInsertPoint())
10966 return;
10967 CGF.EmitRuntimeCall(RTLFn, Args);
10968 }
10969};
10970} // namespace
10971
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000010972Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF,
10973 const VarDecl *VD) {
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010974 if (!VD)
10975 return Address::invalid();
Alexey Bataev4f680db2019-03-19 16:41:16 +000010976 const VarDecl *CVD = VD->getCanonicalDecl();
10977 if (!CVD->hasAttr<OMPAllocateDeclAttr>())
10978 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010979 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
10980 // Use the default allocation.
Alexey Bataev0fd3c682019-04-02 19:44:46 +000010981 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
10982 !AA->getAllocator())
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010983 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010984 llvm::Value *Size;
10985 CharUnits Align = CGM.getContext().getDeclAlign(CVD);
10986 if (CVD->getType()->isVariablyModifiedType()) {
10987 Size = CGF.getTypeSize(CVD->getType());
Alexey Bataev9c397812019-04-03 17:57:06 +000010988 // Align the size: ((size + align - 1) / align) * align
10989 Size = CGF.Builder.CreateNUWAdd(
10990 Size, CGM.getSize(Align - CharUnits::fromQuantity(1)));
10991 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align));
10992 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align));
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010993 } else {
10994 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType());
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010995 Size = CGM.getSize(Sz.alignTo(Align));
Alexey Bataev4f680db2019-03-19 16:41:16 +000010996 }
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010997 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc());
10998 assert(AA->getAllocator() &&
10999 "Expected allocator expression for non-default allocator.");
11000 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator());
Alexey Bataev6cf7b712019-04-08 19:06:42 +000011001 // According to the standard, the original allocator type is a enum (integer).
11002 // Convert to pointer type, if required.
11003 if (Allocator->getType()->isIntegerTy())
11004 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy);
11005 else if (Allocator->getType()->isPointerTy())
11006 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator,
11007 CGM.VoidPtrTy);
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011008 llvm::Value *Args[] = {ThreadID, Size, Allocator};
11009
11010 llvm::Value *Addr =
11011 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args,
11012 CVD->getName() + ".void.addr");
11013 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr,
11014 Allocator};
11015 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free);
11016
11017 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
11018 llvm::makeArrayRef(FiniArgs));
11019 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11020 Addr,
11021 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())),
11022 CVD->getName() + ".addr");
11023 return Address(Addr, Align);
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000011024}
11025
Alexey Bataev2df5f122019-10-01 20:18:32 +000011026/// Checks current context and returns true if it matches the context selector.
11027template <OMPDeclareVariantAttr::CtxSelectorSetType CtxSet,
11028 OMPDeclareVariantAttr::CtxSelectorType Ctx>
11029static bool checkContext(const OMPDeclareVariantAttr *A) {
11030 assert(CtxSet != OMPDeclareVariantAttr::CtxSetUnknown &&
11031 Ctx != OMPDeclareVariantAttr::CtxUnknown &&
11032 "Unknown context selector or context selector set.");
11033 return false;
11034}
11035
11036/// Checks for implementation={vendor(<vendor>)} context selector.
11037/// \returns true iff <vendor>="llvm", false otherwise.
11038template <>
11039bool checkContext<OMPDeclareVariantAttr::CtxSetImplementation,
11040 OMPDeclareVariantAttr::CtxVendor>(
11041 const OMPDeclareVariantAttr *A) {
Alexey Bataev303657a2019-10-08 19:44:16 +000011042 return llvm::all_of(A->implVendors(),
11043 [](StringRef S) { return !S.compare_lower("llvm"); });
Alexey Bataev2df5f122019-10-01 20:18:32 +000011044}
11045
Alexey Bataev0364c762019-10-03 20:49:48 +000011046static bool greaterCtxScore(ASTContext &Ctx, const Expr *LHS, const Expr *RHS) {
11047 // If both scores are unknown, choose the very first one.
11048 if (!LHS && !RHS)
11049 return true;
11050 // If only one is known, return this one.
11051 if (LHS && !RHS)
11052 return true;
11053 if (!LHS && RHS)
11054 return false;
11055 llvm::APSInt LHSVal = LHS->EvaluateKnownConstInt(Ctx);
11056 llvm::APSInt RHSVal = RHS->EvaluateKnownConstInt(Ctx);
Alexey Bataevadc38dc2019-10-09 20:54:06 +000011057 return llvm::APSInt::compareValues(LHSVal, RHSVal) >= 0;
Alexey Bataev0364c762019-10-03 20:49:48 +000011058}
11059
11060namespace {
11061/// Comparator for the priority queue for context selector.
11062class OMPDeclareVariantAttrComparer
11063 : public std::greater<const OMPDeclareVariantAttr *> {
11064private:
11065 ASTContext &Ctx;
11066
11067public:
11068 OMPDeclareVariantAttrComparer(ASTContext &Ctx) : Ctx(Ctx) {}
11069 bool operator()(const OMPDeclareVariantAttr *LHS,
11070 const OMPDeclareVariantAttr *RHS) const {
11071 const Expr *LHSExpr = nullptr;
11072 const Expr *RHSExpr = nullptr;
11073 if (LHS->getCtxScore() == OMPDeclareVariantAttr::ScoreSpecified)
11074 LHSExpr = LHS->getScore();
11075 if (RHS->getCtxScore() == OMPDeclareVariantAttr::ScoreSpecified)
11076 RHSExpr = RHS->getScore();
11077 return greaterCtxScore(Ctx, LHSExpr, RHSExpr);
11078 }
11079};
11080} // anonymous namespace
11081
Alexey Bataev2df5f122019-10-01 20:18:32 +000011082/// Finds the variant function that matches current context with its context
11083/// selector.
Alexey Bataev0364c762019-10-03 20:49:48 +000011084static const FunctionDecl *getDeclareVariantFunction(ASTContext &Ctx,
11085 const FunctionDecl *FD) {
Alexey Bataev2df5f122019-10-01 20:18:32 +000011086 if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>())
11087 return FD;
11088 // Iterate through all DeclareVariant attributes and check context selectors.
Alexey Bataev0364c762019-10-03 20:49:48 +000011089 auto &&Comparer = [&Ctx](const OMPDeclareVariantAttr *LHS,
11090 const OMPDeclareVariantAttr *RHS) {
11091 const Expr *LHSExpr = nullptr;
11092 const Expr *RHSExpr = nullptr;
11093 if (LHS->getCtxScore() == OMPDeclareVariantAttr::ScoreSpecified)
11094 LHSExpr = LHS->getScore();
11095 if (RHS->getCtxScore() == OMPDeclareVariantAttr::ScoreSpecified)
11096 RHSExpr = RHS->getScore();
11097 return greaterCtxScore(Ctx, LHSExpr, RHSExpr);
11098 };
11099 const OMPDeclareVariantAttr *TopMostAttr = nullptr;
11100 for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) {
11101 const OMPDeclareVariantAttr *SelectedAttr = nullptr;
Alexey Bataev2df5f122019-10-01 20:18:32 +000011102 switch (A->getCtxSelectorSet()) {
11103 case OMPDeclareVariantAttr::CtxSetImplementation:
11104 switch (A->getCtxSelector()) {
11105 case OMPDeclareVariantAttr::CtxVendor:
11106 if (checkContext<OMPDeclareVariantAttr::CtxSetImplementation,
11107 OMPDeclareVariantAttr::CtxVendor>(A))
Alexey Bataev0364c762019-10-03 20:49:48 +000011108 SelectedAttr = A;
Alexey Bataev2df5f122019-10-01 20:18:32 +000011109 break;
11110 case OMPDeclareVariantAttr::CtxUnknown:
11111 llvm_unreachable(
Alexey Bataev0364c762019-10-03 20:49:48 +000011112 "Unknown context selector in implementation selector set.");
Alexey Bataev2df5f122019-10-01 20:18:32 +000011113 }
11114 break;
11115 case OMPDeclareVariantAttr::CtxSetUnknown:
11116 llvm_unreachable("Unknown context selector set.");
11117 }
Alexey Bataev0364c762019-10-03 20:49:48 +000011118 // If the attribute matches the context, find the attribute with the highest
11119 // score.
Alexey Bataevadc38dc2019-10-09 20:54:06 +000011120 if (SelectedAttr && (!TopMostAttr || !Comparer(TopMostAttr, SelectedAttr)))
Alexey Bataev0364c762019-10-03 20:49:48 +000011121 TopMostAttr = SelectedAttr;
Alexey Bataev2df5f122019-10-01 20:18:32 +000011122 }
Alexey Bataev0364c762019-10-03 20:49:48 +000011123 if (!TopMostAttr)
Alexey Bataev2df5f122019-10-01 20:18:32 +000011124 return FD;
Alexey Bataev2df5f122019-10-01 20:18:32 +000011125 return cast<FunctionDecl>(
Alexey Bataev0364c762019-10-03 20:49:48 +000011126 cast<DeclRefExpr>(TopMostAttr->getVariantFuncRef()->IgnoreParenImpCasts())
Alexey Bataev2df5f122019-10-01 20:18:32 +000011127 ->getDecl());
11128}
11129
11130bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) {
11131 const auto *D = cast<FunctionDecl>(GD.getDecl());
11132 // If the original function is defined already, use its definition.
11133 StringRef MangledName = CGM.getMangledName(GD);
11134 llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName);
11135 if (Orig && !Orig->isDeclaration())
11136 return false;
Alexey Bataev0364c762019-10-03 20:49:48 +000011137 const FunctionDecl *NewFD = getDeclareVariantFunction(CGM.getContext(), D);
Alexey Bataev2df5f122019-10-01 20:18:32 +000011138 // Emit original function if it does not have declare variant attribute or the
11139 // context does not match.
11140 if (NewFD == D)
11141 return false;
11142 GlobalDecl NewGD = GD.getWithDecl(NewFD);
Alexey Bataevc2cd2d42019-10-10 17:28:10 +000011143 if (tryEmitDeclareVariant(NewGD, GD, Orig, IsForDefinition)) {
Alexey Bataev2df5f122019-10-01 20:18:32 +000011144 DeferredVariantFunction.erase(D);
11145 return true;
11146 }
11147 DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD)));
11148 return true;
11149}
11150
James Y Knight9871db02019-02-05 16:42:33 +000011151llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011152 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11153 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11154 llvm_unreachable("Not supported in SIMD-only mode");
11155}
11156
James Y Knight9871db02019-02-05 16:42:33 +000011157llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011158 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11159 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11160 llvm_unreachable("Not supported in SIMD-only mode");
11161}
11162
James Y Knight9871db02019-02-05 16:42:33 +000011163llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011164 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11165 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
11166 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
11167 bool Tied, unsigned &NumberOfParts) {
11168 llvm_unreachable("Not supported in SIMD-only mode");
11169}
11170
11171void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF,
11172 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000011173 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011174 ArrayRef<llvm::Value *> CapturedVars,
11175 const Expr *IfCond) {
11176 llvm_unreachable("Not supported in SIMD-only mode");
11177}
11178
11179void CGOpenMPSIMDRuntime::emitCriticalRegion(
11180 CodeGenFunction &CGF, StringRef CriticalName,
11181 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
11182 const Expr *Hint) {
11183 llvm_unreachable("Not supported in SIMD-only mode");
11184}
11185
11186void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF,
11187 const RegionCodeGenTy &MasterOpGen,
11188 SourceLocation Loc) {
11189 llvm_unreachable("Not supported in SIMD-only mode");
11190}
11191
11192void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
11193 SourceLocation Loc) {
11194 llvm_unreachable("Not supported in SIMD-only mode");
11195}
11196
11197void CGOpenMPSIMDRuntime::emitTaskgroupRegion(
11198 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen,
11199 SourceLocation Loc) {
11200 llvm_unreachable("Not supported in SIMD-only mode");
11201}
11202
11203void CGOpenMPSIMDRuntime::emitSingleRegion(
11204 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen,
11205 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars,
11206 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs,
11207 ArrayRef<const Expr *> AssignmentOps) {
11208 llvm_unreachable("Not supported in SIMD-only mode");
11209}
11210
11211void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF,
11212 const RegionCodeGenTy &OrderedOpGen,
11213 SourceLocation Loc,
11214 bool IsThreads) {
11215 llvm_unreachable("Not supported in SIMD-only mode");
11216}
11217
11218void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF,
11219 SourceLocation Loc,
11220 OpenMPDirectiveKind Kind,
11221 bool EmitChecks,
11222 bool ForceSimpleCall) {
11223 llvm_unreachable("Not supported in SIMD-only mode");
11224}
11225
11226void CGOpenMPSIMDRuntime::emitForDispatchInit(
11227 CodeGenFunction &CGF, SourceLocation Loc,
11228 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
11229 bool Ordered, const DispatchRTInput &DispatchValues) {
11230 llvm_unreachable("Not supported in SIMD-only mode");
11231}
11232
11233void CGOpenMPSIMDRuntime::emitForStaticInit(
11234 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind,
11235 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) {
11236 llvm_unreachable("Not supported in SIMD-only mode");
11237}
11238
11239void CGOpenMPSIMDRuntime::emitDistributeStaticInit(
11240 CodeGenFunction &CGF, SourceLocation Loc,
11241 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) {
11242 llvm_unreachable("Not supported in SIMD-only mode");
11243}
11244
11245void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
11246 SourceLocation Loc,
11247 unsigned IVSize,
11248 bool IVSigned) {
11249 llvm_unreachable("Not supported in SIMD-only mode");
11250}
11251
11252void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF,
11253 SourceLocation Loc,
11254 OpenMPDirectiveKind DKind) {
11255 llvm_unreachable("Not supported in SIMD-only mode");
11256}
11257
11258llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF,
11259 SourceLocation Loc,
11260 unsigned IVSize, bool IVSigned,
11261 Address IL, Address LB,
11262 Address UB, Address ST) {
11263 llvm_unreachable("Not supported in SIMD-only mode");
11264}
11265
11266void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
11267 llvm::Value *NumThreads,
11268 SourceLocation Loc) {
11269 llvm_unreachable("Not supported in SIMD-only mode");
11270}
11271
11272void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF,
11273 OpenMPProcBindClauseKind ProcBind,
11274 SourceLocation Loc) {
11275 llvm_unreachable("Not supported in SIMD-only mode");
11276}
11277
11278Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
11279 const VarDecl *VD,
11280 Address VDAddr,
11281 SourceLocation Loc) {
11282 llvm_unreachable("Not supported in SIMD-only mode");
11283}
11284
11285llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition(
11286 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit,
11287 CodeGenFunction *CGF) {
11288 llvm_unreachable("Not supported in SIMD-only mode");
11289}
11290
11291Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate(
11292 CodeGenFunction &CGF, QualType VarType, StringRef Name) {
11293 llvm_unreachable("Not supported in SIMD-only mode");
11294}
11295
11296void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF,
11297 ArrayRef<const Expr *> Vars,
11298 SourceLocation Loc) {
11299 llvm_unreachable("Not supported in SIMD-only mode");
11300}
11301
11302void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
11303 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000011304 llvm::Function *TaskFunction,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011305 QualType SharedsTy, Address Shareds,
11306 const Expr *IfCond,
11307 const OMPTaskDataTy &Data) {
11308 llvm_unreachable("Not supported in SIMD-only mode");
11309}
11310
11311void CGOpenMPSIMDRuntime::emitTaskLoopCall(
11312 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000011313 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011314 const Expr *IfCond, const OMPTaskDataTy &Data) {
11315 llvm_unreachable("Not supported in SIMD-only mode");
11316}
11317
11318void CGOpenMPSIMDRuntime::emitReduction(
11319 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates,
11320 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
11321 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) {
11322 assert(Options.SimpleReduction && "Only simple reduction is expected.");
11323 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
11324 ReductionOps, Options);
11325}
11326
11327llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit(
11328 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
11329 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
11330 llvm_unreachable("Not supported in SIMD-only mode");
11331}
11332
11333void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
11334 SourceLocation Loc,
11335 ReductionCodeGen &RCG,
11336 unsigned N) {
11337 llvm_unreachable("Not supported in SIMD-only mode");
11338}
11339
11340Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
11341 SourceLocation Loc,
11342 llvm::Value *ReductionsPtr,
11343 LValue SharedLVal) {
11344 llvm_unreachable("Not supported in SIMD-only mode");
11345}
11346
11347void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
11348 SourceLocation Loc) {
11349 llvm_unreachable("Not supported in SIMD-only mode");
11350}
11351
11352void CGOpenMPSIMDRuntime::emitCancellationPointCall(
11353 CodeGenFunction &CGF, SourceLocation Loc,
11354 OpenMPDirectiveKind CancelRegion) {
11355 llvm_unreachable("Not supported in SIMD-only mode");
11356}
11357
11358void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF,
11359 SourceLocation Loc, const Expr *IfCond,
11360 OpenMPDirectiveKind CancelRegion) {
11361 llvm_unreachable("Not supported in SIMD-only mode");
11362}
11363
11364void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction(
11365 const OMPExecutableDirective &D, StringRef ParentName,
11366 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
11367 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
11368 llvm_unreachable("Not supported in SIMD-only mode");
11369}
11370
Alexey Bataevec7946e2019-09-23 14:06:51 +000011371void CGOpenMPSIMDRuntime::emitTargetCall(
11372 CodeGenFunction &CGF, const OMPExecutableDirective &D,
11373 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
11374 const Expr *Device,
11375 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
11376 const OMPLoopDirective &D)>
11377 SizeEmitter) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011378 llvm_unreachable("Not supported in SIMD-only mode");
11379}
11380
11381bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) {
11382 llvm_unreachable("Not supported in SIMD-only mode");
11383}
11384
11385bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
11386 llvm_unreachable("Not supported in SIMD-only mode");
11387}
11388
11389bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) {
11390 return false;
11391}
11392
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011393void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF,
11394 const OMPExecutableDirective &D,
11395 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000011396 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011397 ArrayRef<llvm::Value *> CapturedVars) {
11398 llvm_unreachable("Not supported in SIMD-only mode");
11399}
11400
11401void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
11402 const Expr *NumTeams,
11403 const Expr *ThreadLimit,
11404 SourceLocation Loc) {
11405 llvm_unreachable("Not supported in SIMD-only mode");
11406}
11407
11408void CGOpenMPSIMDRuntime::emitTargetDataCalls(
11409 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
11410 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
11411 llvm_unreachable("Not supported in SIMD-only mode");
11412}
11413
11414void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
11415 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
11416 const Expr *Device) {
11417 llvm_unreachable("Not supported in SIMD-only mode");
11418}
11419
11420void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000011421 const OMPLoopDirective &D,
11422 ArrayRef<Expr *> NumIterations) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011423 llvm_unreachable("Not supported in SIMD-only mode");
11424}
11425
11426void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
11427 const OMPDependClause *C) {
11428 llvm_unreachable("Not supported in SIMD-only mode");
11429}
11430
11431const VarDecl *
11432CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD,
11433 const VarDecl *NativeParam) const {
11434 llvm_unreachable("Not supported in SIMD-only mode");
11435}
11436
11437Address
11438CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF,
11439 const VarDecl *NativeParam,
11440 const VarDecl *TargetParam) const {
11441 llvm_unreachable("Not supported in SIMD-only mode");
11442}