blob: 27e7175da841f62ca9e57c131ab65f2e5a4fdd18 [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,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000755};
756
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000757/// A basic class for pre|post-action for advanced codegen sequence for OpenMP
758/// region.
759class CleanupTy final : public EHScopeStack::Cleanup {
760 PrePostActionTy *Action;
761
762public:
763 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
764 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
765 if (!CGF.HaveInsertPoint())
766 return;
767 Action->Exit(CGF);
768 }
769};
770
Hans Wennborg7eb54642015-09-10 17:07:54 +0000771} // anonymous namespace
Alexey Bataev18095712014-10-10 12:19:54 +0000772
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000773void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const {
774 CodeGenFunction::RunCleanupsScope Scope(CGF);
775 if (PrePostAction) {
776 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction);
777 Callback(CodeGen, CGF, *PrePostAction);
778 } else {
779 PrePostActionTy Action;
780 Callback(CodeGen, CGF, Action);
781 }
782}
783
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000784/// Check if the combiner is a call to UDR combiner and if it is so return the
785/// UDR decl used for reduction.
786static const OMPDeclareReductionDecl *
787getReductionInit(const Expr *ReductionOp) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000788 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
789 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
790 if (const auto *DRE =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000791 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000792 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000793 return DRD;
794 return nullptr;
795}
796
797static void emitInitWithReductionInitializer(CodeGenFunction &CGF,
798 const OMPDeclareReductionDecl *DRD,
799 const Expr *InitOp,
800 Address Private, Address Original,
801 QualType Ty) {
802 if (DRD->getInitializer()) {
803 std::pair<llvm::Function *, llvm::Function *> Reduction =
804 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000805 const auto *CE = cast<CallExpr>(InitOp);
806 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000807 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
808 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000809 const auto *LHSDRE =
810 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr());
811 const auto *RHSDRE =
812 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000813 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
814 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000815 [=]() { return Private; });
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000816 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000817 [=]() { return Original; });
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000818 (void)PrivateScope.Privatize();
819 RValue Func = RValue::get(Reduction.second);
820 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
821 CGF.EmitIgnoredExpr(InitOp);
822 } else {
823 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty);
Alexey Bataev18fa2322018-05-02 14:20:50 +0000824 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"});
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000825 auto *GV = new llvm::GlobalVariable(
826 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,
Alexey Bataev18fa2322018-05-02 14:20:50 +0000827 llvm::GlobalValue::PrivateLinkage, Init, Name);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000828 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty);
829 RValue InitRVal;
830 switch (CGF.getEvaluationKind(Ty)) {
831 case TEK_Scalar:
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000832 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000833 break;
834 case TEK_Complex:
835 InitRVal =
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000836 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation()));
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000837 break;
838 case TEK_Aggregate:
839 InitRVal = RValue::getAggregate(LV.getAddress());
840 break;
841 }
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000842 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000843 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal);
844 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(),
845 /*IsInitializer=*/false);
846 }
847}
848
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000849/// Emit initialization of arrays of complex types.
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000850/// \param DestAddr Address of the array.
851/// \param Type Type of array.
852/// \param Init Initial expression of array.
853/// \param SrcAddr Address of the original array.
854static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
Alexey Bataeva7b19152017-10-12 20:03:39 +0000855 QualType Type, bool EmitDeclareReductionInit,
856 const Expr *Init,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000857 const OMPDeclareReductionDecl *DRD,
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000858 Address SrcAddr = Address::invalid()) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000859 // Perform element-by-element initialization.
860 QualType ElementTy;
861
862 // Drill down to the base element type on both arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000863 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
864 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000865 DestAddr =
866 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType());
867 if (DRD)
868 SrcAddr =
869 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType());
870
871 llvm::Value *SrcBegin = nullptr;
872 if (DRD)
873 SrcBegin = SrcAddr.getPointer();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000874 llvm::Value *DestBegin = DestAddr.getPointer();
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000875 // Cast from pointer to array type to pointer to single element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000876 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000877 // The basic structure here is a while-do loop.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000878 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body");
879 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done");
880 llvm::Value *IsEmpty =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000881 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty");
882 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
883
884 // Enter the loop body, making that address the current address.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000885 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000886 CGF.EmitBlock(BodyBB);
887
888 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
889
890 llvm::PHINode *SrcElementPHI = nullptr;
891 Address SrcElementCurrent = Address::invalid();
892 if (DRD) {
893 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2,
894 "omp.arraycpy.srcElementPast");
895 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
896 SrcElementCurrent =
897 Address(SrcElementPHI,
898 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
899 }
900 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI(
901 DestBegin->getType(), 2, "omp.arraycpy.destElementPast");
902 DestElementPHI->addIncoming(DestBegin, EntryBB);
903 Address DestElementCurrent =
904 Address(DestElementPHI,
905 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize));
906
907 // Emit copy.
908 {
909 CodeGenFunction::RunCleanupsScope InitScope(CGF);
Alexey Bataeva7b19152017-10-12 20:03:39 +0000910 if (EmitDeclareReductionInit) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000911 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent,
912 SrcElementCurrent, ElementTy);
913 } else
914 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(),
915 /*IsInitializer=*/false);
916 }
917
918 if (DRD) {
919 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000920 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000921 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
922 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock());
923 }
924
925 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000926 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000927 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
928 // Check whether we've reached the end.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000929 llvm::Value *Done =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000930 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
931 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
932 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock());
933
934 // Done.
935 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
936}
937
938LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) {
Alexey Bataevf47c4b42017-09-26 13:47:31 +0000939 return CGF.EmitOMPSharedLValue(E);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000940}
941
942LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF,
943 const Expr *E) {
944 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E))
945 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false);
946 return LValue();
947}
948
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000949void ReductionCodeGen::emitAggregateInitialization(
950 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal,
951 const OMPDeclareReductionDecl *DRD) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000952 // Emit VarDecl with copy init for arrays.
953 // Get the address of the original variable captured in current
954 // captured region.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000955 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000956 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
Alexey Bataeva7b19152017-10-12 20:03:39 +0000957 bool EmitDeclareReductionInit =
958 DRD && (DRD->getInitializer() || !PrivateVD->hasInit());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000959 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(),
Alexey Bataeva7b19152017-10-12 20:03:39 +0000960 EmitDeclareReductionInit,
961 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
962 : PrivateVD->getInit(),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000963 DRD, SharedLVal.getAddress());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000964}
965
966ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds,
967 ArrayRef<const Expr *> Privates,
968 ArrayRef<const Expr *> ReductionOps) {
969 ClausesData.reserve(Shareds.size());
970 SharedAddresses.reserve(Shareds.size());
971 Sizes.reserve(Shareds.size());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000972 BaseDecls.reserve(Shareds.size());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000973 auto IPriv = Privates.begin();
974 auto IRed = ReductionOps.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000975 for (const Expr *Ref : Shareds) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000976 ClausesData.emplace_back(Ref, *IPriv, *IRed);
977 std::advance(IPriv, 1);
978 std::advance(IRed, 1);
979 }
980}
981
982void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) {
983 assert(SharedAddresses.size() == N &&
984 "Number of generated lvalues must be exactly N.");
Jonas Hahnfeld4525c822017-10-23 19:01:35 +0000985 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
986 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
987 SharedAddresses.emplace_back(First, Second);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000988}
989
990void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000991 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000992 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
993 QualType PrivateType = PrivateVD->getType();
994 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref);
Jonas Hahnfeld4525c822017-10-23 19:01:35 +0000995 if (!PrivateType->isVariablyModifiedType()) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000996 Sizes.emplace_back(
997 CGF.getTypeSize(
998 SharedAddresses[N].first.getType().getNonReferenceType()),
999 nullptr);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001000 return;
1001 }
1002 llvm::Value *Size;
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001003 llvm::Value *SizeInChars;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001004 auto *ElemType =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001005 cast<llvm::PointerType>(SharedAddresses[N].first.getPointer()->getType())
1006 ->getElementType();
1007 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001008 if (AsArraySection) {
1009 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(),
1010 SharedAddresses[N].first.getPointer());
1011 Size = CGF.Builder.CreateNUWAdd(
1012 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001013 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001014 } else {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001015 SizeInChars = CGF.getTypeSize(
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001016 SharedAddresses[N].first.getType().getNonReferenceType());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001017 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001018 }
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001019 Sizes.emplace_back(SizeInChars, Size);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001020 CodeGenFunction::OpaqueValueMapping OpaqueMap(
1021 CGF,
1022 cast<OpaqueValueExpr>(
1023 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),
1024 RValue::get(Size));
1025 CGF.EmitVariablyModifiedType(PrivateType);
1026}
1027
1028void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N,
1029 llvm::Value *Size) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001030 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001031 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1032 QualType PrivateType = PrivateVD->getType();
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001033 if (!PrivateType->isVariablyModifiedType()) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001034 assert(!Size && !Sizes[N].second &&
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001035 "Size should be nullptr for non-variably modified reduction "
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001036 "items.");
1037 return;
1038 }
1039 CodeGenFunction::OpaqueValueMapping OpaqueMap(
1040 CGF,
1041 cast<OpaqueValueExpr>(
1042 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),
1043 RValue::get(Size));
1044 CGF.EmitVariablyModifiedType(PrivateType);
1045}
1046
1047void ReductionCodeGen::emitInitialization(
1048 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal,
1049 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) {
1050 assert(SharedAddresses.size() > N && "No variable was generated");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001051 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001052 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001053 const OMPDeclareReductionDecl *DRD =
1054 getReductionInit(ClausesData[N].ReductionOp);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001055 QualType PrivateType = PrivateVD->getType();
1056 PrivateAddr = CGF.Builder.CreateElementBitCast(
1057 PrivateAddr, CGF.ConvertTypeForMem(PrivateType));
1058 QualType SharedType = SharedAddresses[N].first.getType();
1059 SharedLVal = CGF.MakeAddrLValue(
1060 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(),
1061 CGF.ConvertTypeForMem(SharedType)),
Ivan A. Kosarevf5f20462017-10-12 11:29:46 +00001062 SharedType, SharedAddresses[N].first.getBaseInfo(),
Ivan A. Kosarevb9c59f32017-10-31 11:05:34 +00001063 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType));
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001064 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001065 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001066 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) {
1067 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp,
1068 PrivateAddr, SharedLVal.getAddress(),
1069 SharedLVal.getType());
1070 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
1071 !CGF.isTrivialInitializer(PrivateVD->getInit())) {
1072 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr,
1073 PrivateVD->getType().getQualifiers(),
1074 /*IsInitializer=*/false);
1075 }
1076}
1077
1078bool ReductionCodeGen::needCleanups(unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001079 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001080 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1081 QualType PrivateType = PrivateVD->getType();
1082 QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
1083 return DTorKind != QualType::DK_none;
1084}
1085
1086void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N,
1087 Address PrivateAddr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001088 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001089 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1090 QualType PrivateType = PrivateVD->getType();
1091 QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
1092 if (needCleanups(N)) {
1093 PrivateAddr = CGF.Builder.CreateElementBitCast(
1094 PrivateAddr, CGF.ConvertTypeForMem(PrivateType));
1095 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType);
1096 }
1097}
1098
1099static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
1100 LValue BaseLV) {
1101 BaseTy = BaseTy.getNonReferenceType();
1102 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
1103 !CGF.getContext().hasSameType(BaseTy, ElTy)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001104 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001105 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(), PtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001106 } else {
Ivan A. Kosarev9f9d1572017-10-30 11:49:31 +00001107 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(), BaseTy);
1108 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001109 }
1110 BaseTy = BaseTy->getPointeeType();
1111 }
1112 return CGF.MakeAddrLValue(
1113 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(),
1114 CGF.ConvertTypeForMem(ElTy)),
Ivan A. Kosarevf5f20462017-10-12 11:29:46 +00001115 BaseLV.getType(), BaseLV.getBaseInfo(),
Ivan A. Kosarevb9c59f32017-10-31 11:05:34 +00001116 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType()));
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001117}
1118
1119static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
1120 llvm::Type *BaseLVType, CharUnits BaseLVAlignment,
1121 llvm::Value *Addr) {
1122 Address Tmp = Address::invalid();
1123 Address TopTmp = Address::invalid();
1124 Address MostTopTmp = Address::invalid();
1125 BaseTy = BaseTy.getNonReferenceType();
1126 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
1127 !CGF.getContext().hasSameType(BaseTy, ElTy)) {
1128 Tmp = CGF.CreateMemTemp(BaseTy);
1129 if (TopTmp.isValid())
1130 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp);
1131 else
1132 MostTopTmp = Tmp;
1133 TopTmp = Tmp;
1134 BaseTy = BaseTy->getPointeeType();
1135 }
1136 llvm::Type *Ty = BaseLVType;
1137 if (Tmp.isValid())
1138 Ty = Tmp.getElementType();
1139 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty);
1140 if (Tmp.isValid()) {
1141 CGF.Builder.CreateStore(Addr, Tmp);
1142 return MostTopTmp;
1143 }
1144 return Address(Addr, BaseLVAlignment);
1145}
1146
Alexey Bataev1c44e152018-03-06 18:59:43 +00001147static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001148 const VarDecl *OrigVD = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001149 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) {
1150 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
1151 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001152 Base = TempOASE->getBase()->IgnoreParenImpCasts();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001153 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001154 Base = TempASE->getBase()->IgnoreParenImpCasts();
1155 DE = cast<DeclRefExpr>(Base);
1156 OrigVD = cast<VarDecl>(DE->getDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001157 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
1158 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
1159 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001160 Base = TempASE->getBase()->IgnoreParenImpCasts();
1161 DE = cast<DeclRefExpr>(Base);
1162 OrigVD = cast<VarDecl>(DE->getDecl());
1163 }
Alexey Bataev1c44e152018-03-06 18:59:43 +00001164 return OrigVD;
1165}
1166
1167Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N,
1168 Address PrivateAddr) {
1169 const DeclRefExpr *DE;
1170 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001171 BaseDecls.emplace_back(OrigVD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001172 LValue OriginalBaseLValue = CGF.EmitLValue(DE);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001173 LValue BaseLValue =
1174 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
1175 OriginalBaseLValue);
1176 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff(
1177 BaseLValue.getPointer(), SharedAddresses[N].first.getPointer());
Jonas Hahnfeld273d2612017-12-06 19:15:28 +00001178 llvm::Value *PrivatePointer =
1179 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1180 PrivateAddr.getPointer(),
1181 SharedAddresses[N].first.getAddress().getType());
1182 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001183 return castToBase(CGF, OrigVD->getType(),
1184 SharedAddresses[N].first.getType(),
Jonas Hahnfeld273d2612017-12-06 19:15:28 +00001185 OriginalBaseLValue.getAddress().getType(),
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001186 OriginalBaseLValue.getAlignment(), Ptr);
1187 }
1188 BaseDecls.emplace_back(
1189 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl()));
1190 return PrivateAddr;
1191}
1192
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001193bool ReductionCodeGen::usesReductionInitializer(unsigned N) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001194 const OMPDeclareReductionDecl *DRD =
1195 getReductionInit(ClausesData[N].ReductionOp);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001196 return DRD && DRD->getInitializer();
1197}
1198
Alexey Bataev18095712014-10-10 12:19:54 +00001199LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
Alexey Bataev31300ed2016-02-04 11:27:03 +00001200 return CGF.EmitLoadOfPointerLValue(
1201 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
1202 getThreadIDVariable()->getType()->castAs<PointerType>());
Alexey Bataev18095712014-10-10 12:19:54 +00001203}
1204
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001205void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001206 if (!CGF.HaveInsertPoint())
1207 return;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001208 // 1.2.2 OpenMP Language Terminology
1209 // Structured block - An executable statement with a single entry at the
1210 // top and a single exit at the bottom.
1211 // The point of exit cannot be a branch out of the structured block.
1212 // longjmp() and throw() must not violate the entry/exit criteria.
1213 CGF.EHStack.pushTerminate();
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001214 CodeGen(CGF);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001215 CGF.EHStack.popTerminate();
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001216}
1217
Alexey Bataev62b63b12015-03-10 07:28:44 +00001218LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1219 CodeGenFunction &CGF) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00001220 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()),
1221 getThreadIDVariable()->getType(),
Ivan A. Kosarev5f8c0ca2017-10-10 09:39:32 +00001222 AlignmentSource::Decl);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001223}
1224
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001225static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
1226 QualType FieldTy) {
1227 auto *Field = FieldDecl::Create(
1228 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
1229 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
1230 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
1231 Field->setAccess(AS_public);
1232 DC->addDecl(Field);
1233 return Field;
1234}
1235
Alexey Bataev18fa2322018-05-02 14:20:50 +00001236CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator,
1237 StringRef Separator)
1238 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator),
1239 OffloadEntriesInfoManager(CGM) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001240 ASTContext &C = CGM.getContext();
1241 RecordDecl *RD = C.buildImplicitRecord("ident_t");
1242 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
1243 RD->startDefinition();
1244 // reserved_1
1245 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1246 // flags
1247 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1248 // reserved_2
1249 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1250 // reserved_3
1251 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1252 // psource
1253 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
1254 RD->completeDefinition();
1255 IdentQTy = C.getRecordType(RD);
1256 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001257 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
Samuel Antaoee8fb302016-01-06 13:42:12 +00001258
1259 loadOffloadInfoMetadata();
Alexey Bataev9959db52014-05-06 10:08:46 +00001260}
1261
Alexey Bataev91797552015-03-18 04:13:55 +00001262void CGOpenMPRuntime::clear() {
1263 InternalVars.clear();
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00001264 // Clean non-target variable declarations possibly used only in debug info.
1265 for (const auto &Data : EmittedNonTargetVariables) {
1266 if (!Data.getValue().pointsToAliveValue())
1267 continue;
1268 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue());
1269 if (!GV)
1270 continue;
1271 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1272 continue;
1273 GV->eraseFromParent();
1274 }
Alexey Bataev91797552015-03-18 04:13:55 +00001275}
1276
Alexey Bataev18fa2322018-05-02 14:20:50 +00001277std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const {
1278 SmallString<128> Buffer;
1279 llvm::raw_svector_ostream OS(Buffer);
1280 StringRef Sep = FirstSeparator;
1281 for (StringRef Part : Parts) {
1282 OS << Sep << Part;
1283 Sep = Separator;
1284 }
1285 return OS.str();
1286}
1287
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001288static llvm::Function *
1289emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
1290 const Expr *CombinerInitializer, const VarDecl *In,
1291 const VarDecl *Out, bool IsCombiner) {
1292 // void .omp_combiner.(Ty *in, Ty *out);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001293 ASTContext &C = CGM.getContext();
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001294 QualType PtrTy = C.getPointerType(Ty).withRestrict();
1295 FunctionArgList Args;
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001296 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(),
Alexey Bataev56223232017-06-09 13:40:18 +00001297 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001298 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(),
Alexey Bataev56223232017-06-09 13:40:18 +00001299 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001300 Args.push_back(&OmpOutParm);
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001301 Args.push_back(&OmpInParm);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001302 const CGFunctionInfo &FnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00001303 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001304 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00001305 std::string Name = CGM.getOpenMPRuntime().getName(
1306 {IsCombiner ? "omp_combiner" : "omp_initializer", ""});
1307 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1308 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00001309 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataev8c5555c2019-05-21 15:11:58 +00001310 if (CGM.getLangOpts().Optimize) {
1311 Fn->removeFnAttr(llvm::Attribute::NoInline);
1312 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1313 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1314 }
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001315 CodeGenFunction CGF(CGM);
1316 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
1317 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions.
Alexey Bataev7cae94e2018-01-04 19:45:16 +00001318 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(),
1319 Out->getLocation());
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001320 CodeGenFunction::OMPPrivateScope Scope(CGF);
1321 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001322 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() {
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001323 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>())
1324 .getAddress();
1325 });
1326 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001327 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() {
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001328 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>())
1329 .getAddress();
1330 });
1331 (void)Scope.Privatize();
Alexey Bataev070f43a2017-09-06 14:49:58 +00001332 if (!IsCombiner && Out->hasInit() &&
1333 !CGF.isTrivialInitializer(Out->getInit())) {
1334 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out),
1335 Out->getType().getQualifiers(),
1336 /*IsInitializer=*/true);
1337 }
1338 if (CombinerInitializer)
1339 CGF.EmitIgnoredExpr(CombinerInitializer);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001340 Scope.ForceCleanup();
1341 CGF.FinishFunction();
1342 return Fn;
1343}
1344
1345void CGOpenMPRuntime::emitUserDefinedReduction(
1346 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) {
1347 if (UDRMap.count(D) > 0)
1348 return;
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001349 llvm::Function *Combiner = emitCombinerOrInitializer(
Alexey Bataeve6aa4692018-09-13 16:54:05 +00001350 CGM, D->getType(), D->getCombiner(),
1351 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()),
1352 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()),
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001353 /*IsCombiner=*/true);
1354 llvm::Function *Initializer = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001355 if (const Expr *Init = D->getInitializer()) {
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001356 Initializer = emitCombinerOrInitializer(
Alexey Bataev070f43a2017-09-06 14:49:58 +00001357 CGM, D->getType(),
1358 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init
1359 : nullptr,
Alexey Bataeve6aa4692018-09-13 16:54:05 +00001360 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()),
1361 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()),
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001362 /*IsCombiner=*/false);
1363 }
Alexey Bataev43a919f2018-04-13 17:48:43 +00001364 UDRMap.try_emplace(D, Combiner, Initializer);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001365 if (CGF) {
1366 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn);
1367 Decls.second.push_back(D);
1368 }
1369}
1370
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001371std::pair<llvm::Function *, llvm::Function *>
1372CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) {
1373 auto I = UDRMap.find(D);
1374 if (I != UDRMap.end())
1375 return I->second;
1376 emitUserDefinedReduction(/*CGF=*/nullptr, D);
1377 return UDRMap.lookup(D);
1378}
1379
James Y Knight9871db02019-02-05 16:42:33 +00001380static llvm::Function *emitParallelOrTeamsOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001381 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS,
1382 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind,
1383 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00001384 assert(ThreadIDVar->getType()->isPointerType() &&
1385 "thread id variable must be of type kmp_int32 *");
Alexey Bataev18095712014-10-10 12:19:54 +00001386 CodeGenFunction CGF(CGM, true);
Alexey Bataev25e5b442015-09-15 12:52:43 +00001387 bool HasCancel = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001388 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001389 HasCancel = OPD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001390 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001391 HasCancel = OPSD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001392 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001393 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001394 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
Alexey Bataev2139ed62017-11-16 18:20:21 +00001395 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001396 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
Alexey Bataev10a54312017-11-27 16:54:08 +00001397 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001398 else if (const auto *OPFD =
1399 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
Alexey Bataev10a54312017-11-27 16:54:08 +00001400 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001401 else if (const auto *OPFD =
Alexey Bataev10a54312017-11-27 16:54:08 +00001402 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1403 HasCancel = OPFD->hasCancel();
Alexey Bataev25e5b442015-09-15 12:52:43 +00001404 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001405 HasCancel, OutlinedHelperName);
Alexey Bataevd157d472015-06-24 03:35:38 +00001406 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev2377fe92015-09-10 08:12:02 +00001407 return CGF.GenerateOpenMPCapturedStmtFunction(*CS);
Alexey Bataev18095712014-10-10 12:19:54 +00001408}
1409
James Y Knight9871db02019-02-05 16:42:33 +00001410llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001411 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1412 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1413 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1414 return emitParallelOrTeamsOutlinedFunction(
1415 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1416}
1417
James Y Knight9871db02019-02-05 16:42:33 +00001418llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001419 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1420 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1421 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1422 return emitParallelOrTeamsOutlinedFunction(
1423 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1424}
1425
James Y Knight9871db02019-02-05 16:42:33 +00001426llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001427 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
Alexey Bataev48591dd2016-04-20 04:01:36 +00001428 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
1429 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
1430 bool Tied, unsigned &NumberOfParts) {
1431 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF,
1432 PrePostActionTy &) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00001433 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc());
1434 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc());
Alexey Bataev48591dd2016-04-20 04:01:36 +00001435 llvm::Value *TaskArgs[] = {
1436 UpLoc, ThreadID,
1437 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1438 TaskTVar->getType()->castAs<PointerType>())
1439 .getPointer()};
1440 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs);
1441 };
1442 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1443 UntiedCodeGen);
1444 CodeGen.setAction(Action);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001445 assert(!ThreadIDVar->getType()->isPointerType() &&
1446 "thread id variable must be of type kmp_int32 for tasks");
Alexey Bataev475a7442018-01-12 19:39:11 +00001447 const OpenMPDirectiveKind Region =
1448 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop
1449 : OMPD_task;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001450 const CapturedStmt *CS = D.getCapturedStmt(Region);
1451 const auto *TD = dyn_cast<OMPTaskDirective>(&D);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001452 CodeGenFunction CGF(CGM, true);
Alexey Bataev7292c292016-04-25 12:22:29 +00001453 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
1454 InnermostKind,
1455 TD ? TD->hasCancel() : false, Action);
Alexey Bataevd157d472015-06-24 03:35:38 +00001456 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
James Y Knight9871db02019-02-05 16:42:33 +00001457 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
Alexey Bataev48591dd2016-04-20 04:01:36 +00001458 if (!Tied)
1459 NumberOfParts = Action.getNumberOfParts();
1460 return Res;
Alexey Bataev62b63b12015-03-10 07:28:44 +00001461}
1462
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001463static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM,
1464 const RecordDecl *RD, const CGRecordLayout &RL,
1465 ArrayRef<llvm::Constant *> Data) {
1466 llvm::StructType *StructTy = RL.getLLVMType();
1467 unsigned PrevIdx = 0;
1468 ConstantInitBuilder CIBuilder(CGM);
1469 auto DI = Data.begin();
1470 for (const FieldDecl *FD : RD->fields()) {
1471 unsigned Idx = RL.getLLVMFieldNo(FD);
1472 // Fill the alignment.
1473 for (unsigned I = PrevIdx; I < Idx; ++I)
1474 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I)));
1475 PrevIdx = Idx + 1;
1476 Fields.add(*DI);
1477 ++DI;
1478 }
1479}
1480
1481template <class... As>
1482static llvm::GlobalVariable *
Mike Ricee1ca7b62018-08-29 15:45:11 +00001483createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant,
1484 ArrayRef<llvm::Constant *> Data, const Twine &Name,
1485 As &&... Args) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001486 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1487 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1488 ConstantInitBuilder CIBuilder(CGM);
1489 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType());
1490 buildStructValue(Fields, CGM, RD, RL, Data);
1491 return Fields.finishAndCreateGlobal(
Mike Ricee1ca7b62018-08-29 15:45:11 +00001492 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant,
1493 std::forward<As>(Args)...);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001494}
1495
1496template <typename T>
Benjamin Kramer651d0bf2018-05-15 21:26:47 +00001497static void
1498createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty,
1499 ArrayRef<llvm::Constant *> Data,
1500 T &Parent) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001501 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1502 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1503 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType());
1504 buildStructValue(Fields, CGM, RD, RL, Data);
1505 Fields.finishAndAddTo(Parent);
1506}
1507
Alexey Bataev50b3c952016-02-19 10:38:26 +00001508Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001509 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy);
Alexey Bataevceeaa482018-11-21 21:04:34 +00001510 unsigned Reserved2Flags = getDefaultLocationReserved2Flags();
1511 FlagsTy FlagsKey(Flags, Reserved2Flags);
1512 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey);
Alexey Bataev9959db52014-05-06 10:08:46 +00001513 if (!Entry) {
1514 if (!DefaultOpenMPPSource) {
1515 // Initialize default location for psource field of ident_t structure of
1516 // all ident_t objects. Format is ";file;function;line;column;;".
1517 // Taken from
James Y Knight5d71fc52019-01-29 16:37:27 +00001518 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp
Alexey Bataev9959db52014-05-06 10:08:46 +00001519 DefaultOpenMPPSource =
John McCall7f416cc2015-09-08 08:05:57 +00001520 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001521 DefaultOpenMPPSource =
1522 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
1523 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001524
Alexey Bataevceeaa482018-11-21 21:04:34 +00001525 llvm::Constant *Data[] = {
1526 llvm::ConstantInt::getNullValue(CGM.Int32Ty),
1527 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
1528 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags),
1529 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource};
Mike Ricee1ca7b62018-08-29 15:45:11 +00001530 llvm::GlobalValue *DefaultOpenMPLocation =
Alexey Bataevceeaa482018-11-21 21:04:34 +00001531 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "",
Mike Ricee1ca7b62018-08-29 15:45:11 +00001532 llvm::GlobalValue::PrivateLinkage);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001533 DefaultOpenMPLocation->setUnnamedAddr(
1534 llvm::GlobalValue::UnnamedAddr::Global);
John McCall6c9f1fdb2016-11-19 08:17:24 +00001535
Alexey Bataevceeaa482018-11-21 21:04:34 +00001536 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation;
Alexey Bataev9959db52014-05-06 10:08:46 +00001537 }
John McCall7f416cc2015-09-08 08:05:57 +00001538 return Address(Entry, Align);
Alexey Bataev9959db52014-05-06 10:08:46 +00001539}
1540
Alexey Bataevfd006c42018-10-05 15:08:53 +00001541void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF,
1542 bool AtCurrentPoint) {
1543 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1544 assert(!Elem.second.ServiceInsertPt && "Insert point is set already.");
1545
1546 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty);
1547 if (AtCurrentPoint) {
1548 Elem.second.ServiceInsertPt = new llvm::BitCastInst(
1549 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock());
1550 } else {
1551 Elem.second.ServiceInsertPt =
1552 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt");
1553 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt);
1554 }
1555}
1556
1557void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) {
1558 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1559 if (Elem.second.ServiceInsertPt) {
1560 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt;
1561 Elem.second.ServiceInsertPt = nullptr;
1562 Ptr->eraseFromParent();
1563 }
1564}
1565
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001566llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
1567 SourceLocation Loc,
Alexey Bataev50b3c952016-02-19 10:38:26 +00001568 unsigned Flags) {
1569 Flags |= OMP_IDENT_KMPC;
Alexey Bataev9959db52014-05-06 10:08:46 +00001570 // If no debug info is generated - return global default location.
Benjamin Kramer8c305922016-02-02 11:06:51 +00001571 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo ||
Alexey Bataev9959db52014-05-06 10:08:46 +00001572 Loc.isInvalid())
John McCall7f416cc2015-09-08 08:05:57 +00001573 return getOrCreateDefaultLocation(Flags).getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001574
1575 assert(CGF.CurFn && "No function in current CodeGenFunction.");
1576
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001577 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy);
John McCall7f416cc2015-09-08 08:05:57 +00001578 Address LocValue = Address::invalid();
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001579 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
1580 if (I != OpenMPLocThreadIDMap.end())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001581 LocValue = Address(I->second.DebugLoc, Align);
John McCall7f416cc2015-09-08 08:05:57 +00001582
Alexander Musmanc6388682014-12-15 07:07:06 +00001583 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
1584 // GetOpenMPThreadID was called before this routine.
John McCall7f416cc2015-09-08 08:05:57 +00001585 if (!LocValue.isValid()) {
Alexey Bataev15007ba2014-05-07 06:18:01 +00001586 // Generate "ident_t .kmpc_loc.addr;"
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001587 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr");
Alexey Bataev18095712014-10-10 12:19:54 +00001588 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
John McCall7f416cc2015-09-08 08:05:57 +00001589 Elem.second.DebugLoc = AI.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001590 LocValue = AI;
1591
Alexey Bataevfd006c42018-10-05 15:08:53 +00001592 if (!Elem.second.ServiceInsertPt)
1593 setLocThreadIdInsertPt(CGF);
Alexey Bataev9959db52014-05-06 10:08:46 +00001594 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001595 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001596 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001597 CGF.getTypeSize(IdentQTy));
Alexey Bataev9959db52014-05-06 10:08:46 +00001598 }
1599
1600 // char **psource = &.kmpc_loc_<flags>.addr.psource;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001601 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy);
1602 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin();
1603 LValue PSource =
1604 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource));
Alexey Bataev9959db52014-05-06 10:08:46 +00001605
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001606 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
Alexey Bataevf002aca2014-05-30 05:48:40 +00001607 if (OMPDebugLoc == nullptr) {
1608 SmallString<128> Buffer2;
1609 llvm::raw_svector_ostream OS2(Buffer2);
1610 // Build debug location
1611 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
1612 OS2 << ";" << PLoc.getFilename() << ";";
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001613 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl))
Alexey Bataevf002aca2014-05-30 05:48:40 +00001614 OS2 << FD->getQualifiedNameAsString();
Alexey Bataevf002aca2014-05-30 05:48:40 +00001615 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
1616 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
1617 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
Alexey Bataev9959db52014-05-06 10:08:46 +00001618 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001619 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001620 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource);
Alexey Bataevf002aca2014-05-30 05:48:40 +00001621
John McCall7f416cc2015-09-08 08:05:57 +00001622 // Our callers always pass this to a runtime function, so for
1623 // convenience, go ahead and return a naked pointer.
1624 return LocValue.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001625}
1626
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001627llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
1628 SourceLocation Loc) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001629 assert(CGF.CurFn && "No function in current CodeGenFunction.");
1630
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001631 llvm::Value *ThreadID = nullptr;
Alexey Bataev18095712014-10-10 12:19:54 +00001632 // Check whether we've already cached a load of the thread id in this
1633 // function.
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001634 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
Alexey Bataev18095712014-10-10 12:19:54 +00001635 if (I != OpenMPLocThreadIDMap.end()) {
1636 ThreadID = I->second.ThreadID;
Alexey Bataev03b340a2014-10-21 03:16:40 +00001637 if (ThreadID != nullptr)
1638 return ThreadID;
1639 }
Alexey Bataevaee18552017-08-16 14:01:00 +00001640 // If exceptions are enabled, do not use parameter to avoid possible crash.
Alexey Bataev5d2c9a42017-11-02 18:55:05 +00001641 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions ||
1642 !CGF.getLangOpts().CXXExceptions ||
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001643 CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
Alexey Bataevaee18552017-08-16 14:01:00 +00001644 if (auto *OMPRegionInfo =
1645 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
1646 if (OMPRegionInfo->getThreadIDVariable()) {
1647 // Check if this an outlined function with thread id passed as argument.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001648 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
Alexey Bataev1e491372018-01-23 18:44:14 +00001649 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc);
Alexey Bataevaee18552017-08-16 14:01:00 +00001650 // If value loaded in entry block, cache it and use it everywhere in
1651 // function.
1652 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
1653 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1654 Elem.second.ThreadID = ThreadID;
1655 }
1656 return ThreadID;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001657 }
Alexey Bataevd6c57552014-07-25 07:55:17 +00001658 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001659 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001660
1661 // This is not an outlined function region - need to call __kmpc_int32
1662 // kmpc_global_thread_num(ident_t *loc).
1663 // Generate thread id value and cache this value for use across the
1664 // function.
Alexey Bataevfd006c42018-10-05 15:08:53 +00001665 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1666 if (!Elem.second.ServiceInsertPt)
1667 setLocThreadIdInsertPt(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001668 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001669 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001670 llvm::CallInst *Call = CGF.Builder.CreateCall(
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001671 createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
1672 emitUpdateLocation(CGF, Loc));
1673 Call->setCallingConv(CGF.getRuntimeCC());
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001674 Elem.second.ThreadID = Call;
1675 return Call;
Alexey Bataev9959db52014-05-06 10:08:46 +00001676}
1677
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001678void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001679 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataevfd006c42018-10-05 15:08:53 +00001680 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) {
1681 clearLocThreadIdInsertPt(CGF);
Alexey Bataev03b340a2014-10-21 03:16:40 +00001682 OpenMPLocThreadIDMap.erase(CGF.CurFn);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001683 }
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001684 if (FunctionUDRMap.count(CGF.CurFn) > 0) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001685 for(auto *D : FunctionUDRMap[CGF.CurFn])
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001686 UDRMap.erase(D);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001687 FunctionUDRMap.erase(CGF.CurFn);
1688 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001689}
1690
1691llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001692 return IdentTy->getPointerTo();
Alexey Bataev9959db52014-05-06 10:08:46 +00001693}
1694
1695llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001696 if (!Kmpc_MicroTy) {
1697 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
1698 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
1699 llvm::PointerType::getUnqual(CGM.Int32Ty)};
1700 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
1701 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001702 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
1703}
1704
James Y Knight9871db02019-02-05 16:42:33 +00001705llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
1706 llvm::FunctionCallee RTLFn = nullptr;
Alexey Bataev50b3c952016-02-19 10:38:26 +00001707 switch (static_cast<OpenMPRTLFunction>(Function)) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001708 case OMPRTL__kmpc_fork_call: {
1709 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
1710 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +00001711 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1712 getKmpc_MicroPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001713 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001714 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
Alexey Bataev9959db52014-05-06 10:08:46 +00001715 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
James Y Knight9871db02019-02-05 16:42:33 +00001716 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) {
Johannes Doerfertac991bb2019-01-19 05:36:54 +00001717 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
1718 llvm::LLVMContext &Ctx = F->getContext();
1719 llvm::MDBuilder MDB(Ctx);
1720 // Annotate the callback behavior of the __kmpc_fork_call:
1721 // - The callback callee is argument number 2 (microtask).
1722 // - The first two arguments of the callback callee are unknown (-1).
1723 // - All variadic arguments to the __kmpc_fork_call are passed to the
1724 // callback callee.
1725 F->addMetadata(
1726 llvm::LLVMContext::MD_callback,
1727 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
1728 2, {-1, -1},
1729 /* VarArgsArePassed */ true)}));
1730 }
1731 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001732 break;
1733 }
1734 case OMPRTL__kmpc_global_thread_num: {
1735 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +00001736 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001737 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001738 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
Alexey Bataev9959db52014-05-06 10:08:46 +00001739 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
1740 break;
1741 }
Alexey Bataev97720002014-11-11 04:05:39 +00001742 case OMPRTL__kmpc_threadprivate_cached: {
1743 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
1744 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
1745 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1746 CGM.VoidPtrTy, CGM.SizeTy,
1747 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001748 auto *FnTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001749 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
1750 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
1751 break;
1752 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001753 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001754 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
1755 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001756 llvm::Type *TypeParams[] = {
1757 getIdentTyPointerTy(), CGM.Int32Ty,
1758 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001759 auto *FnTy =
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001760 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1761 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
1762 break;
1763 }
Alexey Bataevfc57d162015-12-15 10:55:09 +00001764 case OMPRTL__kmpc_critical_with_hint: {
1765 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid,
1766 // kmp_critical_name *crit, uintptr_t hint);
1767 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1768 llvm::PointerType::getUnqual(KmpCriticalNameTy),
1769 CGM.IntPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001770 auto *FnTy =
Alexey Bataevfc57d162015-12-15 10:55:09 +00001771 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1772 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint");
1773 break;
1774 }
Alexey Bataev97720002014-11-11 04:05:39 +00001775 case OMPRTL__kmpc_threadprivate_register: {
1776 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
1777 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
1778 // typedef void *(*kmpc_ctor)(void *);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001779 auto *KmpcCtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001780 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1781 /*isVarArg*/ false)->getPointerTo();
1782 // typedef void *(*kmpc_cctor)(void *, void *);
1783 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001784 auto *KmpcCopyCtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001785 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001786 /*isVarArg*/ false)
1787 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00001788 // typedef void (*kmpc_dtor)(void *);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001789 auto *KmpcDtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001790 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
1791 ->getPointerTo();
1792 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
1793 KmpcCopyCtorTy, KmpcDtorTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001794 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
Alexey Bataev97720002014-11-11 04:05:39 +00001795 /*isVarArg*/ false);
1796 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
1797 break;
1798 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001799 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001800 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
1801 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001802 llvm::Type *TypeParams[] = {
1803 getIdentTyPointerTy(), CGM.Int32Ty,
1804 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001805 auto *FnTy =
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001806 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1807 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
1808 break;
1809 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001810 case OMPRTL__kmpc_cancel_barrier: {
1811 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
1812 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001813 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001814 auto *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001815 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1816 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001817 break;
1818 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001819 case OMPRTL__kmpc_barrier: {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001820 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001821 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001822 auto *FnTy =
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001823 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1824 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
1825 break;
1826 }
Alexander Musmanc6388682014-12-15 07:07:06 +00001827 case OMPRTL__kmpc_for_static_fini: {
1828 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
1829 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001830 auto *FnTy =
Alexander Musmanc6388682014-12-15 07:07:06 +00001831 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1832 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
1833 break;
1834 }
Alexey Bataevb2059782014-10-13 08:23:51 +00001835 case OMPRTL__kmpc_push_num_threads: {
1836 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
1837 // kmp_int32 num_threads)
1838 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1839 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001840 auto *FnTy =
Alexey Bataevb2059782014-10-13 08:23:51 +00001841 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1842 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
1843 break;
1844 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001845 case OMPRTL__kmpc_serialized_parallel: {
1846 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
1847 // global_tid);
1848 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001849 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001850 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1851 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
1852 break;
1853 }
1854 case OMPRTL__kmpc_end_serialized_parallel: {
1855 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
1856 // global_tid);
1857 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001858 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001859 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1860 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
1861 break;
1862 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001863 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001864 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001865 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001866 auto *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001867 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001868 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
1869 break;
1870 }
Alexey Bataev8d690652014-12-04 07:23:53 +00001871 case OMPRTL__kmpc_master: {
1872 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
1873 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001874 auto *FnTy =
Alexey Bataev8d690652014-12-04 07:23:53 +00001875 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1876 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
1877 break;
1878 }
1879 case OMPRTL__kmpc_end_master: {
1880 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
1881 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001882 auto *FnTy =
Alexey Bataev8d690652014-12-04 07:23:53 +00001883 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1884 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
1885 break;
1886 }
Alexey Bataev9f797f32015-02-05 05:57:51 +00001887 case OMPRTL__kmpc_omp_taskyield: {
1888 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
1889 // int end_part);
1890 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001891 auto *FnTy =
Alexey Bataev9f797f32015-02-05 05:57:51 +00001892 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1893 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
1894 break;
1895 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001896 case OMPRTL__kmpc_single: {
1897 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
1898 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001899 auto *FnTy =
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001900 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1901 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
1902 break;
1903 }
1904 case OMPRTL__kmpc_end_single: {
1905 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
1906 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001907 auto *FnTy =
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001908 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1909 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
1910 break;
1911 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00001912 case OMPRTL__kmpc_omp_task_alloc: {
1913 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
1914 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
1915 // kmp_routine_entry_t *task_entry);
1916 assert(KmpRoutineEntryPtrTy != nullptr &&
1917 "Type kmp_routine_entry_t must be created.");
1918 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1919 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
1920 // Return void * and then cast to particular kmp_task_t type.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001921 auto *FnTy =
Alexey Bataev62b63b12015-03-10 07:28:44 +00001922 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
1923 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
1924 break;
1925 }
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00001926 case OMPRTL__kmpc_omp_target_task_alloc: {
1927 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid,
1928 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
1929 // kmp_routine_entry_t *task_entry, kmp_int64 device_id);
1930 assert(KmpRoutineEntryPtrTy != nullptr &&
1931 "Type kmp_routine_entry_t must be created.");
1932 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1933 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy,
1934 CGM.Int64Ty};
1935 // Return void * and then cast to particular kmp_task_t type.
1936 auto *FnTy =
1937 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
1938 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc");
1939 break;
1940 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00001941 case OMPRTL__kmpc_omp_task: {
1942 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1943 // *new_task);
1944 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1945 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001946 auto *FnTy =
Alexey Bataev62b63b12015-03-10 07:28:44 +00001947 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1948 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
1949 break;
1950 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001951 case OMPRTL__kmpc_copyprivate: {
1952 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
Alexey Bataev66beaa92015-04-30 03:47:32 +00001953 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
Alexey Bataeva63048e2015-03-23 06:18:07 +00001954 // kmp_int32 didit);
1955 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1956 auto *CpyFnTy =
1957 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
Alexey Bataev66beaa92015-04-30 03:47:32 +00001958 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
Alexey Bataeva63048e2015-03-23 06:18:07 +00001959 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
1960 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001961 auto *FnTy =
Alexey Bataeva63048e2015-03-23 06:18:07 +00001962 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1963 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
1964 break;
1965 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001966 case OMPRTL__kmpc_reduce: {
1967 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
1968 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
1969 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
1970 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1971 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
1972 /*isVarArg=*/false);
1973 llvm::Type *TypeParams[] = {
1974 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
1975 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
1976 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001977 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001978 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1979 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
1980 break;
1981 }
1982 case OMPRTL__kmpc_reduce_nowait: {
1983 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
1984 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
1985 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
1986 // *lck);
1987 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1988 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
1989 /*isVarArg=*/false);
1990 llvm::Type *TypeParams[] = {
1991 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
1992 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
1993 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001994 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001995 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1996 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
1997 break;
1998 }
1999 case OMPRTL__kmpc_end_reduce: {
2000 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
2001 // kmp_critical_name *lck);
2002 llvm::Type *TypeParams[] = {
2003 getIdentTyPointerTy(), CGM.Int32Ty,
2004 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002005 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002006 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2007 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
2008 break;
2009 }
2010 case OMPRTL__kmpc_end_reduce_nowait: {
2011 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
2012 // kmp_critical_name *lck);
2013 llvm::Type *TypeParams[] = {
2014 getIdentTyPointerTy(), CGM.Int32Ty,
2015 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002016 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002017 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2018 RTLFn =
2019 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
2020 break;
2021 }
Alexey Bataev1d677132015-04-22 13:57:31 +00002022 case OMPRTL__kmpc_omp_task_begin_if0: {
2023 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2024 // *new_task);
2025 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2026 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002027 auto *FnTy =
Alexey Bataev1d677132015-04-22 13:57:31 +00002028 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2029 RTLFn =
2030 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
2031 break;
2032 }
2033 case OMPRTL__kmpc_omp_task_complete_if0: {
2034 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2035 // *new_task);
2036 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2037 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002038 auto *FnTy =
Alexey Bataev1d677132015-04-22 13:57:31 +00002039 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2040 RTLFn = CGM.CreateRuntimeFunction(FnTy,
2041 /*Name=*/"__kmpc_omp_task_complete_if0");
2042 break;
2043 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002044 case OMPRTL__kmpc_ordered: {
2045 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
2046 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002047 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002048 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2049 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
2050 break;
2051 }
2052 case OMPRTL__kmpc_end_ordered: {
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002053 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002054 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002055 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002056 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2057 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
2058 break;
2059 }
Alexey Bataev8b8e2022015-04-27 05:22:09 +00002060 case OMPRTL__kmpc_omp_taskwait: {
2061 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
2062 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002063 auto *FnTy =
Alexey Bataev8b8e2022015-04-27 05:22:09 +00002064 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2065 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
2066 break;
2067 }
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002068 case OMPRTL__kmpc_taskgroup: {
2069 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
2070 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002071 auto *FnTy =
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002072 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2073 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
2074 break;
2075 }
2076 case OMPRTL__kmpc_end_taskgroup: {
2077 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
2078 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002079 auto *FnTy =
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002080 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2081 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
2082 break;
2083 }
Alexey Bataev7f210c62015-06-18 13:40:03 +00002084 case OMPRTL__kmpc_push_proc_bind: {
2085 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
2086 // int proc_bind)
2087 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002088 auto *FnTy =
Alexey Bataev7f210c62015-06-18 13:40:03 +00002089 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2090 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
2091 break;
2092 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002093 case OMPRTL__kmpc_omp_task_with_deps: {
2094 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
2095 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
2096 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
2097 llvm::Type *TypeParams[] = {
2098 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
2099 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002100 auto *FnTy =
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002101 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2102 RTLFn =
2103 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
2104 break;
2105 }
2106 case OMPRTL__kmpc_omp_wait_deps: {
2107 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
2108 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
2109 // kmp_depend_info_t *noalias_dep_list);
2110 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2111 CGM.Int32Ty, CGM.VoidPtrTy,
2112 CGM.Int32Ty, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002113 auto *FnTy =
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002114 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2115 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
2116 break;
2117 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00002118 case OMPRTL__kmpc_cancellationpoint: {
2119 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
2120 // global_tid, kmp_int32 cncl_kind)
2121 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002122 auto *FnTy =
Alexey Bataev0f34da12015-07-02 04:17:07 +00002123 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2124 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
2125 break;
2126 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002127 case OMPRTL__kmpc_cancel: {
2128 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
2129 // kmp_int32 cncl_kind)
2130 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002131 auto *FnTy =
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002132 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2133 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
2134 break;
2135 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002136 case OMPRTL__kmpc_push_num_teams: {
2137 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid,
2138 // kmp_int32 num_teams, kmp_int32 num_threads)
2139 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
2140 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002141 auto *FnTy =
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002142 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2143 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams");
2144 break;
2145 }
2146 case OMPRTL__kmpc_fork_teams: {
2147 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
2148 // microtask, ...);
2149 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2150 getKmpc_MicroPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002151 auto *FnTy =
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002152 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
2153 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams");
James Y Knight9871db02019-02-05 16:42:33 +00002154 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) {
Johannes Doerfertac991bb2019-01-19 05:36:54 +00002155 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
2156 llvm::LLVMContext &Ctx = F->getContext();
2157 llvm::MDBuilder MDB(Ctx);
2158 // Annotate the callback behavior of the __kmpc_fork_teams:
2159 // - The callback callee is argument number 2 (microtask).
2160 // - The first two arguments of the callback callee are unknown (-1).
2161 // - All variadic arguments to the __kmpc_fork_teams are passed to the
2162 // callback callee.
2163 F->addMetadata(
2164 llvm::LLVMContext::MD_callback,
2165 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
2166 2, {-1, -1},
2167 /* VarArgsArePassed */ true)}));
2168 }
2169 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002170 break;
2171 }
Alexey Bataev7292c292016-04-25 12:22:29 +00002172 case OMPRTL__kmpc_taskloop: {
2173 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
2174 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
2175 // sched, kmp_uint64 grainsize, void *task_dup);
2176 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
2177 CGM.IntTy,
2178 CGM.VoidPtrTy,
2179 CGM.IntTy,
2180 CGM.Int64Ty->getPointerTo(),
2181 CGM.Int64Ty->getPointerTo(),
2182 CGM.Int64Ty,
2183 CGM.IntTy,
2184 CGM.IntTy,
2185 CGM.Int64Ty,
2186 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002187 auto *FnTy =
Alexey Bataev7292c292016-04-25 12:22:29 +00002188 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2189 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop");
2190 break;
2191 }
Alexey Bataev8b427062016-05-25 12:36:08 +00002192 case OMPRTL__kmpc_doacross_init: {
2193 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32
2194 // num_dims, struct kmp_dim *dims);
2195 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
2196 CGM.Int32Ty,
2197 CGM.Int32Ty,
2198 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002199 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002200 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2201 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init");
2202 break;
2203 }
2204 case OMPRTL__kmpc_doacross_fini: {
2205 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid);
2206 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002207 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002208 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2209 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini");
2210 break;
2211 }
2212 case OMPRTL__kmpc_doacross_post: {
2213 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64
2214 // *vec);
2215 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2216 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002217 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002218 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2219 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post");
2220 break;
2221 }
2222 case OMPRTL__kmpc_doacross_wait: {
2223 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64
2224 // *vec);
2225 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2226 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002227 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002228 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2229 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait");
2230 break;
2231 }
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002232 case OMPRTL__kmpc_task_reduction_init: {
2233 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void
2234 // *data);
2235 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002236 auto *FnTy =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002237 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2238 RTLFn =
2239 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init");
2240 break;
2241 }
2242 case OMPRTL__kmpc_task_reduction_get_th_data: {
2243 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
2244 // *d);
2245 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002246 auto *FnTy =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002247 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2248 RTLFn = CGM.CreateRuntimeFunction(
2249 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data");
2250 break;
2251 }
Alexey Bataev4f680db2019-03-19 16:41:16 +00002252 case OMPRTL__kmpc_alloc: {
Alexey Bataev6cf7b712019-04-08 19:06:42 +00002253 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t
2254 // al); omp_allocator_handle_t type is void *.
2255 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy};
Alexey Bataev4f680db2019-03-19 16:41:16 +00002256 auto *FnTy =
2257 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2258 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc");
2259 break;
2260 }
2261 case OMPRTL__kmpc_free: {
Alexey Bataev6cf7b712019-04-08 19:06:42 +00002262 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t
2263 // al); omp_allocator_handle_t type is void *.
2264 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataev4f680db2019-03-19 16:41:16 +00002265 auto *FnTy =
2266 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2267 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free");
2268 break;
2269 }
Alexey Bataev7bb33532019-01-07 21:30:43 +00002270 case OMPRTL__kmpc_push_target_tripcount: {
2271 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64
2272 // size);
2273 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty};
2274 llvm::FunctionType *FnTy =
2275 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2276 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount");
2277 break;
2278 }
Samuel Antaobed3c462015-10-02 16:14:20 +00002279 case OMPRTL__tgt_target: {
George Rokos63bc9d62017-11-21 18:25:12 +00002280 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002281 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Samuel Antaobed3c462015-10-02 16:14:20 +00002282 // *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002283 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaobed3c462015-10-02 16:14:20 +00002284 CGM.VoidPtrTy,
2285 CGM.Int32Ty,
2286 CGM.VoidPtrPtrTy,
2287 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002288 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002289 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002290 auto *FnTy =
Samuel Antaobed3c462015-10-02 16:14:20 +00002291 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2292 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
2293 break;
2294 }
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002295 case OMPRTL__tgt_target_nowait: {
2296 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002297 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes,
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002298 // int64_t *arg_types);
2299 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2300 CGM.VoidPtrTy,
2301 CGM.Int32Ty,
2302 CGM.VoidPtrPtrTy,
2303 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002304 CGM.Int64Ty->getPointerTo(),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002305 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002306 auto *FnTy =
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002307 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2308 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait");
2309 break;
2310 }
Samuel Antaob68e2db2016-03-03 16:20:23 +00002311 case OMPRTL__tgt_target_teams: {
George Rokos63bc9d62017-11-21 18:25:12 +00002312 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002313 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes,
George Rokos63bc9d62017-11-21 18:25:12 +00002314 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
2315 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaob68e2db2016-03-03 16:20:23 +00002316 CGM.VoidPtrTy,
2317 CGM.Int32Ty,
2318 CGM.VoidPtrPtrTy,
2319 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002320 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002321 CGM.Int64Ty->getPointerTo(),
Samuel Antaob68e2db2016-03-03 16:20:23 +00002322 CGM.Int32Ty,
2323 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002324 auto *FnTy =
Samuel Antaob68e2db2016-03-03 16:20:23 +00002325 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2326 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams");
2327 break;
2328 }
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002329 case OMPRTL__tgt_target_teams_nowait: {
2330 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void
Alexey Bataeva90fc662019-06-25 16:00:43 +00002331 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002332 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
2333 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2334 CGM.VoidPtrTy,
2335 CGM.Int32Ty,
2336 CGM.VoidPtrPtrTy,
2337 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002338 CGM.Int64Ty->getPointerTo(),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002339 CGM.Int64Ty->getPointerTo(),
2340 CGM.Int32Ty,
2341 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002342 auto *FnTy =
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002343 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2344 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait");
2345 break;
2346 }
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00002347 case OMPRTL__tgt_register_requires: {
2348 // Build void __tgt_register_requires(int64_t flags);
2349 llvm::Type *TypeParams[] = {CGM.Int64Ty};
2350 auto *FnTy =
2351 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2352 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires");
2353 break;
2354 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00002355 case OMPRTL__tgt_register_lib: {
2356 // Build void __tgt_register_lib(__tgt_bin_desc *desc);
2357 QualType ParamTy =
2358 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
2359 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002360 auto *FnTy =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002361 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2362 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib");
2363 break;
2364 }
2365 case OMPRTL__tgt_unregister_lib: {
2366 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc);
2367 QualType ParamTy =
2368 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
2369 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002370 auto *FnTy =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002371 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2372 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib");
2373 break;
2374 }
Samuel Antaodf158d52016-04-27 22:58:19 +00002375 case OMPRTL__tgt_target_data_begin: {
George Rokos63bc9d62017-11-21 18:25:12 +00002376 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002377 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002378 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaodf158d52016-04-27 22:58:19 +00002379 CGM.Int32Ty,
2380 CGM.VoidPtrPtrTy,
2381 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002382 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002383 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002384 auto *FnTy =
Samuel Antaodf158d52016-04-27 22:58:19 +00002385 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2386 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin");
2387 break;
2388 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002389 case OMPRTL__tgt_target_data_begin_nowait: {
2390 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002391 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002392 // *arg_types);
2393 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2394 CGM.Int32Ty,
2395 CGM.VoidPtrPtrTy,
2396 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002397 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002398 CGM.Int64Ty->getPointerTo()};
2399 auto *FnTy =
2400 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2401 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait");
2402 break;
2403 }
Samuel Antaodf158d52016-04-27 22:58:19 +00002404 case OMPRTL__tgt_target_data_end: {
George Rokos63bc9d62017-11-21 18:25:12 +00002405 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002406 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002407 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaodf158d52016-04-27 22:58:19 +00002408 CGM.Int32Ty,
2409 CGM.VoidPtrPtrTy,
2410 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002411 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002412 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002413 auto *FnTy =
Samuel Antaodf158d52016-04-27 22:58:19 +00002414 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2415 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end");
2416 break;
2417 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002418 case OMPRTL__tgt_target_data_end_nowait: {
2419 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002420 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002421 // *arg_types);
2422 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2423 CGM.Int32Ty,
2424 CGM.VoidPtrPtrTy,
2425 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002426 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002427 CGM.Int64Ty->getPointerTo()};
2428 auto *FnTy =
2429 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2430 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait");
2431 break;
2432 }
Samuel Antao8d2d7302016-05-26 18:30:22 +00002433 case OMPRTL__tgt_target_data_update: {
George Rokos63bc9d62017-11-21 18:25:12 +00002434 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002435 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002436 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antao8d2d7302016-05-26 18:30:22 +00002437 CGM.Int32Ty,
2438 CGM.VoidPtrPtrTy,
2439 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002440 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002441 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002442 auto *FnTy =
Samuel Antao8d2d7302016-05-26 18:30:22 +00002443 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2444 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update");
2445 break;
2446 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002447 case OMPRTL__tgt_target_data_update_nowait: {
2448 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002449 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002450 // *arg_types);
2451 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2452 CGM.Int32Ty,
2453 CGM.VoidPtrPtrTy,
2454 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002455 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002456 CGM.Int64Ty->getPointerTo()};
2457 auto *FnTy =
2458 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2459 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait");
2460 break;
2461 }
Alexey Bataev9959db52014-05-06 10:08:46 +00002462 }
Alexey Bataev50b3c952016-02-19 10:38:26 +00002463 assert(RTLFn && "Unable to find OpenMP runtime function");
Alexey Bataev9959db52014-05-06 10:08:46 +00002464 return RTLFn;
2465}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00002466
James Y Knight9871db02019-02-05 16:42:33 +00002467llvm::FunctionCallee
2468CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman21212e42015-03-13 10:38:23 +00002469 assert((IVSize == 32 || IVSize == 64) &&
2470 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002471 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
2472 : "__kmpc_for_static_init_4u")
2473 : (IVSigned ? "__kmpc_for_static_init_8"
2474 : "__kmpc_for_static_init_8u");
2475 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
2476 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
Alexander Musman21212e42015-03-13 10:38:23 +00002477 llvm::Type *TypeParams[] = {
2478 getIdentTyPointerTy(), // loc
2479 CGM.Int32Ty, // tid
2480 CGM.Int32Ty, // schedtype
2481 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
2482 PtrTy, // p_lower
2483 PtrTy, // p_upper
2484 PtrTy, // p_stride
2485 ITy, // incr
2486 ITy // chunk
2487 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002488 auto *FnTy =
Alexander Musman21212e42015-03-13 10:38:23 +00002489 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2490 return CGM.CreateRuntimeFunction(FnTy, Name);
2491}
2492
James Y Knight9871db02019-02-05 16:42:33 +00002493llvm::FunctionCallee
2494CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002495 assert((IVSize == 32 || IVSize == 64) &&
2496 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002497 StringRef Name =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002498 IVSize == 32
2499 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
2500 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002501 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
Alexander Musman92bdaab2015-03-12 13:37:50 +00002502 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
2503 CGM.Int32Ty, // tid
2504 CGM.Int32Ty, // schedtype
2505 ITy, // lower
2506 ITy, // upper
2507 ITy, // stride
2508 ITy // chunk
2509 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002510 auto *FnTy =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002511 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2512 return CGM.CreateRuntimeFunction(FnTy, Name);
2513}
2514
James Y Knight9871db02019-02-05 16:42:33 +00002515llvm::FunctionCallee
2516CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002517 assert((IVSize == 32 || IVSize == 64) &&
2518 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002519 StringRef Name =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002520 IVSize == 32
2521 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
2522 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
2523 llvm::Type *TypeParams[] = {
2524 getIdentTyPointerTy(), // loc
2525 CGM.Int32Ty, // tid
2526 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002527 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002528 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2529 return CGM.CreateRuntimeFunction(FnTy, Name);
2530}
2531
James Y Knight9871db02019-02-05 16:42:33 +00002532llvm::FunctionCallee
2533CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002534 assert((IVSize == 32 || IVSize == 64) &&
2535 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002536 StringRef Name =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002537 IVSize == 32
2538 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
2539 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002540 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
2541 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002542 llvm::Type *TypeParams[] = {
2543 getIdentTyPointerTy(), // loc
2544 CGM.Int32Ty, // tid
2545 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
2546 PtrTy, // p_lower
2547 PtrTy, // p_upper
2548 PtrTy // p_stride
2549 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002550 auto *FnTy =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002551 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2552 return CGM.CreateRuntimeFunction(FnTy, Name);
2553}
2554
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002555Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) {
Alexey Bataev03f270c2018-03-30 18:31:07 +00002556 if (CGM.getLangOpts().OpenMPSimd)
2557 return Address::invalid();
Alexey Bataev92327c52018-03-26 16:40:55 +00002558 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00002559 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002560 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link ||
2561 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
2562 HasRequiresUnifiedSharedMemory))) {
Alexey Bataev92327c52018-03-26 16:40:55 +00002563 SmallString<64> PtrName;
2564 {
2565 llvm::raw_svector_ostream OS(PtrName);
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002566 OS << CGM.getMangledName(GlobalDecl(VD)) << "_decl_tgt_ref_ptr";
Alexey Bataev92327c52018-03-26 16:40:55 +00002567 }
2568 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName);
2569 if (!Ptr) {
2570 QualType PtrTy = CGM.getContext().getPointerType(VD->getType());
2571 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy),
2572 PtrName);
Alexey Bataev03f270c2018-03-30 18:31:07 +00002573 if (!CGM.getLangOpts().OpenMPIsDevice) {
2574 auto *GV = cast<llvm::GlobalVariable>(Ptr);
2575 GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
2576 GV->setInitializer(CGM.GetAddrOfGlobal(VD));
2577 }
2578 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ptr));
2579 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr));
Alexey Bataev92327c52018-03-26 16:40:55 +00002580 }
2581 return Address(Ptr, CGM.getContext().getDeclAlign(VD));
2582 }
2583 return Address::invalid();
2584}
2585
Alexey Bataev97720002014-11-11 04:05:39 +00002586llvm::Constant *
2587CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002588 assert(!CGM.getLangOpts().OpenMPUseTLS ||
2589 !CGM.getContext().getTargetInfo().isTLSSupported());
Alexey Bataev97720002014-11-11 04:05:39 +00002590 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev18fa2322018-05-02 14:20:50 +00002591 std::string Suffix = getName({"cache", ""});
2592 return getOrCreateInternalVariable(
2593 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix));
Alexey Bataev97720002014-11-11 04:05:39 +00002594}
2595
John McCall7f416cc2015-09-08 08:05:57 +00002596Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
2597 const VarDecl *VD,
2598 Address VDAddr,
2599 SourceLocation Loc) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002600 if (CGM.getLangOpts().OpenMPUseTLS &&
2601 CGM.getContext().getTargetInfo().isTLSSupported())
2602 return VDAddr;
2603
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002604 llvm::Type *VarTy = VDAddr.getElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002605 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00002606 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
2607 CGM.Int8PtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00002608 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
2609 getOrCreateThreadPrivateCache(VD)};
John McCall7f416cc2015-09-08 08:05:57 +00002610 return Address(CGF.EmitRuntimeCall(
2611 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
2612 VDAddr.getAlignment());
Alexey Bataev97720002014-11-11 04:05:39 +00002613}
2614
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002615void CGOpenMPRuntime::emitThreadPrivateVarInit(
John McCall7f416cc2015-09-08 08:05:57 +00002616 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
Alexey Bataev97720002014-11-11 04:05:39 +00002617 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
2618 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
2619 // library.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002620 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002621 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +00002622 OMPLoc);
2623 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
2624 // to register constructor/destructor for variable.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002625 llvm::Value *Args[] = {
2626 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy),
2627 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +00002628 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002629 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +00002630}
2631
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002632llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
John McCall7f416cc2015-09-08 08:05:57 +00002633 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
Alexey Bataev97720002014-11-11 04:05:39 +00002634 bool PerformInit, CodeGenFunction *CGF) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002635 if (CGM.getLangOpts().OpenMPUseTLS &&
2636 CGM.getContext().getTargetInfo().isTLSSupported())
2637 return nullptr;
2638
Alexey Bataev97720002014-11-11 04:05:39 +00002639 VD = VD->getDefinition(CGM.getContext());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00002640 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) {
Alexey Bataev97720002014-11-11 04:05:39 +00002641 QualType ASTTy = VD->getType();
2642
2643 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002644 const Expr *Init = VD->getAnyInitializer();
Alexey Bataev97720002014-11-11 04:05:39 +00002645 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
2646 // Generate function that re-emits the declaration's initializer into the
2647 // threadprivate copy of the variable VD
2648 CodeGenFunction CtorCGF(CGM);
2649 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002650 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
2651 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
Alexey Bataev56223232017-06-09 13:40:18 +00002652 ImplicitParamDecl::Other);
Alexey Bataev97720002014-11-11 04:05:39 +00002653 Args.push_back(&Dst);
2654
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002655 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
John McCallc56a8b32016-03-11 04:30:31 +00002656 CGM.getContext().VoidPtrTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002657 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002658 std::string Name = getName({"__kmpc_global_ctor_", ""});
2659 llvm::Function *Fn =
2660 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002661 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002662 Args, Loc, Loc);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002663 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002664 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00002665 CGM.getContext().VoidPtrTy, Dst.getLocation());
John McCall7f416cc2015-09-08 08:05:57 +00002666 Address Arg = Address(ArgVal, VDAddr.getAlignment());
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002667 Arg = CtorCGF.Builder.CreateElementBitCast(
2668 Arg, CtorCGF.ConvertTypeForMem(ASTTy));
Alexey Bataev97720002014-11-11 04:05:39 +00002669 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
2670 /*IsInitializer=*/true);
2671 ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002672 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00002673 CGM.getContext().VoidPtrTy, Dst.getLocation());
2674 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
2675 CtorCGF.FinishFunction();
2676 Ctor = Fn;
2677 }
2678 if (VD->getType().isDestructedType() != QualType::DK_none) {
2679 // Generate function that emits destructor call for the threadprivate copy
2680 // of the variable VD
2681 CodeGenFunction DtorCGF(CGM);
2682 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002683 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
2684 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
Alexey Bataev56223232017-06-09 13:40:18 +00002685 ImplicitParamDecl::Other);
Alexey Bataev97720002014-11-11 04:05:39 +00002686 Args.push_back(&Dst);
2687
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002688 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
John McCallc56a8b32016-03-11 04:30:31 +00002689 CGM.getContext().VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002690 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002691 std::string Name = getName({"__kmpc_global_dtor_", ""});
2692 llvm::Function *Fn =
2693 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
Adrian Prantl1858c662016-04-24 22:22:29 +00002694 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
Alexey Bataev97720002014-11-11 04:05:39 +00002695 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002696 Loc, Loc);
Adrian Prantl1858c662016-04-24 22:22:29 +00002697 // Create a scope with an artificial location for the body of this function.
2698 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002699 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar(
Alexey Bataev97720002014-11-11 04:05:39 +00002700 DtorCGF.GetAddrOfLocalVar(&Dst),
John McCall7f416cc2015-09-08 08:05:57 +00002701 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
2702 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
Alexey Bataev97720002014-11-11 04:05:39 +00002703 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
2704 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
2705 DtorCGF.FinishFunction();
2706 Dtor = Fn;
2707 }
2708 // Do not emit init function if it is not required.
2709 if (!Ctor && !Dtor)
2710 return nullptr;
2711
2712 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002713 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
2714 /*isVarArg=*/false)
2715 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002716 // Copying constructor for the threadprivate variable.
2717 // Must be NULL - reserved by runtime, but currently it requires that this
2718 // parameter is always NULL. Otherwise it fires assertion.
2719 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
2720 if (Ctor == nullptr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002721 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
2722 /*isVarArg=*/false)
2723 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002724 Ctor = llvm::Constant::getNullValue(CtorTy);
2725 }
2726 if (Dtor == nullptr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002727 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
2728 /*isVarArg=*/false)
2729 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002730 Dtor = llvm::Constant::getNullValue(DtorTy);
2731 }
2732 if (!CGF) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002733 auto *InitFunctionTy =
Alexey Bataev97720002014-11-11 04:05:39 +00002734 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002735 std::string Name = getName({"__omp_threadprivate_init_", ""});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002736 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction(
Alexey Bataev18fa2322018-05-02 14:20:50 +00002737 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction());
Alexey Bataev97720002014-11-11 04:05:39 +00002738 CodeGenFunction InitCGF(CGM);
2739 FunctionArgList ArgList;
2740 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
2741 CGM.getTypes().arrangeNullaryFunction(), ArgList,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002742 Loc, Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002743 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002744 InitCGF.FinishFunction();
2745 return InitFunction;
2746 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002747 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002748 }
2749 return nullptr;
2750}
2751
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002752/// Obtain information that uniquely identifies a target entry. This
Alexey Bataev34f8a702018-03-28 14:28:54 +00002753/// consists of the file and device IDs as well as line number associated with
2754/// the relevant entry source location.
2755static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
2756 unsigned &DeviceID, unsigned &FileID,
2757 unsigned &LineNum) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002758 SourceManager &SM = C.getSourceManager();
Alexey Bataev34f8a702018-03-28 14:28:54 +00002759
2760 // The loc should be always valid and have a file ID (the user cannot use
2761 // #pragma directives in macros)
2762
2763 assert(Loc.isValid() && "Source location is expected to be always valid.");
Alexey Bataev34f8a702018-03-28 14:28:54 +00002764
2765 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
2766 assert(PLoc.isValid() && "Source location is expected to be always valid.");
2767
2768 llvm::sys::fs::UniqueID ID;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00002769 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
2770 SM.getDiagnostics().Report(diag::err_cannot_open_file)
2771 << PLoc.getFilename() << EC.message();
Alexey Bataev34f8a702018-03-28 14:28:54 +00002772
2773 DeviceID = ID.getDevice();
2774 FileID = ID.getFile();
2775 LineNum = PLoc.getLine();
2776}
2777
2778bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD,
2779 llvm::GlobalVariable *Addr,
2780 bool PerformInit) {
2781 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00002782 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002783 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
2784 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
2785 HasRequiresUnifiedSharedMemory))
Alexey Bataevd01b7492018-08-15 19:45:12 +00002786 return CGM.getLangOpts().OpenMPIsDevice;
Alexey Bataev34f8a702018-03-28 14:28:54 +00002787 VD = VD->getDefinition(CGM.getContext());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00002788 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second)
Alexey Bataev34f8a702018-03-28 14:28:54 +00002789 return CGM.getLangOpts().OpenMPIsDevice;
2790
2791 QualType ASTTy = VD->getType();
2792
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002793 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc();
Alexey Bataev34f8a702018-03-28 14:28:54 +00002794 // Produce the unique prefix to identify the new target regions. We use
2795 // the source location of the variable declaration which we know to not
2796 // conflict with any target region.
2797 unsigned DeviceID;
2798 unsigned FileID;
2799 unsigned Line;
2800 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line);
2801 SmallString<128> Buffer, Out;
2802 {
2803 llvm::raw_svector_ostream OS(Buffer);
2804 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID)
2805 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
2806 }
2807
2808 const Expr *Init = VD->getAnyInitializer();
2809 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
2810 llvm::Constant *Ctor;
2811 llvm::Constant *ID;
2812 if (CGM.getLangOpts().OpenMPIsDevice) {
2813 // Generate function that re-emits the declaration's initializer into
2814 // the threadprivate copy of the variable VD
2815 CodeGenFunction CtorCGF(CGM);
2816
2817 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2818 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2819 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
2820 FTy, Twine(Buffer, "_ctor"), FI, Loc);
2821 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF);
2822 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
2823 FunctionArgList(), Loc, Loc);
2824 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF);
2825 CtorCGF.EmitAnyExprToMem(Init,
2826 Address(Addr, CGM.getContext().getDeclAlign(VD)),
2827 Init->getType().getQualifiers(),
2828 /*IsInitializer=*/true);
2829 CtorCGF.FinishFunction();
2830 Ctor = Fn;
2831 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
Alexey Bataeve253f2f2018-05-09 14:15:18 +00002832 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor));
Alexey Bataev34f8a702018-03-28 14:28:54 +00002833 } else {
2834 Ctor = new llvm::GlobalVariable(
2835 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
2836 llvm::GlobalValue::PrivateLinkage,
2837 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor"));
2838 ID = Ctor;
2839 }
2840
2841 // Register the information for the entry associated with the constructor.
2842 Out.clear();
2843 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
2844 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor,
Alexey Bataev03f270c2018-03-30 18:31:07 +00002845 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor);
Alexey Bataev34f8a702018-03-28 14:28:54 +00002846 }
2847 if (VD->getType().isDestructedType() != QualType::DK_none) {
2848 llvm::Constant *Dtor;
2849 llvm::Constant *ID;
2850 if (CGM.getLangOpts().OpenMPIsDevice) {
2851 // Generate function that emits destructor call for the threadprivate
2852 // copy of the variable VD
2853 CodeGenFunction DtorCGF(CGM);
2854
2855 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2856 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2857 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
2858 FTy, Twine(Buffer, "_dtor"), FI, Loc);
2859 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
2860 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
2861 FunctionArgList(), Loc, Loc);
2862 // Create a scope with an artificial location for the body of this
2863 // function.
2864 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
2865 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)),
2866 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()),
2867 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
2868 DtorCGF.FinishFunction();
2869 Dtor = Fn;
2870 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
Alexey Bataeve253f2f2018-05-09 14:15:18 +00002871 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor));
Alexey Bataev34f8a702018-03-28 14:28:54 +00002872 } else {
2873 Dtor = new llvm::GlobalVariable(
2874 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
2875 llvm::GlobalValue::PrivateLinkage,
2876 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor"));
2877 ID = Dtor;
2878 }
2879 // Register the information for the entry associated with the destructor.
2880 Out.clear();
2881 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
2882 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor,
Alexey Bataev03f270c2018-03-30 18:31:07 +00002883 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor);
Alexey Bataev34f8a702018-03-28 14:28:54 +00002884 }
2885 return CGM.getLangOpts().OpenMPIsDevice;
2886}
2887
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002888Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
2889 QualType VarType,
2890 StringRef Name) {
Alexey Bataev18fa2322018-05-02 14:20:50 +00002891 std::string Suffix = getName({"artificial", ""});
2892 std::string CacheSuffix = getName({"cache", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002893 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002894 llvm::Value *GAddr =
2895 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002896 llvm::Value *Args[] = {
2897 emitUpdateLocation(CGF, SourceLocation()),
2898 getThreadID(CGF, SourceLocation()),
2899 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy),
2900 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00002901 /*isSigned=*/false),
Alexey Bataev18fa2322018-05-02 14:20:50 +00002902 getOrCreateInternalVariable(
2903 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))};
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002904 return Address(
2905 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2906 CGF.EmitRuntimeCall(
2907 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
2908 VarLVType->getPointerTo(/*AddrSpace=*/0)),
2909 CGM.getPointerAlign());
2910}
2911
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +00002912void CGOpenMPRuntime::emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
2913 const RegionCodeGenTy &ThenGen,
2914 const RegionCodeGenTy &ElseGen) {
Alexey Bataev1d677132015-04-22 13:57:31 +00002915 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
2916
2917 // If the condition constant folds and can be elided, try to avoid emitting
2918 // the condition and the dead arm of the if/else.
2919 bool CondConstant;
2920 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002921 if (CondConstant)
Alexey Bataev1d677132015-04-22 13:57:31 +00002922 ThenGen(CGF);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002923 else
Alexey Bataev1d677132015-04-22 13:57:31 +00002924 ElseGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00002925 return;
2926 }
2927
2928 // Otherwise, the condition did not fold, or we couldn't elide it. Just
2929 // emit the conditional branch.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002930 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then");
2931 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else");
2932 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end");
Alexey Bataev1d677132015-04-22 13:57:31 +00002933 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
2934
2935 // Emit the 'then' code.
2936 CGF.EmitBlock(ThenBlock);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002937 ThenGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00002938 CGF.EmitBranch(ContBlock);
2939 // Emit the 'else' code if present.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002940 // There is no need to emit line number for unconditional branch.
2941 (void)ApplyDebugLocation::CreateEmpty(CGF);
2942 CGF.EmitBlock(ElseBlock);
2943 ElseGen(CGF);
2944 // There is no need to emit line number for unconditional branch.
2945 (void)ApplyDebugLocation::CreateEmpty(CGF);
2946 CGF.EmitBranch(ContBlock);
Alexey Bataev1d677132015-04-22 13:57:31 +00002947 // Emit the continuation block for code after the if.
2948 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00002949}
2950
Alexey Bataev1d677132015-04-22 13:57:31 +00002951void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00002952 llvm::Function *OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00002953 ArrayRef<llvm::Value *> CapturedVars,
Alexey Bataev1d677132015-04-22 13:57:31 +00002954 const Expr *IfCond) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002955 if (!CGF.HaveInsertPoint())
2956 return;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002957 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002958 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF,
2959 PrePostActionTy &) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00002960 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002961 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev2377fe92015-09-10 08:12:02 +00002962 llvm::Value *Args[] = {
2963 RTLoc,
2964 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002965 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())};
Alexey Bataev2377fe92015-09-10 08:12:02 +00002966 llvm::SmallVector<llvm::Value *, 16> RealArgs;
2967 RealArgs.append(std::begin(Args), std::end(Args));
2968 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
2969
James Y Knight9871db02019-02-05 16:42:33 +00002970 llvm::FunctionCallee RTLFn =
2971 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call);
Alexey Bataev2377fe92015-09-10 08:12:02 +00002972 CGF.EmitRuntimeCall(RTLFn, RealArgs);
2973 };
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002974 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF,
2975 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002976 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
2977 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc);
Alexey Bataev1d677132015-04-22 13:57:31 +00002978 // Build calls:
2979 // __kmpc_serialized_parallel(&Loc, GTid);
2980 llvm::Value *Args[] = {RTLoc, ThreadID};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002981 CGF.EmitRuntimeCall(
2982 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +00002983
Alexey Bataev1d677132015-04-22 13:57:31 +00002984 // OutlinedFn(&GTid, &zero, CapturedStruct);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002985 Address ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty,
2986 /*Name*/ ".zero.addr");
Alexey Bataev1d677132015-04-22 13:57:31 +00002987 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
Alexey Bataev2377fe92015-09-10 08:12:02 +00002988 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
Alexey Bataev8521ff62018-07-25 20:03:01 +00002989 // ThreadId for serialized parallels is 0.
2990 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
Alexey Bataev2377fe92015-09-10 08:12:02 +00002991 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
2992 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
Alexey Bataev3c595a62017-08-14 15:01:03 +00002993 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +00002994
Alexey Bataev1d677132015-04-22 13:57:31 +00002995 // __kmpc_end_serialized_parallel(&Loc, GTid);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002996 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID};
Alexey Bataev1d677132015-04-22 13:57:31 +00002997 CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002998 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel),
2999 EndArgs);
Alexey Bataev1d677132015-04-22 13:57:31 +00003000 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003001 if (IfCond) {
Alexey Bataev1d677132015-04-22 13:57:31 +00003002 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003003 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003004 RegionCodeGenTy ThenRCG(ThenGen);
3005 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00003006 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00003007}
3008
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00003009// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +00003010// thread-ID variable (it is passed in a first argument of the outlined function
3011// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
3012// regular serial code region, get thread ID by calling kmp_int32
3013// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
3014// return the address of that temp.
John McCall7f416cc2015-09-08 08:05:57 +00003015Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
3016 SourceLocation Loc) {
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003017 if (auto *OMPRegionInfo =
Alexey Bataevd74d0602014-10-13 06:02:40 +00003018 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003019 if (OMPRegionInfo->getThreadIDVariable())
Alexey Bataev62b63b12015-03-10 07:28:44 +00003020 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003021
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003022 llvm::Value *ThreadID = getThreadID(CGF, Loc);
3023 QualType Int32Ty =
Alexey Bataevd74d0602014-10-13 06:02:40 +00003024 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003025 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
Alexey Bataevd74d0602014-10-13 06:02:40 +00003026 CGF.EmitStoreOfScalar(ThreadID,
John McCall7f416cc2015-09-08 08:05:57 +00003027 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
Alexey Bataevd74d0602014-10-13 06:02:40 +00003028
3029 return ThreadIDTemp;
3030}
3031
Alexey Bataev1af5bd52019-03-05 17:47:18 +00003032llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable(
3033 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003034 SmallString<256> Buffer;
3035 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00003036 Out << Name;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003037 StringRef RuntimeName = Out.str();
Alexey Bataev43a919f2018-04-13 17:48:43 +00003038 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first;
David Blaikie13156b62014-11-19 03:06:06 +00003039 if (Elem.second) {
3040 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00003041 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00003042 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00003043 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003044
David Blaikie13156b62014-11-19 03:06:06 +00003045 return Elem.second = new llvm::GlobalVariable(
3046 CGM.getModule(), Ty, /*IsConstant*/ false,
3047 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
Alexey Bataev1af5bd52019-03-05 17:47:18 +00003048 Elem.first(), /*InsertBefore=*/nullptr,
3049 llvm::GlobalValue::NotThreadLocal, AddressSpace);
Alexey Bataev97720002014-11-11 04:05:39 +00003050}
3051
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003052llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev18fa2322018-05-02 14:20:50 +00003053 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str();
3054 std::string Name = getName({Prefix, "var"});
3055 return getOrCreateInternalVariable(KmpCriticalNameTy, Name);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003056}
3057
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003058namespace {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003059/// Common pre(post)-action for different OpenMP constructs.
3060class CommonActionTy final : public PrePostActionTy {
James Y Knight9871db02019-02-05 16:42:33 +00003061 llvm::FunctionCallee EnterCallee;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003062 ArrayRef<llvm::Value *> EnterArgs;
James Y Knight9871db02019-02-05 16:42:33 +00003063 llvm::FunctionCallee ExitCallee;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003064 ArrayRef<llvm::Value *> ExitArgs;
3065 bool Conditional;
3066 llvm::BasicBlock *ContBlock = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003067
3068public:
James Y Knight9871db02019-02-05 16:42:33 +00003069 CommonActionTy(llvm::FunctionCallee EnterCallee,
3070 ArrayRef<llvm::Value *> EnterArgs,
3071 llvm::FunctionCallee ExitCallee,
3072 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003073 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
3074 ExitArgs(ExitArgs), Conditional(Conditional) {}
3075 void Enter(CodeGenFunction &CGF) override {
3076 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs);
3077 if (Conditional) {
3078 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes);
3079 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
3080 ContBlock = CGF.createBasicBlock("omp_if.end");
3081 // Generate the branch (If-stmt)
3082 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
3083 CGF.EmitBlock(ThenBlock);
3084 }
Alexey Bataeva744ff52015-05-05 09:24:37 +00003085 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003086 void Done(CodeGenFunction &CGF) {
3087 // Emit the rest of blocks/branches
3088 CGF.EmitBranch(ContBlock);
3089 CGF.EmitBlock(ContBlock, true);
3090 }
3091 void Exit(CodeGenFunction &CGF) override {
3092 CGF.EmitRuntimeCall(ExitCallee, ExitArgs);
Alexey Bataev3e6124b2015-04-10 07:48:12 +00003093 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003094};
Hans Wennborg7eb54642015-09-10 17:07:54 +00003095} // anonymous namespace
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003096
3097void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
3098 StringRef CriticalName,
3099 const RegionCodeGenTy &CriticalOpGen,
Alexey Bataevfc57d162015-12-15 10:55:09 +00003100 SourceLocation Loc, const Expr *Hint) {
3101 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
Alexey Bataev75ddfab2014-12-01 11:32:38 +00003102 // CriticalOpGen();
3103 // __kmpc_end_critical(ident_t *, gtid, Lock);
3104 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev8ef31412015-12-18 07:58:25 +00003105 if (!CGF.HaveInsertPoint())
3106 return;
Alexey Bataevfc57d162015-12-15 10:55:09 +00003107 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3108 getCriticalRegionLock(CriticalName)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003109 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args),
3110 std::end(Args));
Alexey Bataevfc57d162015-12-15 10:55:09 +00003111 if (Hint) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003112 EnterArgs.push_back(CGF.Builder.CreateIntCast(
3113 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false));
3114 }
3115 CommonActionTy Action(
3116 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint
3117 : OMPRTL__kmpc_critical),
3118 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args);
3119 CriticalOpGen.setAction(Action);
Alexey Bataevfc57d162015-12-15 10:55:09 +00003120 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003121}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003122
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003123void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003124 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003125 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003126 if (!CGF.HaveInsertPoint())
3127 return;
Alexey Bataev8d690652014-12-04 07:23:53 +00003128 // if(__kmpc_master(ident_t *, gtid)) {
3129 // MasterOpGen();
3130 // __kmpc_end_master(ident_t *, gtid);
3131 // }
3132 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00003133 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003134 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args,
3135 createRuntimeFunction(OMPRTL__kmpc_end_master), Args,
3136 /*Conditional=*/true);
3137 MasterOpGen.setAction(Action);
3138 emitInlinedDirective(CGF, OMPD_master, MasterOpGen);
3139 Action.Done(CGF);
Alexey Bataev8d690652014-12-04 07:23:53 +00003140}
3141
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003142void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
3143 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003144 if (!CGF.HaveInsertPoint())
3145 return;
Alexey Bataev9f797f32015-02-05 05:57:51 +00003146 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
3147 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003148 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00003149 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003150 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00003151 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
3152 Region->emitUntiedSwitch(CGF);
Alexey Bataev9f797f32015-02-05 05:57:51 +00003153}
3154
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003155void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
3156 const RegionCodeGenTy &TaskgroupOpGen,
3157 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003158 if (!CGF.HaveInsertPoint())
3159 return;
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003160 // __kmpc_taskgroup(ident_t *, gtid);
3161 // TaskgroupOpGen();
3162 // __kmpc_end_taskgroup(ident_t *, gtid);
3163 // Prepare arguments and build a call to __kmpc_taskgroup
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003164 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
3165 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args,
3166 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
3167 Args);
3168 TaskgroupOpGen.setAction(Action);
3169 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003170}
3171
John McCall7f416cc2015-09-08 08:05:57 +00003172/// Given an array of pointers to variables, project the address of a
3173/// given variable.
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003174static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
3175 unsigned Index, const VarDecl *Var) {
John McCall7f416cc2015-09-08 08:05:57 +00003176 // Pull out the pointer to the variable.
James Y Knight751fe282019-02-09 22:22:28 +00003177 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index);
John McCall7f416cc2015-09-08 08:05:57 +00003178 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
3179
3180 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003181 Addr = CGF.Builder.CreateElementBitCast(
3182 Addr, CGF.ConvertTypeForMem(Var->getType()));
John McCall7f416cc2015-09-08 08:05:57 +00003183 return Addr;
3184}
3185
Alexey Bataeva63048e2015-03-23 06:18:07 +00003186static llvm::Value *emitCopyprivateCopyFunction(
Alexey Bataev420d45b2015-04-14 05:11:24 +00003187 CodeGenModule &CGM, llvm::Type *ArgsType,
3188 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003189 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps,
3190 SourceLocation Loc) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003191 ASTContext &C = CGM.getContext();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003192 // void copy_func(void *LHSArg, void *RHSArg);
3193 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003194 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3195 ImplicitParamDecl::Other);
3196 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3197 ImplicitParamDecl::Other);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003198 Args.push_back(&LHSArg);
3199 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003200 const auto &CGFI =
3201 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00003202 std::string Name =
3203 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"});
3204 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
3205 llvm::GlobalValue::InternalLinkage, Name,
3206 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00003207 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00003208 Fn->setDoesNotRecurse();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003209 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003210 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev420d45b2015-04-14 05:11:24 +00003211 // Dest = (void*[n])(LHSArg);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003212 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00003213 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3214 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
3215 ArgsType), CGF.getPointerAlign());
3216 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3217 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
3218 ArgsType), CGF.getPointerAlign());
Alexey Bataeva63048e2015-03-23 06:18:07 +00003219 // *(Type0*)Dst[0] = *(Type0*)Src[0];
3220 // *(Type1*)Dst[1] = *(Type1*)Src[1];
3221 // ...
3222 // *(Typen*)Dst[n] = *(Typen*)Src[n];
Alexey Bataeva63048e2015-03-23 06:18:07 +00003223 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003224 const auto *DestVar =
3225 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +00003226 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
3227
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003228 const auto *SrcVar =
3229 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +00003230 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
3231
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003232 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003233 QualType Type = VD->getType();
John McCall7f416cc2015-09-08 08:05:57 +00003234 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003235 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00003236 CGF.FinishFunction();
3237 return Fn;
3238}
3239
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003240void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003241 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00003242 SourceLocation Loc,
3243 ArrayRef<const Expr *> CopyprivateVars,
3244 ArrayRef<const Expr *> SrcExprs,
3245 ArrayRef<const Expr *> DstExprs,
3246 ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003247 if (!CGF.HaveInsertPoint())
3248 return;
Alexey Bataeva63048e2015-03-23 06:18:07 +00003249 assert(CopyprivateVars.size() == SrcExprs.size() &&
3250 CopyprivateVars.size() == DstExprs.size() &&
3251 CopyprivateVars.size() == AssignmentOps.size());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003252 ASTContext &C = CGM.getContext();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003253 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003254 // if(__kmpc_single(ident_t *, gtid)) {
3255 // SingleOpGen();
3256 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003257 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003258 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00003259 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3260 // <copy_func>, did_it);
3261
John McCall7f416cc2015-09-08 08:05:57 +00003262 Address DidIt = Address::invalid();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003263 if (!CopyprivateVars.empty()) {
3264 // int32 did_it = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003265 QualType KmpInt32Ty =
3266 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003267 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
John McCall7f416cc2015-09-08 08:05:57 +00003268 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003269 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003270 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00003271 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003272 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args,
3273 createRuntimeFunction(OMPRTL__kmpc_end_single), Args,
3274 /*Conditional=*/true);
3275 SingleOpGen.setAction(Action);
3276 emitInlinedDirective(CGF, OMPD_single, SingleOpGen);
3277 if (DidIt.isValid()) {
3278 // did_it = 1;
3279 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
3280 }
3281 Action.Done(CGF);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003282 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3283 // <copy_func>, did_it);
John McCall7f416cc2015-09-08 08:05:57 +00003284 if (DidIt.isValid()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00003285 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003286 QualType CopyprivateArrayTy =
Alexey Bataeva63048e2015-03-23 06:18:07 +00003287 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
3288 /*IndexTypeQuals=*/0);
3289 // Create a list of all private variables for copyprivate.
John McCall7f416cc2015-09-08 08:05:57 +00003290 Address CopyprivateList =
Alexey Bataeva63048e2015-03-23 06:18:07 +00003291 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
3292 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +00003293 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I);
John McCall7f416cc2015-09-08 08:05:57 +00003294 CGF.Builder.CreateStore(
Alexey Bataeva63048e2015-03-23 06:18:07 +00003295 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00003296 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy),
3297 Elem);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003298 }
3299 // Build function that copies private values from single region to all other
3300 // threads in the corresponding parallel region.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003301 llvm::Value *CpyFn = emitCopyprivateCopyFunction(
Alexey Bataeva63048e2015-03-23 06:18:07 +00003302 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003303 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003304 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00003305 Address CL =
3306 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
3307 CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003308 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003309 llvm::Value *Args[] = {
3310 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
3311 getThreadID(CGF, Loc), // i32 <gtid>
Alexey Bataev66beaa92015-04-30 03:47:32 +00003312 BufSize, // size_t <buf_size>
John McCall7f416cc2015-09-08 08:05:57 +00003313 CL.getPointer(), // void *<copyprivate list>
Alexey Bataeva63048e2015-03-23 06:18:07 +00003314 CpyFn, // void (*) (void *, void *) <copy_func>
3315 DidItVal // i32 did_it
3316 };
3317 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
3318 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003319}
3320
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003321void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
3322 const RegionCodeGenTy &OrderedOpGen,
Alexey Bataev5f600d62015-09-29 03:48:57 +00003323 SourceLocation Loc, bool IsThreads) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003324 if (!CGF.HaveInsertPoint())
3325 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003326 // __kmpc_ordered(ident_t *, gtid);
3327 // OrderedOpGen();
3328 // __kmpc_end_ordered(ident_t *, gtid);
3329 // Prepare arguments and build a call to __kmpc_ordered
Alexey Bataev5f600d62015-09-29 03:48:57 +00003330 if (IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003331 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003332 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args,
3333 createRuntimeFunction(OMPRTL__kmpc_end_ordered),
3334 Args);
3335 OrderedOpGen.setAction(Action);
3336 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
3337 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003338 }
Alexey Bataev5f600d62015-09-29 03:48:57 +00003339 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003340}
3341
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003342unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) {
Alexey Bataev50b3c952016-02-19 10:38:26 +00003343 unsigned Flags;
3344 if (Kind == OMPD_for)
3345 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
3346 else if (Kind == OMPD_sections)
3347 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
3348 else if (Kind == OMPD_single)
3349 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
3350 else if (Kind == OMPD_barrier)
3351 Flags = OMP_IDENT_BARRIER_EXPL;
3352 else
3353 Flags = OMP_IDENT_BARRIER_IMPL;
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003354 return Flags;
3355}
3356
Alexey Bataevf6a53d62019-03-18 18:40:00 +00003357void CGOpenMPRuntime::getDefaultScheduleAndChunk(
3358 CodeGenFunction &CGF, const OMPLoopDirective &S,
3359 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const {
3360 // Check if the loop directive is actually a doacross loop directive. In this
3361 // case choose static, 1 schedule.
3362 if (llvm::any_of(
3363 S.getClausesOfKind<OMPOrderedClause>(),
3364 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) {
3365 ScheduleKind = OMPC_SCHEDULE_static;
3366 // Chunk size is 1 in this case.
3367 llvm::APInt ChunkSize(32, 1);
3368 ChunkExpr = IntegerLiteral::Create(
3369 CGF.getContext(), ChunkSize,
3370 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
3371 SourceLocation());
3372 }
3373}
3374
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003375void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
3376 OpenMPDirectiveKind Kind, bool EmitChecks,
3377 bool ForceSimpleCall) {
3378 if (!CGF.HaveInsertPoint())
3379 return;
3380 // Build call __kmpc_cancel_barrier(loc, thread_id);
3381 // Build call __kmpc_barrier(loc, thread_id);
3382 unsigned Flags = getDefaultFlagsForBarriers(Kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003383 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
3384 // thread_id);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003385 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
3386 getThreadID(CGF, Loc)};
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003387 if (auto *OMPRegionInfo =
3388 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00003389 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003390 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003391 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev25e5b442015-09-15 12:52:43 +00003392 if (EmitChecks) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003393 // if (__kmpc_cancel_barrier()) {
3394 // exit from construct;
3395 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003396 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
3397 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
3398 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003399 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
3400 CGF.EmitBlock(ExitBB);
3401 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003402 CodeGenFunction::JumpDest CancelDestination =
Alexey Bataev25e5b442015-09-15 12:52:43 +00003403 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003404 CGF.EmitBranchThroughCleanup(CancelDestination);
3405 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
3406 }
3407 return;
3408 }
3409 }
3410 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003411}
3412
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003413/// Map the OpenMP loop schedule to the runtime enumeration.
Alexander Musmanc6388682014-12-15 07:07:06 +00003414static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003415 bool Chunked, bool Ordered) {
Alexander Musmanc6388682014-12-15 07:07:06 +00003416 switch (ScheduleKind) {
3417 case OMPC_SCHEDULE_static:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003418 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
3419 : (Ordered ? OMP_ord_static : OMP_sch_static);
Alexander Musmanc6388682014-12-15 07:07:06 +00003420 case OMPC_SCHEDULE_dynamic:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003421 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00003422 case OMPC_SCHEDULE_guided:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003423 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00003424 case OMPC_SCHEDULE_runtime:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003425 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
3426 case OMPC_SCHEDULE_auto:
3427 return Ordered ? OMP_ord_auto : OMP_sch_auto;
Alexander Musmanc6388682014-12-15 07:07:06 +00003428 case OMPC_SCHEDULE_unknown:
3429 assert(!Chunked && "chunk was specified but schedule kind not known");
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003430 return Ordered ? OMP_ord_static : OMP_sch_static;
Alexander Musmanc6388682014-12-15 07:07:06 +00003431 }
3432 llvm_unreachable("Unexpected runtime schedule");
3433}
3434
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003435/// Map the OpenMP distribute schedule to the runtime enumeration.
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003436static OpenMPSchedType
3437getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
3438 // only static is allowed for dist_schedule
3439 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
3440}
3441
Alexander Musmanc6388682014-12-15 07:07:06 +00003442bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
3443 bool Chunked) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003444 OpenMPSchedType Schedule =
3445 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
Alexander Musmanc6388682014-12-15 07:07:06 +00003446 return Schedule == OMP_sch_static;
3447}
3448
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003449bool CGOpenMPRuntime::isStaticNonchunked(
3450 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003451 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003452 return Schedule == OMP_dist_sch_static;
3453}
3454
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00003455bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind,
3456 bool Chunked) const {
3457 OpenMPSchedType Schedule =
3458 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
3459 return Schedule == OMP_sch_static_chunked;
3460}
3461
3462bool CGOpenMPRuntime::isStaticChunked(
3463 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
3464 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
3465 return Schedule == OMP_dist_sch_static_chunked;
3466}
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003467
Alexander Musmandf7a8e22015-01-22 08:49:35 +00003468bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003469 OpenMPSchedType Schedule =
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003470 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00003471 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
3472 return Schedule != OMP_sch_static;
3473}
3474
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003475static int addMonoNonMonoModifier(OpenMPSchedType Schedule,
3476 OpenMPScheduleClauseModifier M1,
3477 OpenMPScheduleClauseModifier M2) {
Alexey Bataev6cff6242016-05-30 13:05:14 +00003478 int Modifier = 0;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003479 switch (M1) {
3480 case OMPC_SCHEDULE_MODIFIER_monotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003481 Modifier = OMP_sch_modifier_monotonic;
3482 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003483 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003484 Modifier = OMP_sch_modifier_nonmonotonic;
3485 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003486 case OMPC_SCHEDULE_MODIFIER_simd:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003487 if (Schedule == OMP_sch_static_chunked)
3488 Schedule = OMP_sch_static_balanced_chunked;
3489 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003490 case OMPC_SCHEDULE_MODIFIER_last:
3491 case OMPC_SCHEDULE_MODIFIER_unknown:
3492 break;
3493 }
3494 switch (M2) {
3495 case OMPC_SCHEDULE_MODIFIER_monotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003496 Modifier = OMP_sch_modifier_monotonic;
3497 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003498 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003499 Modifier = OMP_sch_modifier_nonmonotonic;
3500 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003501 case OMPC_SCHEDULE_MODIFIER_simd:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003502 if (Schedule == OMP_sch_static_chunked)
3503 Schedule = OMP_sch_static_balanced_chunked;
3504 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003505 case OMPC_SCHEDULE_MODIFIER_last:
3506 case OMPC_SCHEDULE_MODIFIER_unknown:
3507 break;
3508 }
Alexey Bataev6cff6242016-05-30 13:05:14 +00003509 return Schedule | Modifier;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003510}
3511
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003512void CGOpenMPRuntime::emitForDispatchInit(
3513 CodeGenFunction &CGF, SourceLocation Loc,
3514 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
3515 bool Ordered, const DispatchRTInput &DispatchValues) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003516 if (!CGF.HaveInsertPoint())
3517 return;
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003518 OpenMPSchedType Schedule = getRuntimeSchedule(
3519 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered);
John McCall7f416cc2015-09-08 08:05:57 +00003520 assert(Ordered ||
3521 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
Alexey Bataev6cff6242016-05-30 13:05:14 +00003522 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
3523 Schedule != OMP_sch_static_balanced_chunked));
John McCall7f416cc2015-09-08 08:05:57 +00003524 // Call __kmpc_dispatch_init(
3525 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
3526 // kmp_int[32|64] lower, kmp_int[32|64] upper,
3527 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00003528
John McCall7f416cc2015-09-08 08:05:57 +00003529 // If the Chunk was not specified in the clause - use default value 1.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003530 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk
3531 : CGF.Builder.getIntN(IVSize, 1);
John McCall7f416cc2015-09-08 08:05:57 +00003532 llvm::Value *Args[] = {
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003533 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3534 CGF.Builder.getInt32(addMonoNonMonoModifier(
3535 Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003536 DispatchValues.LB, // Lower
3537 DispatchValues.UB, // Upper
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003538 CGF.Builder.getIntN(IVSize, 1), // Stride
3539 Chunk // Chunk
John McCall7f416cc2015-09-08 08:05:57 +00003540 };
3541 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
3542}
3543
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003544static void emitForStaticInitCall(
3545 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
James Y Knight9871db02019-02-05 16:42:33 +00003546 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003547 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003548 const CGOpenMPRuntime::StaticRTInput &Values) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003549 if (!CGF.HaveInsertPoint())
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003550 return;
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003551
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003552 assert(!Values.Ordered);
3553 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
3554 Schedule == OMP_sch_static_balanced_chunked ||
3555 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
3556 Schedule == OMP_dist_sch_static ||
3557 Schedule == OMP_dist_sch_static_chunked);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003558
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003559 // Call __kmpc_for_static_init(
3560 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
3561 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
3562 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
3563 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
3564 llvm::Value *Chunk = Values.Chunk;
3565 if (Chunk == nullptr) {
3566 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
3567 Schedule == OMP_dist_sch_static) &&
3568 "expected static non-chunked schedule");
3569 // If the Chunk was not specified in the clause - use default value 1.
3570 Chunk = CGF.Builder.getIntN(Values.IVSize, 1);
3571 } else {
3572 assert((Schedule == OMP_sch_static_chunked ||
3573 Schedule == OMP_sch_static_balanced_chunked ||
3574 Schedule == OMP_ord_static_chunked ||
3575 Schedule == OMP_dist_sch_static_chunked) &&
3576 "expected static chunked schedule");
3577 }
3578 llvm::Value *Args[] = {
3579 UpdateLocation,
3580 ThreadId,
3581 CGF.Builder.getInt32(addMonoNonMonoModifier(Schedule, M1,
3582 M2)), // Schedule type
3583 Values.IL.getPointer(), // &isLastIter
3584 Values.LB.getPointer(), // &LB
3585 Values.UB.getPointer(), // &UB
3586 Values.ST.getPointer(), // &Stride
3587 CGF.Builder.getIntN(Values.IVSize, 1), // Incr
3588 Chunk // Chunk
3589 };
3590 CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003591}
3592
John McCall7f416cc2015-09-08 08:05:57 +00003593void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
3594 SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003595 OpenMPDirectiveKind DKind,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003596 const OpenMPScheduleTy &ScheduleKind,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003597 const StaticRTInput &Values) {
3598 OpenMPSchedType ScheduleNum = getRuntimeSchedule(
3599 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered);
3600 assert(isOpenMPWorksharingDirective(DKind) &&
3601 "Expected loop-based or sections-based directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003602 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003603 isOpenMPLoopDirective(DKind)
3604 ? OMP_IDENT_WORK_LOOP
3605 : OMP_IDENT_WORK_SECTIONS);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003606 llvm::Value *ThreadId = getThreadID(CGF, Loc);
James Y Knight9871db02019-02-05 16:42:33 +00003607 llvm::FunctionCallee StaticInitFunction =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003608 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003609 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003610 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003611}
John McCall7f416cc2015-09-08 08:05:57 +00003612
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003613void CGOpenMPRuntime::emitDistributeStaticInit(
3614 CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003615 OpenMPDistScheduleClauseKind SchedKind,
3616 const CGOpenMPRuntime::StaticRTInput &Values) {
3617 OpenMPSchedType ScheduleNum =
3618 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003619 llvm::Value *UpdatedLocation =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003620 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003621 llvm::Value *ThreadId = getThreadID(CGF, Loc);
James Y Knight9871db02019-02-05 16:42:33 +00003622 llvm::FunctionCallee StaticInitFunction =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003623 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003624 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
3625 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003626 OMPC_SCHEDULE_MODIFIER_unknown, Values);
Alexander Musmanc6388682014-12-15 07:07:06 +00003627}
3628
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003629void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
Alexey Bataevf43f7142017-09-06 16:17:35 +00003630 SourceLocation Loc,
3631 OpenMPDirectiveKind DKind) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003632 if (!CGF.HaveInsertPoint())
3633 return;
Alexander Musmanc6388682014-12-15 07:07:06 +00003634 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataevf43f7142017-09-06 16:17:35 +00003635 llvm::Value *Args[] = {
3636 emitUpdateLocation(CGF, Loc,
3637 isOpenMPDistributeDirective(DKind)
3638 ? OMP_IDENT_WORK_DISTRIBUTE
3639 : isOpenMPLoopDirective(DKind)
3640 ? OMP_IDENT_WORK_LOOP
3641 : OMP_IDENT_WORK_SECTIONS),
3642 getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003643 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
3644 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00003645}
3646
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003647void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
3648 SourceLocation Loc,
3649 unsigned IVSize,
3650 bool IVSigned) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003651 if (!CGF.HaveInsertPoint())
3652 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003653 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00003654 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003655 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
3656}
3657
Alexander Musman92bdaab2015-03-12 13:37:50 +00003658llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
3659 SourceLocation Loc, unsigned IVSize,
John McCall7f416cc2015-09-08 08:05:57 +00003660 bool IVSigned, Address IL,
3661 Address LB, Address UB,
3662 Address ST) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00003663 // Call __kmpc_dispatch_next(
3664 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
3665 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
3666 // kmp_int[32|64] *p_stride);
3667 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00003668 emitUpdateLocation(CGF, Loc),
3669 getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00003670 IL.getPointer(), // &isLastIter
3671 LB.getPointer(), // &Lower
3672 UB.getPointer(), // &Upper
3673 ST.getPointer() // &Stride
Alexander Musman92bdaab2015-03-12 13:37:50 +00003674 };
3675 llvm::Value *Call =
3676 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
3677 return CGF.EmitScalarConversion(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003678 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00003679 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00003680}
3681
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003682void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
3683 llvm::Value *NumThreads,
3684 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003685 if (!CGF.HaveInsertPoint())
3686 return;
Alexey Bataevb2059782014-10-13 08:23:51 +00003687 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
3688 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003689 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00003690 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003691 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
3692 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00003693}
3694
Alexey Bataev7f210c62015-06-18 13:40:03 +00003695void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
3696 OpenMPProcBindClauseKind ProcBind,
3697 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003698 if (!CGF.HaveInsertPoint())
3699 return;
Alexey Bataev7f210c62015-06-18 13:40:03 +00003700 // Constants for proc bind value accepted by the runtime.
3701 enum ProcBindTy {
3702 ProcBindFalse = 0,
3703 ProcBindTrue,
3704 ProcBindMaster,
3705 ProcBindClose,
3706 ProcBindSpread,
3707 ProcBindIntel,
3708 ProcBindDefault
3709 } RuntimeProcBind;
3710 switch (ProcBind) {
3711 case OMPC_PROC_BIND_master:
3712 RuntimeProcBind = ProcBindMaster;
3713 break;
3714 case OMPC_PROC_BIND_close:
3715 RuntimeProcBind = ProcBindClose;
3716 break;
3717 case OMPC_PROC_BIND_spread:
3718 RuntimeProcBind = ProcBindSpread;
3719 break;
3720 case OMPC_PROC_BIND_unknown:
3721 llvm_unreachable("Unsupported proc_bind value.");
3722 }
3723 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
3724 llvm::Value *Args[] = {
3725 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3726 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
3727 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
3728}
3729
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003730void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
3731 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003732 if (!CGF.HaveInsertPoint())
3733 return;
Alexey Bataevd76df6d2015-02-24 12:55:09 +00003734 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003735 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
3736 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00003737}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003738
Alexey Bataev62b63b12015-03-10 07:28:44 +00003739namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003740/// Indexes of fields for type kmp_task_t.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003741enum KmpTaskTFields {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003742 /// List of shared variables.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003743 KmpTaskTShareds,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003744 /// Task routine.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003745 KmpTaskTRoutine,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003746 /// Partition id for the untied tasks.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003747 KmpTaskTPartId,
Alexey Bataevad537bb2016-05-30 09:06:50 +00003748 /// Function with call of destructors for private variables.
3749 Data1,
3750 /// Task priority.
3751 Data2,
Alexey Bataev7292c292016-04-25 12:22:29 +00003752 /// (Taskloops only) Lower bound.
3753 KmpTaskTLowerBound,
3754 /// (Taskloops only) Upper bound.
3755 KmpTaskTUpperBound,
3756 /// (Taskloops only) Stride.
3757 KmpTaskTStride,
3758 /// (Taskloops only) Is last iteration flag.
3759 KmpTaskTLastIter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003760 /// (Taskloops only) Reduction data.
3761 KmpTaskTReductions,
Alexey Bataev62b63b12015-03-10 07:28:44 +00003762};
Hans Wennborg7eb54642015-09-10 17:07:54 +00003763} // anonymous namespace
Alexey Bataev62b63b12015-03-10 07:28:44 +00003764
Samuel Antaoee8fb302016-01-06 13:42:12 +00003765bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003766 return OffloadEntriesTargetRegion.empty() &&
3767 OffloadEntriesDeviceGlobalVar.empty();
Samuel Antaoee8fb302016-01-06 13:42:12 +00003768}
3769
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003770/// Initialize target region entry.
Samuel Antaoee8fb302016-01-06 13:42:12 +00003771void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3772 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3773 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00003774 unsigned Order) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003775 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
3776 "only required for the device "
3777 "code generation.");
Samuel Antao2de62b02016-02-13 23:35:10 +00003778 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
Samuel Antaof83efdb2017-01-05 16:02:49 +00003779 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003780 OMPTargetRegionEntryTargetRegion);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003781 ++OffloadingEntriesNum;
3782}
3783
3784void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3785 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3786 StringRef ParentName, unsigned LineNum,
Samuel Antaof83efdb2017-01-05 16:02:49 +00003787 llvm::Constant *Addr, llvm::Constant *ID,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003788 OMPTargetRegionEntryKind Flags) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003789 // If we are emitting code for a target, the entry is already initialized,
3790 // only has to be registered.
3791 if (CGM.getLangOpts().OpenMPIsDevice) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00003792 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) {
3793 unsigned DiagID = CGM.getDiags().getCustomDiagID(
3794 DiagnosticsEngine::Error,
3795 "Unable to find target region on line '%0' in the device code.");
3796 CGM.getDiags().Report(DiagID) << LineNum;
3797 return;
3798 }
Samuel Antao2de62b02016-02-13 23:35:10 +00003799 auto &Entry =
3800 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
Samuel Antaoee8fb302016-01-06 13:42:12 +00003801 assert(Entry.isValid() && "Entry not initialized!");
3802 Entry.setAddress(Addr);
3803 Entry.setID(ID);
Samuel Antaof83efdb2017-01-05 16:02:49 +00003804 Entry.setFlags(Flags);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003805 } else {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003806 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags);
Samuel Antao2de62b02016-02-13 23:35:10 +00003807 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00003808 ++OffloadingEntriesNum;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003809 }
3810}
3811
3812bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00003813 unsigned DeviceID, unsigned FileID, StringRef ParentName,
3814 unsigned LineNum) const {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003815 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
3816 if (PerDevice == OffloadEntriesTargetRegion.end())
3817 return false;
3818 auto PerFile = PerDevice->second.find(FileID);
3819 if (PerFile == PerDevice->second.end())
3820 return false;
3821 auto PerParentName = PerFile->second.find(ParentName);
3822 if (PerParentName == PerFile->second.end())
3823 return false;
3824 auto PerLine = PerParentName->second.find(LineNum);
3825 if (PerLine == PerParentName->second.end())
3826 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003827 // Fail if this entry is already registered.
Samuel Antao2de62b02016-02-13 23:35:10 +00003828 if (PerLine->second.getAddress() || PerLine->second.getID())
Samuel Antaoee8fb302016-01-06 13:42:12 +00003829 return false;
3830 return true;
3831}
3832
3833void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
3834 const OffloadTargetRegionEntryInfoActTy &Action) {
3835 // Scan all target region entries and perform the provided action.
Alexey Bataev03f270c2018-03-30 18:31:07 +00003836 for (const auto &D : OffloadEntriesTargetRegion)
3837 for (const auto &F : D.second)
3838 for (const auto &P : F.second)
3839 for (const auto &L : P.second)
Samuel Antao2de62b02016-02-13 23:35:10 +00003840 Action(D.first, F.first, P.first(), L.first, L.second);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003841}
3842
Alexey Bataev03f270c2018-03-30 18:31:07 +00003843void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3844 initializeDeviceGlobalVarEntryInfo(StringRef Name,
3845 OMPTargetGlobalVarEntryKind Flags,
3846 unsigned Order) {
3847 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
3848 "only required for the device "
3849 "code generation.");
3850 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
3851 ++OffloadingEntriesNum;
3852}
Samuel Antaoee8fb302016-01-06 13:42:12 +00003853
Alexey Bataev03f270c2018-03-30 18:31:07 +00003854void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3855 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr,
3856 CharUnits VarSize,
3857 OMPTargetGlobalVarEntryKind Flags,
3858 llvm::GlobalValue::LinkageTypes Linkage) {
3859 if (CGM.getLangOpts().OpenMPIsDevice) {
3860 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3861 assert(Entry.isValid() && Entry.getFlags() == Flags &&
3862 "Entry not initialized!");
3863 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
3864 "Resetting with the new address.");
Alexey Bataev8259cc32019-03-12 20:05:17 +00003865 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) {
3866 if (Entry.getVarSize().isZero()) {
3867 Entry.setVarSize(VarSize);
3868 Entry.setLinkage(Linkage);
3869 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003870 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00003871 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003872 Entry.setVarSize(VarSize);
3873 Entry.setLinkage(Linkage);
Alexey Bataev8259cc32019-03-12 20:05:17 +00003874 Entry.setAddress(Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00003875 } else {
Alexey Bataev8259cc32019-03-12 20:05:17 +00003876 if (hasDeviceGlobalVarEntryInfo(VarName)) {
3877 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3878 assert(Entry.isValid() && Entry.getFlags() == Flags &&
3879 "Entry not initialized!");
3880 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
3881 "Resetting with the new address.");
3882 if (Entry.getVarSize().isZero()) {
3883 Entry.setVarSize(VarSize);
3884 Entry.setLinkage(Linkage);
3885 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003886 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00003887 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003888 OffloadEntriesDeviceGlobalVar.try_emplace(
3889 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage);
3890 ++OffloadingEntriesNum;
3891 }
3892}
3893
3894void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3895 actOnDeviceGlobalVarEntriesInfo(
3896 const OffloadDeviceGlobalVarEntryInfoActTy &Action) {
3897 // Scan all target region entries and perform the provided action.
3898 for (const auto &E : OffloadEntriesDeviceGlobalVar)
3899 Action(E.getKey(), E.getValue());
Samuel Antaoee8fb302016-01-06 13:42:12 +00003900}
3901
3902llvm::Function *
3903CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003904 // If we don't have entries or if we are emitting code for the device, we
3905 // don't need to do anything.
3906 if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty())
3907 return nullptr;
3908
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003909 llvm::Module &M = CGM.getModule();
3910 ASTContext &C = CGM.getContext();
Samuel Antaoee8fb302016-01-06 13:42:12 +00003911
3912 // Get list of devices we care about
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003913 const std::vector<llvm::Triple> &Devices = CGM.getLangOpts().OMPTargetTriples;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003914
3915 // We should be creating an offloading descriptor only if there are devices
3916 // specified.
3917 assert(!Devices.empty() && "No OpenMP offloading devices??");
3918
3919 // Create the external variables that will point to the begin and end of the
3920 // host entries section. These will be defined by the linker.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003921 llvm::Type *OffloadEntryTy =
Samuel Antaoee8fb302016-01-06 13:42:12 +00003922 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy());
Alexey Bataev18fa2322018-05-02 14:20:50 +00003923 std::string EntriesBeginName = getName({"omp_offloading", "entries_begin"});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003924 auto *HostEntriesBegin = new llvm::GlobalVariable(
Samuel Antaoee8fb302016-01-06 13:42:12 +00003925 M, OffloadEntryTy, /*isConstant=*/true,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00003926 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr,
Alexey Bataev18fa2322018-05-02 14:20:50 +00003927 EntriesBeginName);
3928 std::string EntriesEndName = getName({"omp_offloading", "entries_end"});
3929 auto *HostEntriesEnd =
3930 new llvm::GlobalVariable(M, OffloadEntryTy, /*isConstant=*/true,
3931 llvm::GlobalValue::ExternalLinkage,
3932 /*Initializer=*/nullptr, EntriesEndName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003933
3934 // Create all device images
Samuel Antaoee8fb302016-01-06 13:42:12 +00003935 auto *DeviceImageTy = cast<llvm::StructType>(
3936 CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy()));
John McCall23c9dc62016-11-28 22:18:27 +00003937 ConstantInitBuilder DeviceImagesBuilder(CGM);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003938 ConstantArrayBuilder DeviceImagesEntries =
3939 DeviceImagesBuilder.beginArray(DeviceImageTy);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003940
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003941 for (const llvm::Triple &Device : Devices) {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003942 StringRef T = Device.getTriple();
Alexey Bataev18fa2322018-05-02 14:20:50 +00003943 std::string BeginName = getName({"omp_offloading", "img_start", ""});
Samuel Antaoee8fb302016-01-06 13:42:12 +00003944 auto *ImgBegin = new llvm::GlobalVariable(
Alexey Bataev62a4cb02018-07-31 18:27:42 +00003945 M, CGM.Int8Ty, /*isConstant=*/true,
3946 llvm::GlobalValue::ExternalWeakLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00003947 /*Initializer=*/nullptr, Twine(BeginName).concat(T));
3948 std::string EndName = getName({"omp_offloading", "img_end", ""});
Samuel Antaoee8fb302016-01-06 13:42:12 +00003949 auto *ImgEnd = new llvm::GlobalVariable(
Alexey Bataev62a4cb02018-07-31 18:27:42 +00003950 M, CGM.Int8Ty, /*isConstant=*/true,
3951 llvm::GlobalValue::ExternalWeakLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00003952 /*Initializer=*/nullptr, Twine(EndName).concat(T));
Samuel Antaoee8fb302016-01-06 13:42:12 +00003953
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003954 llvm::Constant *Data[] = {ImgBegin, ImgEnd, HostEntriesBegin,
3955 HostEntriesEnd};
3956 createConstantGlobalStructAndAddToParent(CGM, getTgtDeviceImageQTy(), Data,
3957 DeviceImagesEntries);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003958 }
3959
3960 // Create device images global array.
Alexey Bataev18fa2322018-05-02 14:20:50 +00003961 std::string ImagesName = getName({"omp_offloading", "device_images"});
John McCall6c9f1fdb2016-11-19 08:17:24 +00003962 llvm::GlobalVariable *DeviceImages =
Alexey Bataev18fa2322018-05-02 14:20:50 +00003963 DeviceImagesEntries.finishAndCreateGlobal(ImagesName,
3964 CGM.getPointerAlign(),
3965 /*isConstant=*/true);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00003966 DeviceImages->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003967
3968 // This is a Zero array to be used in the creation of the constant expressions
3969 llvm::Constant *Index[] = {llvm::Constant::getNullValue(CGM.Int32Ty),
3970 llvm::Constant::getNullValue(CGM.Int32Ty)};
3971
3972 // Create the target region descriptor.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003973 llvm::Constant *Data[] = {
3974 llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()),
3975 llvm::ConstantExpr::getGetElementPtr(DeviceImages->getValueType(),
3976 DeviceImages, Index),
3977 HostEntriesBegin, HostEntriesEnd};
Alexey Bataev18fa2322018-05-02 14:20:50 +00003978 std::string Descriptor = getName({"omp_offloading", "descriptor"});
Mike Ricee1ca7b62018-08-29 15:45:11 +00003979 llvm::GlobalVariable *Desc = createGlobalStruct(
3980 CGM, getTgtBinaryDescriptorQTy(), /*IsConstant=*/true, Data, Descriptor);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003981
3982 // Emit code to register or unregister the descriptor at execution
3983 // startup or closing, respectively.
3984
Alexey Bataev03f270c2018-03-30 18:31:07 +00003985 llvm::Function *UnRegFn;
3986 {
3987 FunctionArgList Args;
3988 ImplicitParamDecl DummyPtr(C, C.VoidPtrTy, ImplicitParamDecl::Other);
3989 Args.push_back(&DummyPtr);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003990
Alexey Bataev03f270c2018-03-30 18:31:07 +00003991 CodeGenFunction CGF(CGM);
3992 // Disable debug info for global (de-)initializer because they are not part
3993 // of some particular construct.
3994 CGF.disableDebugInfo();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003995 const auto &FI =
3996 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
3997 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00003998 std::string UnregName = getName({"omp_offloading", "descriptor_unreg"});
3999 UnRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, UnregName, FI);
Alexey Bataev03f270c2018-03-30 18:31:07 +00004000 CGF.StartFunction(GlobalDecl(), C.VoidTy, UnRegFn, FI, Args);
4001 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_unregister_lib),
4002 Desc);
4003 CGF.FinishFunction();
4004 }
4005 llvm::Function *RegFn;
4006 {
4007 CodeGenFunction CGF(CGM);
4008 // Disable debug info for global (de-)initializer because they are not part
4009 // of some particular construct.
4010 CGF.disableDebugInfo();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004011 const auto &FI = CGM.getTypes().arrangeNullaryFunction();
Alexey Bataev03f270c2018-03-30 18:31:07 +00004012 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Sergey Dmitrievbde9cf92018-08-03 20:19:28 +00004013
4014 // Encode offload target triples into the registration function name. It
4015 // will serve as a comdat key for the registration/unregistration code for
4016 // this particular combination of offloading targets.
4017 SmallVector<StringRef, 4U> RegFnNameParts(Devices.size() + 2U);
4018 RegFnNameParts[0] = "omp_offloading";
4019 RegFnNameParts[1] = "descriptor_reg";
4020 llvm::transform(Devices, std::next(RegFnNameParts.begin(), 2),
4021 [](const llvm::Triple &T) -> const std::string& {
4022 return T.getTriple();
4023 });
4024 llvm::sort(std::next(RegFnNameParts.begin(), 2), RegFnNameParts.end());
4025 std::string Descriptor = getName(RegFnNameParts);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004026 RegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, Descriptor, FI);
Alexey Bataev03f270c2018-03-30 18:31:07 +00004027 CGF.StartFunction(GlobalDecl(), C.VoidTy, RegFn, FI, FunctionArgList());
4028 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_lib), Desc);
4029 // Create a variable to drive the registration and unregistration of the
4030 // descriptor, so we can reuse the logic that emits Ctors and Dtors.
4031 ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(),
4032 SourceLocation(), nullptr, C.CharTy,
4033 ImplicitParamDecl::Other);
4034 CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc);
4035 CGF.FinishFunction();
4036 }
George Rokos29d0f002017-05-27 03:03:13 +00004037 if (CGM.supportsCOMDAT()) {
4038 // It is sufficient to call registration function only once, so create a
4039 // COMDAT group for registration/unregistration functions and associated
4040 // data. That would reduce startup time and code size. Registration
4041 // function serves as a COMDAT group key.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004042 llvm::Comdat *ComdatKey = M.getOrInsertComdat(RegFn->getName());
George Rokos29d0f002017-05-27 03:03:13 +00004043 RegFn->setLinkage(llvm::GlobalValue::LinkOnceAnyLinkage);
4044 RegFn->setVisibility(llvm::GlobalValue::HiddenVisibility);
4045 RegFn->setComdat(ComdatKey);
4046 UnRegFn->setComdat(ComdatKey);
4047 DeviceImages->setComdat(ComdatKey);
4048 Desc->setComdat(ComdatKey);
4049 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004050 return RegFn;
4051}
4052
Alexey Bataev03f270c2018-03-30 18:31:07 +00004053void CGOpenMPRuntime::createOffloadEntry(
4054 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags,
4055 llvm::GlobalValue::LinkageTypes Linkage) {
Samuel Antao2de62b02016-02-13 23:35:10 +00004056 StringRef Name = Addr->getName();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004057 llvm::Module &M = CGM.getModule();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004058 llvm::LLVMContext &C = M.getContext();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004059
4060 // Create constant string with the name.
4061 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
4062
Alexey Bataev18fa2322018-05-02 14:20:50 +00004063 std::string StringName = getName({"omp_offloading", "entry_name"});
4064 auto *Str = new llvm::GlobalVariable(
4065 M, StrPtrInit->getType(), /*isConstant=*/true,
4066 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00004067 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004068
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004069 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy),
4070 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy),
4071 llvm::ConstantInt::get(CGM.SizeTy, Size),
4072 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
4073 llvm::ConstantInt::get(CGM.Int32Ty, 0)};
Alexey Bataev18fa2322018-05-02 14:20:50 +00004074 std::string EntryName = getName({"omp_offloading", "entry", ""});
Mike Ricee1ca7b62018-08-29 15:45:11 +00004075 llvm::GlobalVariable *Entry = createGlobalStruct(
4076 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data,
4077 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004078
4079 // The entry has to be created in the section the linker expects it to be.
Alexey Bataev18fa2322018-05-02 14:20:50 +00004080 std::string Section = getName({"omp_offloading", "entries"});
4081 Entry->setSection(Section);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004082}
4083
4084void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
4085 // Emit the offloading entries and metadata so that the device codegen side
Samuel Antao4c8035b2016-12-12 18:00:20 +00004086 // can easily figure out what to emit. The produced metadata looks like
4087 // this:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004088 //
4089 // !omp_offload.info = !{!1, ...}
4090 //
4091 // Right now we only generate metadata for function that contain target
4092 // regions.
4093
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00004094 // If we do not have entries, we don't need to do anything.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004095 if (OffloadEntriesInfoManager.empty())
4096 return;
4097
4098 llvm::Module &M = CGM.getModule();
4099 llvm::LLVMContext &C = M.getContext();
Alexey Bataev03f270c2018-03-30 18:31:07 +00004100 SmallVector<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16>
Samuel Antaoee8fb302016-01-06 13:42:12 +00004101 OrderedEntries(OffloadEntriesInfoManager.size());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004102 llvm::SmallVector<StringRef, 16> ParentFunctions(
4103 OffloadEntriesInfoManager.size());
Samuel Antaoee8fb302016-01-06 13:42:12 +00004104
Simon Pilgrim2c518802017-03-30 14:13:19 +00004105 // Auxiliary methods to create metadata values and strings.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004106 auto &&GetMDInt = [this](unsigned V) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004107 return llvm::ConstantAsMetadata::get(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004108 llvm::ConstantInt::get(CGM.Int32Ty, V));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004109 };
4110
Alexey Bataev03f270c2018-03-30 18:31:07 +00004111 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); };
4112
4113 // Create the offloading info metadata node.
4114 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004115
4116 // Create function that emits metadata for each target region entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00004117 auto &&TargetRegionMetadataEmitter =
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004118 [&C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, &GetMDString](
Alexey Bataev03f270c2018-03-30 18:31:07 +00004119 unsigned DeviceID, unsigned FileID, StringRef ParentName,
4120 unsigned Line,
4121 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
4122 // Generate metadata for target regions. Each entry of this metadata
4123 // contains:
4124 // - Entry 0 -> Kind of this type of metadata (0).
4125 // - Entry 1 -> Device ID of the file where the entry was identified.
4126 // - Entry 2 -> File ID of the file where the entry was identified.
4127 // - Entry 3 -> Mangled name of the function where the entry was
4128 // identified.
4129 // - Entry 4 -> Line in the file where the entry was identified.
4130 // - Entry 5 -> Order the entry was created.
4131 // The first element of the metadata node is the kind.
4132 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID),
4133 GetMDInt(FileID), GetMDString(ParentName),
4134 GetMDInt(Line), GetMDInt(E.getOrder())};
Samuel Antaoee8fb302016-01-06 13:42:12 +00004135
Alexey Bataev03f270c2018-03-30 18:31:07 +00004136 // Save this entry in the right position of the ordered entries array.
4137 OrderedEntries[E.getOrder()] = &E;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004138 ParentFunctions[E.getOrder()] = ParentName;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004139
Alexey Bataev03f270c2018-03-30 18:31:07 +00004140 // Add metadata to the named metadata node.
4141 MD->addOperand(llvm::MDNode::get(C, Ops));
4142 };
Samuel Antaoee8fb302016-01-06 13:42:12 +00004143
4144 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
4145 TargetRegionMetadataEmitter);
4146
Alexey Bataev03f270c2018-03-30 18:31:07 +00004147 // Create function that emits metadata for each device global variable entry;
4148 auto &&DeviceGlobalVarMetadataEmitter =
4149 [&C, &OrderedEntries, &GetMDInt, &GetMDString,
4150 MD](StringRef MangledName,
4151 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar
4152 &E) {
4153 // Generate metadata for global variables. Each entry of this metadata
4154 // contains:
4155 // - Entry 0 -> Kind of this type of metadata (1).
4156 // - Entry 1 -> Mangled name of the variable.
4157 // - Entry 2 -> Declare target kind.
4158 // - Entry 3 -> Order the entry was created.
4159 // The first element of the metadata node is the kind.
4160 llvm::Metadata *Ops[] = {
4161 GetMDInt(E.getKind()), GetMDString(MangledName),
4162 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
4163
4164 // Save this entry in the right position of the ordered entries array.
4165 OrderedEntries[E.getOrder()] = &E;
4166
4167 // Add metadata to the named metadata node.
4168 MD->addOperand(llvm::MDNode::get(C, Ops));
4169 };
4170
4171 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo(
4172 DeviceGlobalVarMetadataEmitter);
4173
4174 for (const auto *E : OrderedEntries) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004175 assert(E && "All ordered entries must exist!");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004176 if (const auto *CE =
Samuel Antaoee8fb302016-01-06 13:42:12 +00004177 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
4178 E)) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004179 if (!CE->getID() || !CE->getAddress()) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004180 // Do not blame the entry if the parent funtion is not emitted.
4181 StringRef FnName = ParentFunctions[CE->getOrder()];
4182 if (!CGM.GetGlobalValue(FnName))
4183 continue;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004184 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4185 DiagnosticsEngine::Error,
Alexey Bataev7f01d202018-07-16 18:12:18 +00004186 "Offloading entry for target region is incorrect: either the "
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004187 "address or the ID is invalid.");
4188 CGM.getDiags().Report(DiagID);
4189 continue;
4190 }
Alexey Bataev34f8a702018-03-28 14:28:54 +00004191 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004192 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage);
4193 } else if (const auto *CE =
4194 dyn_cast<OffloadEntriesInfoManagerTy::
4195 OffloadEntryInfoDeviceGlobalVar>(E)) {
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004196 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags =
4197 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4198 CE->getFlags());
4199 switch (Flags) {
4200 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00004201 if (CGM.getLangOpts().OpenMPIsDevice &&
4202 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())
4203 continue;
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004204 if (!CE->getAddress()) {
4205 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4206 DiagnosticsEngine::Error,
4207 "Offloading entry for declare target variable is incorrect: the "
4208 "address is invalid.");
4209 CGM.getDiags().Report(DiagID);
4210 continue;
4211 }
Alexey Bataevb4dd6d22018-08-29 20:41:37 +00004212 // The vaiable has no definition - no need to add the entry.
4213 if (CE->getVarSize().isZero())
4214 continue;
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004215 break;
4216 }
4217 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink:
4218 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) ||
4219 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) &&
4220 "Declaret target link address is set.");
4221 if (CGM.getLangOpts().OpenMPIsDevice)
4222 continue;
4223 if (!CE->getAddress()) {
4224 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4225 DiagnosticsEngine::Error,
4226 "Offloading entry for declare target variable is incorrect: the "
4227 "address is invalid.");
4228 CGM.getDiags().Report(DiagID);
4229 continue;
4230 }
4231 break;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004232 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004233 createOffloadEntry(CE->getAddress(), CE->getAddress(),
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004234 CE->getVarSize().getQuantity(), Flags,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004235 CE->getLinkage());
4236 } else {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004237 llvm_unreachable("Unsupported entry kind.");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004238 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004239 }
4240}
4241
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004242/// Loads all the offload entries information from the host IR
Samuel Antaoee8fb302016-01-06 13:42:12 +00004243/// metadata.
4244void CGOpenMPRuntime::loadOffloadInfoMetadata() {
4245 // If we are in target mode, load the metadata from the host IR. This code has
4246 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
4247
4248 if (!CGM.getLangOpts().OpenMPIsDevice)
4249 return;
4250
4251 if (CGM.getLangOpts().OMPHostIRFile.empty())
4252 return;
4253
4254 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004255 if (auto EC = Buf.getError()) {
4256 CGM.getDiags().Report(diag::err_cannot_open_file)
4257 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004258 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004259 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004260
4261 llvm::LLVMContext C;
Peter Collingbourned9445c42016-11-13 07:00:17 +00004262 auto ME = expectedToErrorOrAndEmitErrors(
4263 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004264
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004265 if (auto EC = ME.getError()) {
4266 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4267 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'");
4268 CGM.getDiags().Report(DiagID)
4269 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004270 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004271 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004272
4273 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
4274 if (!MD)
4275 return;
4276
George Burgess IV00f70bd2018-03-01 05:43:23 +00004277 for (llvm::MDNode *MN : MD->operands()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004278 auto &&GetMDInt = [MN](unsigned Idx) {
4279 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004280 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
4281 };
4282
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004283 auto &&GetMDString = [MN](unsigned Idx) {
4284 auto *V = cast<llvm::MDString>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004285 return V->getString();
4286 };
4287
Alexey Bataev03f270c2018-03-30 18:31:07 +00004288 switch (GetMDInt(0)) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004289 default:
4290 llvm_unreachable("Unexpected metadata!");
4291 break;
4292 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
Alexey Bataev34f8a702018-03-28 14:28:54 +00004293 OffloadingEntryInfoTargetRegion:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004294 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
Alexey Bataev03f270c2018-03-30 18:31:07 +00004295 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2),
4296 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4),
4297 /*Order=*/GetMDInt(5));
4298 break;
4299 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
4300 OffloadingEntryInfoDeviceGlobalVar:
4301 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo(
4302 /*MangledName=*/GetMDString(1),
4303 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4304 /*Flags=*/GetMDInt(2)),
4305 /*Order=*/GetMDInt(3));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004306 break;
4307 }
4308 }
4309}
4310
Alexey Bataev62b63b12015-03-10 07:28:44 +00004311void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
4312 if (!KmpRoutineEntryPtrTy) {
4313 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004314 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004315 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
4316 FunctionProtoType::ExtProtoInfo EPI;
4317 KmpRoutineEntryPtrQTy = C.getPointerType(
4318 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
4319 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
4320 }
4321}
4322
Samuel Antaoee8fb302016-01-06 13:42:12 +00004323QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004324 // Make sure the type of the entry is already created. This is the type we
4325 // have to create:
4326 // struct __tgt_offload_entry{
4327 // void *addr; // Pointer to the offload entry info.
4328 // // (function or global)
4329 // char *name; // Name of the function or global.
4330 // size_t size; // Size of the entry info (0 if it a function).
Samuel Antaof83efdb2017-01-05 16:02:49 +00004331 // int32_t flags; // Flags associated with the entry, e.g. 'link'.
4332 // int32_t reserved; // Reserved, to use by the runtime library.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004333 // };
4334 if (TgtOffloadEntryQTy.isNull()) {
4335 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004336 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004337 RD->startDefinition();
4338 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4339 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
4340 addFieldToRecordDecl(C, RD, C.getSizeType());
Samuel Antaof83efdb2017-01-05 16:02:49 +00004341 addFieldToRecordDecl(
4342 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4343 addFieldToRecordDecl(
4344 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004345 RD->completeDefinition();
Jonas Hahnfeld5e4df282018-01-18 15:38:03 +00004346 RD->addAttr(PackedAttr::CreateImplicit(C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004347 TgtOffloadEntryQTy = C.getRecordType(RD);
4348 }
4349 return TgtOffloadEntryQTy;
4350}
4351
4352QualType CGOpenMPRuntime::getTgtDeviceImageQTy() {
4353 // These are the types we need to build:
4354 // struct __tgt_device_image{
4355 // void *ImageStart; // Pointer to the target code start.
4356 // void *ImageEnd; // Pointer to the target code end.
4357 // // We also add the host entries to the device image, as it may be useful
4358 // // for the target runtime to have access to that information.
4359 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all
4360 // // the entries.
4361 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
4362 // // entries (non inclusive).
4363 // };
4364 if (TgtDeviceImageQTy.isNull()) {
4365 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004366 RecordDecl *RD = C.buildImplicitRecord("__tgt_device_image");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004367 RD->startDefinition();
4368 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4369 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4370 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4371 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4372 RD->completeDefinition();
4373 TgtDeviceImageQTy = C.getRecordType(RD);
4374 }
4375 return TgtDeviceImageQTy;
4376}
4377
4378QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() {
4379 // struct __tgt_bin_desc{
4380 // int32_t NumDevices; // Number of devices supported.
4381 // __tgt_device_image *DeviceImages; // Arrays of device images
4382 // // (one per device).
4383 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the
4384 // // entries.
4385 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
4386 // // entries (non inclusive).
4387 // };
4388 if (TgtBinaryDescriptorQTy.isNull()) {
4389 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004390 RecordDecl *RD = C.buildImplicitRecord("__tgt_bin_desc");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004391 RD->startDefinition();
4392 addFieldToRecordDecl(
4393 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4394 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy()));
4395 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4396 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4397 RD->completeDefinition();
4398 TgtBinaryDescriptorQTy = C.getRecordType(RD);
4399 }
4400 return TgtBinaryDescriptorQTy;
4401}
4402
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004403namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00004404struct PrivateHelpersTy {
4405 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
4406 const VarDecl *PrivateElemInit)
4407 : Original(Original), PrivateCopy(PrivateCopy),
4408 PrivateElemInit(PrivateElemInit) {}
4409 const VarDecl *Original;
4410 const VarDecl *PrivateCopy;
4411 const VarDecl *PrivateElemInit;
4412};
4413typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Hans Wennborg7eb54642015-09-10 17:07:54 +00004414} // anonymous namespace
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004415
Alexey Bataev9e034042015-05-05 04:05:12 +00004416static RecordDecl *
Craig Topper8674c5c2015-09-29 04:30:07 +00004417createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004418 if (!Privates.empty()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004419 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004420 // Build struct .kmp_privates_t. {
4421 // /* private vars */
4422 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004423 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t");
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004424 RD->startDefinition();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004425 for (const auto &Pair : Privates) {
4426 const VarDecl *VD = Pair.second.Original;
4427 QualType Type = VD->getType().getNonReferenceType();
4428 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type);
Alexey Bataevc71a4092015-09-11 10:29:41 +00004429 if (VD->hasAttrs()) {
4430 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
4431 E(VD->getAttrs().end());
4432 I != E; ++I)
4433 FD->addAttr(*I);
4434 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004435 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004436 RD->completeDefinition();
4437 return RD;
4438 }
4439 return nullptr;
4440}
4441
Alexey Bataev9e034042015-05-05 04:05:12 +00004442static RecordDecl *
Alexey Bataev7292c292016-04-25 12:22:29 +00004443createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind,
4444 QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004445 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004446 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004447 // Build struct kmp_task_t {
4448 // void * shareds;
4449 // kmp_routine_entry_t routine;
4450 // kmp_int32 part_id;
Alexey Bataevad537bb2016-05-30 09:06:50 +00004451 // kmp_cmplrdata_t data1;
4452 // kmp_cmplrdata_t data2;
Alexey Bataev7292c292016-04-25 12:22:29 +00004453 // For taskloops additional fields:
4454 // kmp_uint64 lb;
4455 // kmp_uint64 ub;
4456 // kmp_int64 st;
4457 // kmp_int32 liter;
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004458 // void * reductions;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004459 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004460 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004461 UD->startDefinition();
4462 addFieldToRecordDecl(C, UD, KmpInt32Ty);
4463 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy);
4464 UD->completeDefinition();
4465 QualType KmpCmplrdataTy = C.getRecordType(UD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004466 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t");
Alexey Bataev62b63b12015-03-10 07:28:44 +00004467 RD->startDefinition();
4468 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4469 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
4470 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004471 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
4472 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004473 if (isOpenMPTaskLoopDirective(Kind)) {
4474 QualType KmpUInt64Ty =
4475 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
4476 QualType KmpInt64Ty =
4477 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
4478 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4479 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4480 addFieldToRecordDecl(C, RD, KmpInt64Ty);
4481 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004482 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004483 }
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004484 RD->completeDefinition();
4485 return RD;
4486}
4487
4488static RecordDecl *
4489createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004490 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004491 ASTContext &C = CGM.getContext();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004492 // Build struct kmp_task_t_with_privates {
4493 // kmp_task_t task_data;
4494 // .kmp_privates_t. privates;
4495 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004496 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004497 RD->startDefinition();
4498 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004499 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates))
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004500 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004501 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004502 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004503}
4504
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004505/// Emit a proxy function which accepts kmp_task_t as the second
Alexey Bataev62b63b12015-03-10 07:28:44 +00004506/// argument.
4507/// \code
4508/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00004509/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt,
Alexey Bataev7292c292016-04-25 12:22:29 +00004510/// For taskloops:
4511/// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004512/// tt->reductions, tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004513/// return 0;
4514/// }
4515/// \endcode
James Y Knight9871db02019-02-05 16:42:33 +00004516static llvm::Function *
Alexey Bataev62b63b12015-03-10 07:28:44 +00004517emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev7292c292016-04-25 12:22:29 +00004518 OpenMPDirectiveKind Kind, QualType KmpInt32Ty,
4519 QualType KmpTaskTWithPrivatesPtrQTy,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004520 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
James Y Knight9871db02019-02-05 16:42:33 +00004521 QualType SharedsPtrTy, llvm::Function *TaskFunction,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004522 llvm::Value *TaskPrivatesMap) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004523 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004524 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004525 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4526 ImplicitParamDecl::Other);
4527 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4528 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4529 ImplicitParamDecl::Other);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004530 Args.push_back(&GtidArg);
4531 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004532 const auto &TaskEntryFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004533 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004534 llvm::FunctionType *TaskEntryTy =
4535 CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004536 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""});
4537 auto *TaskEntry = llvm::Function::Create(
4538 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004539 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004540 TaskEntry->setDoesNotRecurse();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004541 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004542 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args,
4543 Loc, Loc);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004544
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004545 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
Alexey Bataev7292c292016-04-25 12:22:29 +00004546 // tt,
4547 // For taskloops:
4548 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
4549 // tt->task_data.shareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004550 llvm::Value *GtidParam = CGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00004551 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
Alexey Bataev31300ed2016-02-04 11:27:03 +00004552 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4553 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4554 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004555 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004556 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004557 LValue Base =
4558 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004559 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004560 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004561 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
4562 llvm::Value *PartidParam = PartIdLVal.getPointer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004563
4564 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004565 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
4566 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev1e491372018-01-23 18:44:14 +00004567 CGF.EmitLoadOfScalar(SharedsLVal, Loc),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004568 CGF.ConvertTypeForMem(SharedsPtrTy));
4569
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004570 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4571 llvm::Value *PrivatesParam;
4572 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004573 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004574 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00004575 PrivatesLVal.getPointer(), CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004576 } else {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004577 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004578 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004579
Alexey Bataev7292c292016-04-25 12:22:29 +00004580 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam,
4581 TaskPrivatesMap,
4582 CGF.Builder
4583 .CreatePointerBitCastOrAddrSpaceCast(
4584 TDBase.getAddress(), CGF.VoidPtrTy)
4585 .getPointer()};
4586 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs),
4587 std::end(CommonArgs));
4588 if (isOpenMPTaskLoopDirective(Kind)) {
4589 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004590 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI);
4591 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004592 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004593 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI);
4594 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004595 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004596 LValue StLVal = CGF.EmitLValueForField(Base, *StFI);
4597 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004598 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004599 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4600 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004601 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004602 LValue RLVal = CGF.EmitLValueForField(Base, *RFI);
4603 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004604 CallArgs.push_back(LBParam);
4605 CallArgs.push_back(UBParam);
4606 CallArgs.push_back(StParam);
4607 CallArgs.push_back(LIParam);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004608 CallArgs.push_back(RParam);
Alexey Bataev7292c292016-04-25 12:22:29 +00004609 }
4610 CallArgs.push_back(SharedsParam);
4611
Alexey Bataev3c595a62017-08-14 15:01:03 +00004612 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction,
4613 CallArgs);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004614 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)),
4615 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004616 CGF.FinishFunction();
4617 return TaskEntry;
4618}
4619
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004620static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
4621 SourceLocation Loc,
4622 QualType KmpInt32Ty,
4623 QualType KmpTaskTWithPrivatesPtrQTy,
4624 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004625 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004626 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004627 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4628 ImplicitParamDecl::Other);
4629 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4630 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4631 ImplicitParamDecl::Other);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004632 Args.push_back(&GtidArg);
4633 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004634 const auto &DestructorFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004635 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004636 llvm::FunctionType *DestructorFnTy =
4637 CGM.getTypes().GetFunctionType(DestructorFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004638 std::string Name =
4639 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""});
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004640 auto *DestructorFn =
4641 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00004642 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004643 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004644 DestructorFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004645 DestructorFn->setDoesNotRecurse();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004646 CodeGenFunction CGF(CGM);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004647 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004648 Args, Loc, Loc);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004649
Alexey Bataev31300ed2016-02-04 11:27:03 +00004650 LValue Base = CGF.EmitLoadOfPointerLValue(
4651 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4652 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004653 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004654 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
4655 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004656 Base = CGF.EmitLValueForField(Base, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004657 for (const auto *Field :
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004658 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004659 if (QualType::DestructionKind DtorKind =
4660 Field->getType().isDestructedType()) {
4661 LValue FieldLValue = CGF.EmitLValueForField(Base, Field);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004662 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
4663 }
4664 }
4665 CGF.FinishFunction();
4666 return DestructorFn;
4667}
4668
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004669/// Emit a privates mapping function for correct handling of private and
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004670/// firstprivate variables.
4671/// \code
4672/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
4673/// **noalias priv1,..., <tyn> **noalias privn) {
4674/// *priv1 = &.privates.priv1;
4675/// ...;
4676/// *privn = &.privates.privn;
4677/// }
4678/// \endcode
4679static llvm::Value *
4680emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Craig Topper8674c5c2015-09-29 04:30:07 +00004681 ArrayRef<const Expr *> PrivateVars,
4682 ArrayRef<const Expr *> FirstprivateVars,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004683 ArrayRef<const Expr *> LastprivateVars,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004684 QualType PrivatesQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004685 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004686 ASTContext &C = CGM.getContext();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004687 FunctionArgList Args;
4688 ImplicitParamDecl TaskPrivatesArg(
4689 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
Alexey Bataev56223232017-06-09 13:40:18 +00004690 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
4691 ImplicitParamDecl::Other);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004692 Args.push_back(&TaskPrivatesArg);
4693 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
4694 unsigned Counter = 1;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004695 for (const Expr *E : PrivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +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 Bataev3ae88e22015-05-22 08:56:35 +00004703 PrivateVarsPos[VD] = Counter;
4704 ++Counter;
4705 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004706 for (const Expr *E : FirstprivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004707 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004708 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4709 C.getPointerType(C.getPointerType(E->getType()))
4710 .withConst()
4711 .withRestrict(),
4712 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004713 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004714 PrivateVarsPos[VD] = Counter;
4715 ++Counter;
4716 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004717 for (const Expr *E : LastprivateVars) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004718 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004719 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4720 C.getPointerType(C.getPointerType(E->getType()))
4721 .withConst()
4722 .withRestrict(),
4723 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004724 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataevf93095a2016-05-05 08:46:22 +00004725 PrivateVarsPos[VD] = Counter;
4726 ++Counter;
4727 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004728 const auto &TaskPrivatesMapFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004729 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004730 llvm::FunctionType *TaskPrivatesMapTy =
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004731 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004732 std::string Name =
4733 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""});
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004734 auto *TaskPrivatesMap = llvm::Function::Create(
Alexey Bataev18fa2322018-05-02 14:20:50 +00004735 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
4736 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004737 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004738 TaskPrivatesMapFnInfo);
Alexey Bataev8c5555c2019-05-21 15:11:58 +00004739 if (CGM.getLangOpts().Optimize) {
4740 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
4741 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
4742 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
4743 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004744 CodeGenFunction CGF(CGM);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004745 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004746 TaskPrivatesMapFnInfo, Args, Loc, Loc);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004747
4748 // *privi = &.privates.privi;
Alexey Bataev31300ed2016-02-04 11:27:03 +00004749 LValue Base = CGF.EmitLoadOfPointerLValue(
4750 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
4751 TaskPrivatesArg.getType()->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004752 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004753 Counter = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004754 for (const FieldDecl *Field : PrivatesQTyRD->fields()) {
4755 LValue FieldLVal = CGF.EmitLValueForField(Base, Field);
4756 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
4757 LValue RefLVal =
4758 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
4759 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue(
Alexey Bataev31300ed2016-02-04 11:27:03 +00004760 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>());
Alexey Bataev2377fe92015-09-10 08:12:02 +00004761 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004762 ++Counter;
4763 }
4764 CGF.FinishFunction();
4765 return TaskPrivatesMap;
4766}
4767
Alexey Bataevf93095a2016-05-05 08:46:22 +00004768/// Emit initialization for private variables in task-based directives.
Alexey Bataev8a831592016-05-10 10:36:51 +00004769static void emitPrivatesInit(CodeGenFunction &CGF,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004770 const OMPExecutableDirective &D,
4771 Address KmpTaskSharedsPtr, LValue TDBase,
4772 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4773 QualType SharedsTy, QualType SharedsPtrTy,
4774 const OMPTaskDataTy &Data,
4775 ArrayRef<PrivateDataTy> Privates, bool ForDup) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004776 ASTContext &C = CGF.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004777 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
4778 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004779 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind())
4780 ? OMPD_taskloop
4781 : OMPD_task;
4782 const CapturedStmt &CS = *D.getCapturedStmt(Kind);
4783 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004784 LValue SrcBase;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004785 bool IsTargetTask =
4786 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) ||
4787 isOpenMPTargetExecutionDirective(D.getDirectiveKind());
4788 // For target-based directives skip 3 firstprivate arrays BasePointersArray,
4789 // PointersArray and SizesArray. The original variables for these arrays are
4790 // not captured and we get their addresses explicitly.
4791 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) ||
Alexey Bataev8451efa2018-01-15 19:06:12 +00004792 (IsTargetTask && KmpTaskSharedsPtr.isValid())) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004793 SrcBase = CGF.MakeAddrLValue(
4794 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4795 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
4796 SharedsTy);
4797 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004798 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004799 for (const PrivateDataTy &Pair : Privates) {
4800 const VarDecl *VD = Pair.second.PrivateCopy;
4801 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004802 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) &&
4803 !CGF.isTrivialInitializer(Init)))) {
Alexey Bataev8a831592016-05-10 10:36:51 +00004804 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004805 if (const VarDecl *Elem = Pair.second.PrivateElemInit) {
4806 const VarDecl *OriginalVD = Pair.second.Original;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004807 // Check if the variable is the target-based BasePointersArray,
4808 // PointersArray or SizesArray.
4809 LValue SharedRefLValue;
Alexey Bataevab41ea62019-03-13 20:46:28 +00004810 QualType Type = PrivateLValue.getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004811 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004812 if (IsTargetTask && !SharedField) {
4813 assert(isa<ImplicitParamDecl>(OriginalVD) &&
4814 isa<CapturedDecl>(OriginalVD->getDeclContext()) &&
4815 cast<CapturedDecl>(OriginalVD->getDeclContext())
4816 ->getNumParams() == 0 &&
4817 isa<TranslationUnitDecl>(
4818 cast<CapturedDecl>(OriginalVD->getDeclContext())
4819 ->getDeclContext()) &&
4820 "Expected artificial target data variable.");
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004821 SharedRefLValue =
4822 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type);
4823 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004824 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField);
4825 SharedRefLValue = CGF.MakeAddrLValue(
4826 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
4827 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl),
4828 SharedRefLValue.getTBAAInfo());
4829 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004830 if (Type->isArrayType()) {
4831 // Initialize firstprivate array.
4832 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) {
4833 // Perform simple memcpy.
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00004834 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004835 } else {
4836 // Initialize firstprivate array using element-by-element
Simon Pilgrim2c518802017-03-30 14:13:19 +00004837 // initialization.
Alexey Bataevf93095a2016-05-05 08:46:22 +00004838 CGF.EmitOMPAggregateAssign(
4839 PrivateLValue.getAddress(), SharedRefLValue.getAddress(), Type,
4840 [&CGF, Elem, Init, &CapturesInfo](Address DestElement,
4841 Address SrcElement) {
4842 // Clean up any temporaries needed by the initialization.
4843 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4844 InitScope.addPrivate(
4845 Elem, [SrcElement]() -> Address { return SrcElement; });
4846 (void)InitScope.Privatize();
4847 // Emit initialization for single element.
4848 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
4849 CGF, &CapturesInfo);
4850 CGF.EmitAnyExprToMem(Init, DestElement,
4851 Init->getType().getQualifiers(),
4852 /*IsInitializer=*/false);
4853 });
4854 }
4855 } else {
4856 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4857 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
4858 return SharedRefLValue.getAddress();
4859 });
4860 (void)InitScope.Privatize();
4861 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
4862 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
4863 /*capturedByInit=*/false);
4864 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004865 } else {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004866 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004867 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004868 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004869 ++FI;
4870 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004871}
4872
4873/// Check if duplication function is required for taskloops.
4874static bool checkInitIsRequired(CodeGenFunction &CGF,
4875 ArrayRef<PrivateDataTy> Privates) {
4876 bool InitRequired = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004877 for (const PrivateDataTy &Pair : Privates) {
4878 const VarDecl *VD = Pair.second.PrivateCopy;
4879 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004880 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) &&
4881 !CGF.isTrivialInitializer(Init));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004882 if (InitRequired)
4883 break;
Alexey Bataevf93095a2016-05-05 08:46:22 +00004884 }
4885 return InitRequired;
4886}
4887
4888
4889/// Emit task_dup function (for initialization of
4890/// private/firstprivate/lastprivate vars and last_iter flag)
4891/// \code
4892/// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int
4893/// lastpriv) {
4894/// // setup lastprivate flag
4895/// task_dst->last = lastpriv;
4896/// // could be constructor calls here...
4897/// }
4898/// \endcode
4899static llvm::Value *
4900emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
4901 const OMPExecutableDirective &D,
4902 QualType KmpTaskTWithPrivatesPtrQTy,
4903 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4904 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy,
4905 QualType SharedsPtrTy, const OMPTaskDataTy &Data,
4906 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004907 ASTContext &C = CGM.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004908 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004909 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4910 KmpTaskTWithPrivatesPtrQTy,
4911 ImplicitParamDecl::Other);
4912 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4913 KmpTaskTWithPrivatesPtrQTy,
4914 ImplicitParamDecl::Other);
4915 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy,
4916 ImplicitParamDecl::Other);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004917 Args.push_back(&DstArg);
4918 Args.push_back(&SrcArg);
4919 Args.push_back(&LastprivArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004920 const auto &TaskDupFnInfo =
Alexey Bataevf93095a2016-05-05 08:46:22 +00004921 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004922 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004923 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""});
4924 auto *TaskDup = llvm::Function::Create(
4925 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004926 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004927 TaskDup->setDoesNotRecurse();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004928 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004929 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc,
4930 Loc);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004931
4932 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4933 CGF.GetAddrOfLocalVar(&DstArg),
4934 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4935 // task_dst->liter = lastpriv;
4936 if (WithLastIter) {
4937 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
4938 LValue Base = CGF.EmitLValueForField(
4939 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4940 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4941 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar(
4942 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc);
4943 CGF.EmitStoreOfScalar(Lastpriv, LILVal);
4944 }
4945
4946 // Emit initial values for private copies (if any).
4947 assert(!Privates.empty());
4948 Address KmpTaskSharedsPtr = Address::invalid();
4949 if (!Data.FirstprivateVars.empty()) {
4950 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4951 CGF.GetAddrOfLocalVar(&SrcArg),
4952 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4953 LValue Base = CGF.EmitLValueForField(
4954 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4955 KmpTaskSharedsPtr = Address(
4956 CGF.EmitLoadOfScalar(CGF.EmitLValueForField(
4957 Base, *std::next(KmpTaskTQTyRD->field_begin(),
4958 KmpTaskTShareds)),
4959 Loc),
4960 CGF.getNaturalTypeAlignment(SharedsTy));
4961 }
Alexey Bataev8a831592016-05-10 10:36:51 +00004962 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
4963 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004964 CGF.FinishFunction();
4965 return TaskDup;
4966}
4967
Alexey Bataev8a831592016-05-10 10:36:51 +00004968/// Checks if destructor function is required to be generated.
4969/// \return true if cleanups are required, false otherwise.
4970static bool
4971checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) {
4972 bool NeedsCleanup = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004973 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4974 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl());
4975 for (const FieldDecl *FD : PrivateRD->fields()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00004976 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType();
4977 if (NeedsCleanup)
4978 break;
4979 }
4980 return NeedsCleanup;
4981}
4982
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004983CGOpenMPRuntime::TaskResultTy
4984CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
4985 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00004986 llvm::Function *TaskFunction, QualType SharedsTy,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004987 Address Shareds, const OMPTaskDataTy &Data) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004988 ASTContext &C = CGM.getContext();
Alexey Bataev7292c292016-04-25 12:22:29 +00004989 llvm::SmallVector<PrivateDataTy, 4> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004990 // Aggregate privates and sort them by the alignment.
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004991 auto I = Data.PrivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004992 for (const Expr *E : Data.PrivateVars) {
4993 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00004994 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00004995 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00004996 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00004997 /*PrivateElemInit=*/nullptr));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004998 ++I;
4999 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005000 I = Data.FirstprivateCopies.begin();
5001 auto IElemInitRef = Data.FirstprivateInits.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005002 for (const Expr *E : Data.FirstprivateVars) {
5003 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00005004 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00005005 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00005006 PrivateHelpersTy(
5007 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00005008 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())));
Richard Trieucc3949d2016-02-18 22:34:54 +00005009 ++I;
5010 ++IElemInitRef;
Alexey Bataev9e034042015-05-05 04:05:12 +00005011 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00005012 I = Data.LastprivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005013 for (const Expr *E : Data.LastprivateVars) {
5014 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00005015 Privates.emplace_back(
Alexey Bataevf93095a2016-05-05 08:46:22 +00005016 C.getDeclAlign(VD),
5017 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00005018 /*PrivateElemInit=*/nullptr));
Alexey Bataevf93095a2016-05-05 08:46:22 +00005019 ++I;
5020 }
Fangrui Song899d1392019-04-24 14:43:05 +00005021 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) {
5022 return L.first > R.first;
5023 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005024 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005025 // Build type kmp_routine_entry_t (if not built yet).
5026 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005027 // Build type kmp_task_t (if not built yet).
Alexey Bataeve213f3e2017-10-11 15:29:40 +00005028 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) {
5029 if (SavedKmpTaskloopTQTy.isNull()) {
5030 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5031 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5032 }
5033 KmpTaskTQTy = SavedKmpTaskloopTQTy;
Alexey Bataev3a03a7f2017-10-11 15:56:38 +00005034 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00005035 assert((D.getDirectiveKind() == OMPD_task ||
5036 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) ||
5037 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) &&
5038 "Expected taskloop, task or target directive");
Alexey Bataeve213f3e2017-10-11 15:29:40 +00005039 if (SavedKmpTaskTQTy.isNull()) {
5040 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5041 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5042 }
5043 KmpTaskTQTy = SavedKmpTaskTQTy;
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005044 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005045 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005046 // Build particular struct kmp_task_t for the given task.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005047 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005048 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005049 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005050 QualType KmpTaskTWithPrivatesPtrQTy =
5051 C.getPointerType(KmpTaskTWithPrivatesQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005052 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
5053 llvm::Type *KmpTaskTWithPrivatesPtrTy =
5054 KmpTaskTWithPrivatesTy->getPointerTo();
5055 llvm::Value *KmpTaskTWithPrivatesTySize =
5056 CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005057 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
5058
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005059 // Emit initial values for private copies (if any).
5060 llvm::Value *TaskPrivatesMap = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005061 llvm::Type *TaskPrivatesMapTy =
James Y Knight9871db02019-02-05 16:42:33 +00005062 std::next(TaskFunction->arg_begin(), 3)->getType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005063 if (!Privates.empty()) {
5064 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataevf93095a2016-05-05 08:46:22 +00005065 TaskPrivatesMap = emitTaskPrivateMappingFunction(
5066 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars,
5067 FI->getType(), Privates);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005068 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5069 TaskPrivatesMap, TaskPrivatesMapTy);
5070 } else {
5071 TaskPrivatesMap = llvm::ConstantPointerNull::get(
5072 cast<llvm::PointerType>(TaskPrivatesMapTy));
5073 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005074 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
5075 // kmp_task_t *tt);
James Y Knight9871db02019-02-05 16:42:33 +00005076 llvm::Function *TaskEntry = emitProxyTaskFunction(
Alexey Bataev7292c292016-04-25 12:22:29 +00005077 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5078 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction,
5079 TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005080
5081 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
5082 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
5083 // kmp_routine_entry_t *task_entry);
5084 // Task flags. Format is taken from
James Y Knight5d71fc52019-01-29 16:37:27 +00005085 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h,
Alexey Bataev62b63b12015-03-10 07:28:44 +00005086 // description of kmp_tasking_flags struct.
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005087 enum {
5088 TiedFlag = 0x1,
5089 FinalFlag = 0x2,
5090 DestructorsFlag = 0x8,
5091 PriorityFlag = 0x20
5092 };
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005093 unsigned Flags = Data.Tied ? TiedFlag : 0;
Alexey Bataev8a831592016-05-10 10:36:51 +00005094 bool NeedsCleanup = false;
5095 if (!Privates.empty()) {
5096 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD);
5097 if (NeedsCleanup)
5098 Flags = Flags | DestructorsFlag;
5099 }
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005100 if (Data.Priority.getInt())
5101 Flags = Flags | PriorityFlag;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005102 llvm::Value *TaskFlags =
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005103 Data.Final.getPointer()
5104 ? CGF.Builder.CreateSelect(Data.Final.getPointer(),
Alexey Bataev62b63b12015-03-10 07:28:44 +00005105 CGF.Builder.getInt32(FinalFlag),
5106 CGF.Builder.getInt32(/*C=*/0))
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005107 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005108 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005109 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00005110 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc),
5111 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
5112 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5113 TaskEntry, KmpRoutineEntryPtrTy)};
5114 llvm::Value *NewTask;
5115 if (D.hasClausesOfKind<OMPNowaitClause>()) {
5116 // Check if we have any device clause associated with the directive.
5117 const Expr *Device = nullptr;
5118 if (auto *C = D.getSingleClause<OMPDeviceClause>())
5119 Device = C->getDevice();
5120 // Emit device ID if any otherwise use default value.
5121 llvm::Value *DeviceID;
5122 if (Device)
5123 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
5124 CGF.Int64Ty, /*isSigned=*/true);
5125 else
5126 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
5127 AllocArgs.push_back(DeviceID);
5128 NewTask = CGF.EmitRuntimeCall(
5129 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs);
5130 } else {
5131 NewTask = CGF.EmitRuntimeCall(
Alexey Bataev62b63b12015-03-10 07:28:44 +00005132 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00005133 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005134 llvm::Value *NewTaskNewTaskTTy =
5135 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5136 NewTask, KmpTaskTWithPrivatesPtrTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005137 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
5138 KmpTaskTWithPrivatesQTy);
5139 LValue TDBase =
5140 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005141 // Fill the data in the resulting kmp_task_t record.
5142 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00005143 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005144 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00005145 KmpTaskSharedsPtr =
5146 Address(CGF.EmitLoadOfScalar(
5147 CGF.EmitLValueForField(
5148 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
5149 KmpTaskTShareds)),
5150 Loc),
5151 CGF.getNaturalTypeAlignment(SharedsTy));
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00005152 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy);
5153 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy);
Richard Smithe78fac52018-04-05 20:52:58 +00005154 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005155 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005156 // Emit initial values for private copies (if any).
Alexey Bataevf93095a2016-05-05 08:46:22 +00005157 TaskResultTy Result;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005158 if (!Privates.empty()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00005159 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD,
5160 SharedsTy, SharedsPtrTy, Data, Privates,
5161 /*ForDup=*/false);
Alexey Bataevf93095a2016-05-05 08:46:22 +00005162 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
5163 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) {
5164 Result.TaskDupFn = emitTaskDupFunction(
5165 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
5166 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates,
5167 /*WithLastIter=*/!Data.LastprivateVars.empty());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005168 }
5169 }
Alexey Bataevad537bb2016-05-30 09:06:50 +00005170 // Fields of union "kmp_cmplrdata_t" for destructors and priority.
5171 enum { Priority = 0, Destructors = 1 };
Alexey Bataev62b63b12015-03-10 07:28:44 +00005172 // Provide pointer to function with destructors for privates.
Alexey Bataevad537bb2016-05-30 09:06:50 +00005173 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005174 const RecordDecl *KmpCmplrdataUD =
5175 (*FI)->getType()->getAsUnionType()->getDecl();
Alexey Bataevad537bb2016-05-30 09:06:50 +00005176 if (NeedsCleanup) {
5177 llvm::Value *DestructorFn = emitDestructorsFunction(
5178 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5179 KmpTaskTWithPrivatesQTy);
5180 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI);
5181 LValue DestructorsLV = CGF.EmitLValueForField(
5182 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
5183 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5184 DestructorFn, KmpRoutineEntryPtrTy),
5185 DestructorsLV);
5186 }
5187 // Set priority.
5188 if (Data.Priority.getInt()) {
5189 LValue Data2LV = CGF.EmitLValueForField(
5190 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
5191 LValue PriorityLV = CGF.EmitLValueForField(
5192 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
5193 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV);
5194 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005195 Result.NewTask = NewTask;
5196 Result.TaskEntry = TaskEntry;
5197 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
5198 Result.TDBase = TDBase;
5199 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
5200 return Result;
Alexey Bataev7292c292016-04-25 12:22:29 +00005201}
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005202
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005203void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
5204 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005205 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005206 QualType SharedsTy, Address Shareds,
5207 const Expr *IfCond,
5208 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005209 if (!CGF.HaveInsertPoint())
5210 return;
5211
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005212 TaskResultTy Result =
5213 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
5214 llvm::Value *NewTask = Result.NewTask;
James Y Knight9871db02019-02-05 16:42:33 +00005215 llvm::Function *TaskEntry = Result.TaskEntry;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005216 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy;
5217 LValue TDBase = Result.TDBase;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005218 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD;
5219 ASTContext &C = CGM.getContext();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005220 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00005221 Address DependenciesArray = Address::invalid();
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005222 unsigned NumDependencies = Data.Dependences.size();
John McCall7f416cc2015-09-08 08:05:57 +00005223 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005224 // Dependence kind for RTL.
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005225 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 };
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005226 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
5227 RecordDecl *KmpDependInfoRD;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005228 QualType FlagsTy =
5229 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005230 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
5231 if (KmpDependInfoTy.isNull()) {
5232 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
5233 KmpDependInfoRD->startDefinition();
5234 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
5235 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
5236 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
5237 KmpDependInfoRD->completeDefinition();
5238 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005239 } else {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005240 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005241 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005242 // Define type kmp_depend_info[<Dependences.size()>];
5243 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00005244 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005245 ArrayType::Normal, /*IndexTypeQuals=*/0);
5246 // kmp_depend_info[<Dependences.size()>] deps;
Alexey Bataev48591dd2016-04-20 04:01:36 +00005247 DependenciesArray =
5248 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005249 for (unsigned I = 0; I < NumDependencies; ++I) {
5250 const Expr *E = Data.Dependences[I].second;
5251 LValue Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005252 llvm::Value *Size;
5253 QualType Ty = E->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005254 if (const auto *ASE =
5255 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005256 LValue UpAddrLVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005257 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005258 llvm::Value *UpAddr =
John McCall7f416cc2015-09-08 08:05:57 +00005259 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005260 llvm::Value *LowIntPtr =
John McCall7f416cc2015-09-08 08:05:57 +00005261 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005262 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
5263 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005264 } else {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005265 Size = CGF.getTypeSize(Ty);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005266 }
5267 LValue Base = CGF.MakeAddrLValue(
James Y Knight751fe282019-02-09 22:22:28 +00005268 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005269 KmpDependInfoTy);
5270 // deps[i].base_addr = &<Dependences[i].second>;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005271 LValue BaseAddrLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005272 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00005273 CGF.EmitStoreOfScalar(
5274 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy),
5275 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005276 // deps[i].len = sizeof(<Dependences[i].second>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005277 LValue LenLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005278 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
5279 CGF.EmitStoreOfScalar(Size, LenLVal);
5280 // deps[i].flags = <Dependences[i].first>;
5281 RTLDependenceKindTy DepKind;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005282 switch (Data.Dependences[I].first) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005283 case OMPC_DEPEND_in:
5284 DepKind = DepIn;
5285 break;
Alexey Bataev92e82f92015-11-23 13:33:42 +00005286 // Out and InOut dependencies must use the same code.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005287 case OMPC_DEPEND_out:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005288 case OMPC_DEPEND_inout:
5289 DepKind = DepInOut;
5290 break;
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005291 case OMPC_DEPEND_mutexinoutset:
5292 DepKind = DepMutexInOutSet;
5293 break;
Alexey Bataeveb482352015-12-18 05:05:56 +00005294 case OMPC_DEPEND_source:
Alexey Bataeva636c7f2015-12-23 10:27:45 +00005295 case OMPC_DEPEND_sink:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005296 case OMPC_DEPEND_unknown:
5297 llvm_unreachable("Unknown task dependence type");
5298 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005299 LValue FlagsLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005300 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
5301 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
5302 FlagsLVal);
5303 }
John McCall7f416cc2015-09-08 08:05:57 +00005304 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knightf5f1b0e2019-02-08 15:34:12 +00005305 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005306 }
5307
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005308 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev62b63b12015-03-10 07:28:44 +00005309 // libcall.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005310 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
5311 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
5312 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
5313 // list is not empty
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005314 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5315 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00005316 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
5317 llvm::Value *DepTaskArgs[7];
5318 if (NumDependencies) {
5319 DepTaskArgs[0] = UpLoc;
5320 DepTaskArgs[1] = ThreadID;
5321 DepTaskArgs[2] = NewTask;
5322 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
5323 DepTaskArgs[4] = DependenciesArray.getPointer();
5324 DepTaskArgs[5] = CGF.Builder.getInt32(0);
5325 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5326 }
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005327 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies,
5328 &TaskArgs,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005329 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005330 if (!Data.Tied) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005331 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005332 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
Alexey Bataev48591dd2016-04-20 04:01:36 +00005333 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
5334 }
John McCall7f416cc2015-09-08 08:05:57 +00005335 if (NumDependencies) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005336 CGF.EmitRuntimeCall(
Alexey Bataev48591dd2016-04-20 04:01:36 +00005337 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs);
John McCall7f416cc2015-09-08 08:05:57 +00005338 } else {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005339 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
John McCall7f416cc2015-09-08 08:05:57 +00005340 TaskArgs);
5341 }
Alexey Bataev48591dd2016-04-20 04:01:36 +00005342 // Check if parent region is untied and build return for untied task;
5343 if (auto *Region =
5344 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
5345 Region->emitUntiedSwitch(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00005346 };
John McCall7f416cc2015-09-08 08:05:57 +00005347
5348 llvm::Value *DepWaitTaskArgs[6];
5349 if (NumDependencies) {
5350 DepWaitTaskArgs[0] = UpLoc;
5351 DepWaitTaskArgs[1] = ThreadID;
5352 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
5353 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
5354 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
5355 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5356 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005357 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
Alexey Bataev3c595a62017-08-14 15:01:03 +00005358 NumDependencies, &DepWaitTaskArgs,
5359 Loc](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005360 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005361 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
5362 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
5363 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
5364 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
5365 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00005366 if (NumDependencies)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005367 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005368 DepWaitTaskArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005369 // Call proxy_task_entry(gtid, new_task);
Alexey Bataev3c595a62017-08-14 15:01:03 +00005370 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
5371 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005372 Action.Enter(CGF);
5373 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
Alexey Bataev3c595a62017-08-14 15:01:03 +00005374 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
Alexey Bataev2c7eee52017-08-04 19:10:54 +00005375 OutlinedFnArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005376 };
5377
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005378 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
5379 // kmp_task_t *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005380 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
5381 // kmp_task_t *new_task);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005382 RegionCodeGenTy RCG(CodeGen);
5383 CommonActionTy Action(
5384 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs,
5385 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs);
5386 RCG.setAction(Action);
5387 RCG(CGF);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005388 };
John McCall7f416cc2015-09-08 08:05:57 +00005389
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005390 if (IfCond) {
Alexey Bataev1d677132015-04-22 13:57:31 +00005391 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005392 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005393 RegionCodeGenTy ThenRCG(ThenCodeGen);
5394 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00005395 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005396}
5397
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005398void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
5399 const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005400 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005401 QualType SharedsTy, Address Shareds,
5402 const Expr *IfCond,
5403 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005404 if (!CGF.HaveInsertPoint())
5405 return;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005406 TaskResultTy Result =
5407 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005408 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev7292c292016-04-25 12:22:29 +00005409 // libcall.
5410 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
5411 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
5412 // sched, kmp_uint64 grainsize, void *task_dup);
5413 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5414 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
5415 llvm::Value *IfVal;
5416 if (IfCond) {
5417 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy,
5418 /*isSigned=*/true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005419 } else {
Alexey Bataev7292c292016-04-25 12:22:29 +00005420 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005421 }
Alexey Bataev7292c292016-04-25 12:22:29 +00005422
5423 LValue LBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005424 Result.TDBase,
5425 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005426 const auto *LBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005427 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl());
5428 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(),
5429 /*IsInitializer=*/true);
5430 LValue UBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005431 Result.TDBase,
5432 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005433 const auto *UBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005434 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl());
5435 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(),
5436 /*IsInitializer=*/true);
5437 LValue StLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005438 Result.TDBase,
5439 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005440 const auto *StVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005441 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl());
5442 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(),
5443 /*IsInitializer=*/true);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005444 // Store reductions address.
5445 LValue RedLVal = CGF.EmitLValueForField(
5446 Result.TDBase,
5447 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005448 if (Data.Reductions) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005449 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005450 } else {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005451 CGF.EmitNullInitialization(RedLVal.getAddress(),
5452 CGF.getContext().VoidPtrTy);
5453 }
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005454 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
Alexey Bataev7292c292016-04-25 12:22:29 +00005455 llvm::Value *TaskArgs[] = {
Alexey Bataev33446032017-07-12 18:09:32 +00005456 UpLoc,
5457 ThreadID,
5458 Result.NewTask,
5459 IfVal,
5460 LBLVal.getPointer(),
5461 UBLVal.getPointer(),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00005462 CGF.EmitLoadOfScalar(StLVal, Loc),
Alexey Bataevac6e4de2018-10-24 19:06:37 +00005463 llvm::ConstantInt::getSigned(
5464 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005465 llvm::ConstantInt::getSigned(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005466 CGF.IntTy, Data.Schedule.getPointer()
5467 ? Data.Schedule.getInt() ? NumTasks : Grainsize
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005468 : NoSchedule),
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005469 Data.Schedule.getPointer()
5470 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty,
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005471 /*isSigned=*/false)
5472 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0),
Alexey Bataev33446032017-07-12 18:09:32 +00005473 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5474 Result.TaskDupFn, CGF.VoidPtrTy)
5475 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)};
Alexey Bataev7292c292016-04-25 12:22:29 +00005476 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs);
5477}
5478
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005479/// Emit reduction operation for each element of array (required for
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005480/// array sections) LHS op = RHS.
5481/// \param Type Type of array.
5482/// \param LHSVar Variable on the left side of the reduction operation
5483/// (references element of array in original variable).
5484/// \param RHSVar Variable on the right side of the reduction operation
5485/// (references element of array in original variable).
5486/// \param RedOpGen Generator of reduction operation with use of LHSVar and
5487/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00005488static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005489 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
5490 const VarDecl *RHSVar,
5491 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
5492 const Expr *, const Expr *)> &RedOpGen,
5493 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
5494 const Expr *UpExpr = nullptr) {
5495 // Perform element-by-element initialization.
5496 QualType ElementTy;
5497 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
5498 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
5499
5500 // Drill down to the base element type on both arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005501 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
5502 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005503
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005504 llvm::Value *RHSBegin = RHSAddr.getPointer();
5505 llvm::Value *LHSBegin = LHSAddr.getPointer();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005506 // Cast from pointer to array type to pointer to single element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005507 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005508 // The basic structure here is a while-do loop.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005509 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
5510 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
5511 llvm::Value *IsEmpty =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005512 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
5513 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
5514
5515 // Enter the loop body, making that address the current address.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005516 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005517 CGF.EmitBlock(BodyBB);
5518
5519 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
5520
5521 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
5522 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
5523 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
5524 Address RHSElementCurrent =
5525 Address(RHSElementPHI,
5526 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5527
5528 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
5529 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
5530 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
5531 Address LHSElementCurrent =
5532 Address(LHSElementPHI,
5533 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5534
5535 // Emit copy.
5536 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005537 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; });
5538 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005539 Scope.Privatize();
5540 RedOpGen(CGF, XExpr, EExpr, UpExpr);
5541 Scope.ForceCleanup();
5542
5543 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005544 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005545 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005546 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005547 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
5548 // Check whether we've reached the end.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005549 llvm::Value *Done =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005550 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
5551 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
5552 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
5553 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
5554
5555 // Done.
5556 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
5557}
5558
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005559/// Emit reduction combiner. If the combiner is a simple expression emit it as
5560/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
5561/// UDR combiner function.
5562static void emitReductionCombiner(CodeGenFunction &CGF,
5563 const Expr *ReductionOp) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005564 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
5565 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
5566 if (const auto *DRE =
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005567 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005568 if (const auto *DRD =
5569 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005570 std::pair<llvm::Function *, llvm::Function *> Reduction =
5571 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
5572 RValue Func = RValue::get(Reduction.first);
5573 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
5574 CGF.EmitIgnoredExpr(ReductionOp);
5575 return;
5576 }
5577 CGF.EmitIgnoredExpr(ReductionOp);
5578}
5579
James Y Knight9871db02019-02-05 16:42:33 +00005580llvm::Function *CGOpenMPRuntime::emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005581 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates,
5582 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
5583 ArrayRef<const Expr *> ReductionOps) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005584 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005585
5586 // void reduction_func(void *LHSArg, void *RHSArg);
5587 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005588 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5589 ImplicitParamDecl::Other);
5590 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5591 ImplicitParamDecl::Other);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005592 Args.push_back(&LHSArg);
5593 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005594 const auto &CGFI =
5595 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00005596 std::string Name = getName({"omp", "reduction", "reduction_func"});
5597 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
5598 llvm::GlobalValue::InternalLinkage, Name,
5599 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00005600 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00005601 Fn->setDoesNotRecurse();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005602 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005603 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005604
5605 // Dst = (void*[n])(LHSArg);
5606 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00005607 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5608 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
5609 ArgsType), CGF.getPointerAlign());
5610 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5611 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
5612 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005613
5614 // ...
5615 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
5616 // ...
5617 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005618 auto IPriv = Privates.begin();
5619 unsigned Idx = 0;
5620 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005621 const auto *RHSVar =
5622 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
5623 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005624 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005625 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005626 const auto *LHSVar =
5627 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
5628 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005629 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005630 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005631 QualType PrivTy = (*IPriv)->getType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00005632 if (PrivTy->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005633 // Get array size and emit VLA type.
5634 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005635 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005636 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005637 const VariableArrayType *VLA =
5638 CGF.getContext().getAsVariableArrayType(PrivTy);
5639 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005640 CodeGenFunction::OpaqueValueMapping OpaqueMap(
Alexey Bataev1189bd02016-01-26 12:20:39 +00005641 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005642 CGF.EmitVariablyModifiedType(PrivTy);
5643 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005644 }
5645 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005646 IPriv = Privates.begin();
5647 auto ILHS = LHSExprs.begin();
5648 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005649 for (const Expr *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005650 if ((*IPriv)->getType()->isArrayType()) {
5651 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005652 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5653 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005654 EmitOMPAggregateReduction(
5655 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5656 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5657 emitReductionCombiner(CGF, E);
5658 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005659 } else {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005660 // Emit reduction for array subscript or single variable.
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005661 emitReductionCombiner(CGF, E);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005662 }
Richard Trieucc3949d2016-02-18 22:34:54 +00005663 ++IPriv;
5664 ++ILHS;
5665 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005666 }
5667 Scope.ForceCleanup();
5668 CGF.FinishFunction();
5669 return Fn;
5670}
5671
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005672void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF,
5673 const Expr *ReductionOp,
5674 const Expr *PrivateRef,
5675 const DeclRefExpr *LHS,
5676 const DeclRefExpr *RHS) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005677 if (PrivateRef->getType()->isArrayType()) {
5678 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005679 const auto *LHSVar = cast<VarDecl>(LHS->getDecl());
5680 const auto *RHSVar = cast<VarDecl>(RHS->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005681 EmitOMPAggregateReduction(
5682 CGF, PrivateRef->getType(), LHSVar, RHSVar,
5683 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5684 emitReductionCombiner(CGF, ReductionOp);
5685 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005686 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005687 // Emit reduction for array subscript or single variable.
5688 emitReductionCombiner(CGF, ReductionOp);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005689 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005690}
5691
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005692void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005693 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005694 ArrayRef<const Expr *> LHSExprs,
5695 ArrayRef<const Expr *> RHSExprs,
5696 ArrayRef<const Expr *> ReductionOps,
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005697 ReductionOptionsTy Options) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00005698 if (!CGF.HaveInsertPoint())
5699 return;
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005700
5701 bool WithNowait = Options.WithNowait;
5702 bool SimpleReduction = Options.SimpleReduction;
5703
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005704 // Next code should be emitted for reduction:
5705 //
5706 // static kmp_critical_name lock = { 0 };
5707 //
5708 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
5709 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
5710 // ...
5711 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
5712 // *(Type<n>-1*)rhs[<n>-1]);
5713 // }
5714 //
5715 // ...
5716 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
5717 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5718 // RedList, reduce_func, &<lock>)) {
5719 // case 1:
5720 // ...
5721 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5722 // ...
5723 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5724 // break;
5725 // case 2:
5726 // ...
5727 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5728 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00005729 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005730 // break;
5731 // default:;
5732 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005733 //
5734 // if SimpleReduction is true, only the next code is generated:
5735 // ...
5736 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5737 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005738
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005739 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005740
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005741 if (SimpleReduction) {
5742 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005743 auto IPriv = Privates.begin();
5744 auto ILHS = LHSExprs.begin();
5745 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005746 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005747 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5748 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005749 ++IPriv;
5750 ++ILHS;
5751 ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005752 }
5753 return;
5754 }
5755
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005756 // 1. Build a list of reduction variables.
5757 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005758 auto Size = RHSExprs.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005759 for (const Expr *E : Privates) {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005760 if (E->getType()->isVariablyModifiedType())
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005761 // Reserve place for array size.
5762 ++Size;
5763 }
5764 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005765 QualType ReductionArrayTy =
5766 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
5767 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00005768 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005769 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005770 auto IPriv = Privates.begin();
5771 unsigned Idx = 0;
5772 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
James Y Knight751fe282019-02-09 22:22:28 +00005773 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
John McCall7f416cc2015-09-08 08:05:57 +00005774 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005775 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00005776 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
5777 Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005778 if ((*IPriv)->getType()->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005779 // Store array size.
5780 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005781 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005782 llvm::Value *Size = CGF.Builder.CreateIntCast(
5783 CGF.getVLASize(
5784 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
Sander de Smalen891af03a2018-02-03 13:55:59 +00005785 .NumElts,
Alexey Bataev1189bd02016-01-26 12:20:39 +00005786 CGF.SizeTy, /*isSigned=*/false);
5787 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
5788 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005789 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005790 }
5791
5792 // 2. Emit reduce_func().
James Y Knight9871db02019-02-05 16:42:33 +00005793 llvm::Function *ReductionFn = emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005794 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
5795 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005796
5797 // 3. Create static kmp_critical_name lock = { 0 };
Alexey Bataev18fa2322018-05-02 14:20:50 +00005798 std::string Name = getName({"reduction"});
5799 llvm::Value *Lock = getCriticalRegionLock(Name);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005800
5801 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5802 // RedList, reduce_func, &<lock>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005803 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
5804 llvm::Value *ThreadId = getThreadID(CGF, Loc);
5805 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
5806 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Samuel Antao4c8035b2016-12-12 18:00:20 +00005807 ReductionList.getPointer(), CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005808 llvm::Value *Args[] = {
5809 IdentTLoc, // ident_t *<loc>
5810 ThreadId, // i32 <gtid>
5811 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
5812 ReductionArrayTySize, // size_type sizeof(RedList)
5813 RL, // void *RedList
5814 ReductionFn, // void (*) (void *, void *) <reduce_func>
5815 Lock // kmp_critical_name *&<lock>
5816 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005817 llvm::Value *Res = CGF.EmitRuntimeCall(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005818 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
5819 : OMPRTL__kmpc_reduce),
5820 Args);
5821
5822 // 5. Build switch(res)
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005823 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
5824 llvm::SwitchInst *SwInst =
5825 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005826
5827 // 6. Build case 1:
5828 // ...
5829 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5830 // ...
5831 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5832 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005833 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005834 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
5835 CGF.EmitBlock(Case1BB);
5836
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005837 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5838 llvm::Value *EndArgs[] = {
5839 IdentTLoc, // ident_t *<loc>
5840 ThreadId, // i32 <gtid>
5841 Lock // kmp_critical_name *&<lock>
5842 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005843 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5844 CodeGenFunction &CGF, PrePostActionTy &Action) {
5845 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005846 auto IPriv = Privates.begin();
5847 auto ILHS = LHSExprs.begin();
5848 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005849 for (const Expr *E : ReductionOps) {
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005850 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5851 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005852 ++IPriv;
5853 ++ILHS;
5854 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005855 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005856 };
5857 RegionCodeGenTy RCG(CodeGen);
5858 CommonActionTy Action(
5859 nullptr, llvm::None,
5860 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
5861 : OMPRTL__kmpc_end_reduce),
5862 EndArgs);
5863 RCG.setAction(Action);
5864 RCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005865
5866 CGF.EmitBranch(DefaultBB);
5867
5868 // 7. Build case 2:
5869 // ...
5870 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5871 // ...
5872 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005873 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005874 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
5875 CGF.EmitBlock(Case2BB);
5876
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005877 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
5878 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005879 auto ILHS = LHSExprs.begin();
5880 auto IRHS = RHSExprs.begin();
5881 auto IPriv = Privates.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005882 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005883 const Expr *XExpr = nullptr;
5884 const Expr *EExpr = nullptr;
5885 const Expr *UpExpr = nullptr;
5886 BinaryOperatorKind BO = BO_Comma;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005887 if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005888 if (BO->getOpcode() == BO_Assign) {
5889 XExpr = BO->getLHS();
5890 UpExpr = BO->getRHS();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005891 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005892 }
5893 // Try to emit update expression as a simple atomic.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005894 const Expr *RHSExpr = UpExpr;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005895 if (RHSExpr) {
5896 // Analyze RHS part of the whole expression.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005897 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005898 RHSExpr->IgnoreParenImpCasts())) {
5899 // If this is a conditional operator, analyze its condition for
5900 // min/max reduction operator.
5901 RHSExpr = ACO->getCond();
Alexey Bataev69a47792015-05-07 03:54:03 +00005902 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005903 if (const auto *BORHS =
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005904 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
5905 EExpr = BORHS->getRHS();
5906 BO = BORHS->getOpcode();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005907 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005908 }
5909 if (XExpr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005910 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005911 auto &&AtomicRedGen = [BO, VD,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005912 Loc](CodeGenFunction &CGF, const Expr *XExpr,
5913 const Expr *EExpr, const Expr *UpExpr) {
5914 LValue X = CGF.EmitLValue(XExpr);
5915 RValue E;
5916 if (EExpr)
5917 E = CGF.EmitAnyExpr(EExpr);
5918 CGF.EmitOMPAtomicSimpleUpdateExpr(
JF Bastien92f4ef12016-04-06 17:26:42 +00005919 X, E, BO, /*IsXLHSInRHSPart=*/true,
5920 llvm::AtomicOrdering::Monotonic, Loc,
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005921 [&CGF, UpExpr, VD, Loc](RValue XRValue) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005922 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5923 PrivateScope.addPrivate(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005924 VD, [&CGF, VD, XRValue, Loc]() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005925 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5926 CGF.emitOMPSimpleStore(
5927 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
5928 VD->getType().getNonReferenceType(), Loc);
5929 return LHSTemp;
5930 });
5931 (void)PrivateScope.Privatize();
5932 return CGF.EmitAnyExpr(UpExpr);
5933 });
5934 };
5935 if ((*IPriv)->getType()->isArrayType()) {
5936 // Emit atomic reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005937 const auto *RHSVar =
5938 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005939 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
5940 AtomicRedGen, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005941 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005942 // Emit atomic reduction for array subscript or single variable.
5943 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005944 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005945 } else {
5946 // Emit as a critical region.
5947 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
Alexey Bataev18fa2322018-05-02 14:20:50 +00005948 const Expr *, const Expr *) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005949 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev18fa2322018-05-02 14:20:50 +00005950 std::string Name = RT.getName({"atomic_reduction"});
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005951 RT.emitCriticalRegion(
Alexey Bataev18fa2322018-05-02 14:20:50 +00005952 CGF, Name,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005953 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
5954 Action.Enter(CGF);
5955 emitReductionCombiner(CGF, E);
5956 },
5957 Loc);
5958 };
5959 if ((*IPriv)->getType()->isArrayType()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005960 const auto *LHSVar =
5961 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5962 const auto *RHSVar =
5963 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005964 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5965 CritRedGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005966 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005967 CritRedGen(CGF, nullptr, nullptr, nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005968 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005969 }
Richard Trieucc3949d2016-02-18 22:34:54 +00005970 ++ILHS;
5971 ++IRHS;
5972 ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005973 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005974 };
5975 RegionCodeGenTy AtomicRCG(AtomicCodeGen);
5976 if (!WithNowait) {
5977 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
5978 llvm::Value *EndArgs[] = {
5979 IdentTLoc, // ident_t *<loc>
5980 ThreadId, // i32 <gtid>
5981 Lock // kmp_critical_name *&<lock>
5982 };
5983 CommonActionTy Action(nullptr, llvm::None,
5984 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
5985 EndArgs);
5986 AtomicRCG.setAction(Action);
5987 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005988 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005989 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005990 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005991
5992 CGF.EmitBranch(DefaultBB);
5993 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
5994}
5995
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005996/// Generates unique name for artificial threadprivate variables.
Alexey Bataev1c44e152018-03-06 18:59:43 +00005997/// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>"
5998static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix,
5999 const Expr *Ref) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006000 SmallString<256> Buffer;
6001 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev1c44e152018-03-06 18:59:43 +00006002 const clang::DeclRefExpr *DE;
6003 const VarDecl *D = ::getBaseDecl(Ref, DE);
6004 if (!D)
6005 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl());
6006 D = D->getCanonicalDecl();
Alexey Bataev18fa2322018-05-02 14:20:50 +00006007 std::string Name = CGM.getOpenMPRuntime().getName(
6008 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)});
6009 Out << Prefix << Name << "_"
Stephen Kellyf2ceec42018-08-09 21:08:08 +00006010 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006011 return Out.str();
6012}
6013
6014/// Emits reduction initializer function:
6015/// \code
6016/// void @.red_init(void* %arg) {
6017/// %0 = bitcast void* %arg to <type>*
6018/// store <type> <init>, <type>* %0
6019/// ret void
6020/// }
6021/// \endcode
6022static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM,
6023 SourceLocation Loc,
6024 ReductionCodeGen &RCG, unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006025 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006026 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006027 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6028 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006029 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006030 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006031 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006032 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006033 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006034 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006035 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006036 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006037 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006038 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006039 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006040 Address PrivateAddr = CGF.EmitLoadOfPointer(
6041 CGF.GetAddrOfLocalVar(&Param),
6042 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6043 llvm::Value *Size = nullptr;
6044 // If the size of the reduction item is non-constant, load it from global
6045 // threadprivate variable.
6046 if (RCG.getSizes(N).second) {
6047 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6048 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006049 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006050 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6051 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006052 }
6053 RCG.emitAggregateType(CGF, N, Size);
6054 LValue SharedLVal;
6055 // If initializer uses initializer from declare reduction construct, emit a
6056 // pointer to the address of the original reduction item (reuired by reduction
6057 // initializer)
6058 if (RCG.usesReductionInitializer(N)) {
6059 Address SharedAddr =
6060 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6061 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006062 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataev21dab122018-03-09 15:20:30 +00006063 SharedAddr = CGF.EmitLoadOfPointer(
6064 SharedAddr,
6065 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006066 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy);
6067 } else {
6068 SharedLVal = CGF.MakeNaturalAlignAddrLValue(
6069 llvm::ConstantPointerNull::get(CGM.VoidPtrTy),
6070 CGM.getContext().VoidPtrTy);
6071 }
6072 // Emit the initializer:
6073 // %0 = bitcast void* %arg to <type>*
6074 // store <type> <init>, <type>* %0
6075 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal,
6076 [](CodeGenFunction &) { return false; });
6077 CGF.FinishFunction();
6078 return Fn;
6079}
6080
6081/// Emits reduction combiner function:
6082/// \code
6083/// void @.red_comb(void* %arg0, void* %arg1) {
6084/// %lhs = bitcast void* %arg0 to <type>*
6085/// %rhs = bitcast void* %arg1 to <type>*
6086/// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs)
6087/// store <type> %2, <type>* %lhs
6088/// ret void
6089/// }
6090/// \endcode
6091static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM,
6092 SourceLocation Loc,
6093 ReductionCodeGen &RCG, unsigned N,
6094 const Expr *ReductionOp,
6095 const Expr *LHS, const Expr *RHS,
6096 const Expr *PrivateRef) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006097 ASTContext &C = CGM.getContext();
6098 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl());
6099 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006100 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006101 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
6102 C.VoidPtrTy, ImplicitParamDecl::Other);
6103 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6104 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006105 Args.emplace_back(&ParamInOut);
6106 Args.emplace_back(&ParamIn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006107 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006108 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006109 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006110 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006111 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006112 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006113 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006114 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006115 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006116 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006117 llvm::Value *Size = nullptr;
6118 // If the size of the reduction item is non-constant, load it from global
6119 // threadprivate variable.
6120 if (RCG.getSizes(N).second) {
6121 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6122 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006123 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006124 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6125 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006126 }
6127 RCG.emitAggregateType(CGF, N, Size);
6128 // Remap lhs and rhs variables to the addresses of the function arguments.
6129 // %lhs = bitcast void* %arg0 to <type>*
6130 // %rhs = bitcast void* %arg1 to <type>*
6131 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006132 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006133 // Pull out the pointer to the variable.
6134 Address PtrAddr = CGF.EmitLoadOfPointer(
6135 CGF.GetAddrOfLocalVar(&ParamInOut),
6136 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6137 return CGF.Builder.CreateElementBitCast(
6138 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType()));
6139 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006140 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006141 // Pull out the pointer to the variable.
6142 Address PtrAddr = CGF.EmitLoadOfPointer(
6143 CGF.GetAddrOfLocalVar(&ParamIn),
6144 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6145 return CGF.Builder.CreateElementBitCast(
6146 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType()));
6147 });
6148 PrivateScope.Privatize();
6149 // Emit the combiner body:
6150 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs)
6151 // store <type> %2, <type>* %lhs
6152 CGM.getOpenMPRuntime().emitSingleReductionCombiner(
6153 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS),
6154 cast<DeclRefExpr>(RHS));
6155 CGF.FinishFunction();
6156 return Fn;
6157}
6158
6159/// Emits reduction finalizer function:
6160/// \code
6161/// void @.red_fini(void* %arg) {
6162/// %0 = bitcast void* %arg to <type>*
6163/// <destroy>(<type>* %0)
6164/// ret void
6165/// }
6166/// \endcode
6167static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM,
6168 SourceLocation Loc,
6169 ReductionCodeGen &RCG, unsigned N) {
6170 if (!RCG.needCleanups(N))
6171 return nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006172 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006173 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006174 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6175 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006176 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006177 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006178 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006179 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006180 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006181 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006182 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006183 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006184 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006185 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006186 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006187 Address PrivateAddr = CGF.EmitLoadOfPointer(
6188 CGF.GetAddrOfLocalVar(&Param),
6189 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6190 llvm::Value *Size = nullptr;
6191 // If the size of the reduction item is non-constant, load it from global
6192 // threadprivate variable.
6193 if (RCG.getSizes(N).second) {
6194 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6195 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006196 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006197 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6198 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006199 }
6200 RCG.emitAggregateType(CGF, N, Size);
6201 // Emit the finalizer body:
6202 // <destroy>(<type>* %0)
6203 RCG.emitCleanups(CGF, N, PrivateAddr);
6204 CGF.FinishFunction();
6205 return Fn;
6206}
6207
6208llvm::Value *CGOpenMPRuntime::emitTaskReductionInit(
6209 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
6210 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
6211 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty())
6212 return nullptr;
6213
6214 // Build typedef struct:
6215 // kmp_task_red_input {
6216 // void *reduce_shar; // shared reduction item
6217 // size_t reduce_size; // size of data item
6218 // void *reduce_init; // data initialization routine
6219 // void *reduce_fini; // data finalization routine
6220 // void *reduce_comb; // data combiner routine
6221 // kmp_task_red_flags_t flags; // flags for additional info from compiler
6222 // } kmp_task_red_input_t;
6223 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006224 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t");
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006225 RD->startDefinition();
6226 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6227 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType());
6228 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6229 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6230 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6231 const FieldDecl *FlagsFD = addFieldToRecordDecl(
6232 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false));
6233 RD->completeDefinition();
6234 QualType RDType = C.getRecordType(RD);
6235 unsigned Size = Data.ReductionVars.size();
6236 llvm::APInt ArraySize(/*numBits=*/64, Size);
6237 QualType ArrayRDType = C.getConstantArrayType(
6238 RDType, ArraySize, ArrayType::Normal, /*IndexTypeQuals=*/0);
6239 // kmp_task_red_input_t .rd_input.[Size];
6240 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input.");
6241 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies,
6242 Data.ReductionOps);
6243 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) {
6244 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt];
6245 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0),
6246 llvm::ConstantInt::get(CGM.SizeTy, Cnt)};
6247 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP(
6248 TaskRedInput.getPointer(), Idxs,
6249 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc,
6250 ".rd_input.gep.");
6251 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType);
6252 // ElemLVal.reduce_shar = &Shareds[Cnt];
6253 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD);
6254 RCG.emitSharedLValue(CGF, Cnt);
6255 llvm::Value *CastedShared =
6256 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer());
6257 CGF.EmitStoreOfScalar(CastedShared, SharedLVal);
6258 RCG.emitAggregateType(CGF, Cnt);
6259 llvm::Value *SizeValInChars;
6260 llvm::Value *SizeVal;
6261 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt);
6262 // We use delayed creation/initialization for VLAs, array sections and
6263 // custom reduction initializations. It is required because runtime does not
6264 // provide the way to pass the sizes of VLAs/array sections to
6265 // initializer/combiner/finalizer functions and does not pass the pointer to
6266 // original reduction item to the initializer. Instead threadprivate global
6267 // variables are used to store these values and use them in the functions.
6268 bool DelayedCreation = !!SizeVal;
6269 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy,
6270 /*isSigned=*/false);
6271 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD);
6272 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal);
6273 // ElemLVal.reduce_init = init;
6274 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD);
6275 llvm::Value *InitAddr =
6276 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt));
6277 CGF.EmitStoreOfScalar(InitAddr, InitLVal);
6278 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt);
6279 // ElemLVal.reduce_fini = fini;
6280 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD);
6281 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt);
6282 llvm::Value *FiniAddr = Fini
6283 ? CGF.EmitCastToVoidPtr(Fini)
6284 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy);
6285 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal);
6286 // ElemLVal.reduce_comb = comb;
6287 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD);
6288 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction(
6289 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt],
6290 RHSExprs[Cnt], Data.ReductionCopies[Cnt]));
6291 CGF.EmitStoreOfScalar(CombAddr, CombLVal);
6292 // ElemLVal.flags = 0;
6293 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD);
6294 if (DelayedCreation) {
6295 CGF.EmitStoreOfScalar(
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006296 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006297 FlagsLVal);
6298 } else
6299 CGF.EmitNullInitialization(FlagsLVal.getAddress(), FlagsLVal.getType());
6300 }
6301 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void
6302 // *data);
6303 llvm::Value *Args[] = {
6304 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6305 /*isSigned=*/true),
6306 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true),
6307 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(),
6308 CGM.VoidPtrTy)};
6309 return CGF.EmitRuntimeCall(
6310 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args);
6311}
6312
6313void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
6314 SourceLocation Loc,
6315 ReductionCodeGen &RCG,
6316 unsigned N) {
6317 auto Sizes = RCG.getSizes(N);
6318 // Emit threadprivate global variable if the type is non-constant
6319 // (Sizes.second = nullptr).
6320 if (Sizes.second) {
6321 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy,
6322 /*isSigned=*/false);
6323 Address SizeAddr = getAddrOfArtificialThreadPrivate(
6324 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006325 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006326 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false);
6327 }
6328 // Store address of the original reduction item if custom initializer is used.
6329 if (RCG.usesReductionInitializer(N)) {
6330 Address SharedAddr = getAddrOfArtificialThreadPrivate(
6331 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006332 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006333 CGF.Builder.CreateStore(
6334 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6335 RCG.getSharedLValue(N).getPointer(), CGM.VoidPtrTy),
6336 SharedAddr, /*IsVolatile=*/false);
6337 }
6338}
6339
6340Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF,
6341 SourceLocation Loc,
6342 llvm::Value *ReductionsPtr,
6343 LValue SharedLVal) {
6344 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
6345 // *d);
6346 llvm::Value *Args[] = {
6347 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6348 /*isSigned=*/true),
6349 ReductionsPtr,
6350 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(SharedLVal.getPointer(),
6351 CGM.VoidPtrTy)};
6352 return Address(
6353 CGF.EmitRuntimeCall(
6354 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args),
6355 SharedLVal.getAlignment());
6356}
6357
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006358void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
6359 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006360 if (!CGF.HaveInsertPoint())
6361 return;
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006362 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
6363 // global_tid);
6364 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
6365 // Ignore return result until untied tasks are supported.
6366 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00006367 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
6368 Region->emitUntiedSwitch(CGF);
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006369}
6370
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006371void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006372 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00006373 const RegionCodeGenTy &CodeGen,
6374 bool HasCancel) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006375 if (!CGF.HaveInsertPoint())
6376 return;
Alexey Bataev25e5b442015-09-15 12:52:43 +00006377 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006378 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00006379}
6380
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006381namespace {
6382enum RTCancelKind {
6383 CancelNoreq = 0,
6384 CancelParallel = 1,
6385 CancelLoop = 2,
6386 CancelSections = 3,
6387 CancelTaskgroup = 4
6388};
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00006389} // anonymous namespace
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006390
6391static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
6392 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00006393 if (CancelRegion == OMPD_parallel)
6394 CancelKind = CancelParallel;
6395 else if (CancelRegion == OMPD_for)
6396 CancelKind = CancelLoop;
6397 else if (CancelRegion == OMPD_sections)
6398 CancelKind = CancelSections;
6399 else {
6400 assert(CancelRegion == OMPD_taskgroup);
6401 CancelKind = CancelTaskgroup;
6402 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006403 return CancelKind;
6404}
6405
6406void CGOpenMPRuntime::emitCancellationPointCall(
6407 CodeGenFunction &CGF, SourceLocation Loc,
6408 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006409 if (!CGF.HaveInsertPoint())
6410 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006411 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
6412 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006413 if (auto *OMPRegionInfo =
6414 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Jonas Hahnfeldb07931f2017-02-17 18:32:58 +00006415 // For 'cancellation point taskgroup', the task region info may not have a
6416 // cancel. This may instead happen in another adjacent task.
6417 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006418 llvm::Value *Args[] = {
6419 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
6420 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006421 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006422 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006423 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
6424 // if (__kmpc_cancellationpoint()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006425 // exit from construct;
6426 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006427 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6428 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6429 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006430 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6431 CGF.EmitBlock(ExitBB);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006432 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006433 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev25e5b442015-09-15 12:52:43 +00006434 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006435 CGF.EmitBranchThroughCleanup(CancelDest);
6436 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6437 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006438 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006439}
6440
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006441void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00006442 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006443 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006444 if (!CGF.HaveInsertPoint())
6445 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006446 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
6447 // kmp_int32 cncl_kind);
6448 if (auto *OMPRegionInfo =
6449 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006450 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF,
6451 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006452 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev87933c72015-09-18 08:07:34 +00006453 llvm::Value *Args[] = {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006454 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
Alexey Bataev87933c72015-09-18 08:07:34 +00006455 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
6456 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006457 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006458 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
Alexey Bataev87933c72015-09-18 08:07:34 +00006459 // if (__kmpc_cancel()) {
Alexey Bataev87933c72015-09-18 08:07:34 +00006460 // exit from construct;
6461 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006462 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6463 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6464 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev87933c72015-09-18 08:07:34 +00006465 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6466 CGF.EmitBlock(ExitBB);
Alexey Bataev87933c72015-09-18 08:07:34 +00006467 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006468 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev87933c72015-09-18 08:07:34 +00006469 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6470 CGF.EmitBranchThroughCleanup(CancelDest);
6471 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6472 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006473 if (IfCond) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006474 emitOMPIfClause(CGF, IfCond, ThenGen,
6475 [](CodeGenFunction &, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006476 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006477 RegionCodeGenTy ThenRCG(ThenGen);
6478 ThenRCG(CGF);
6479 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006480 }
6481}
Samuel Antaobed3c462015-10-02 16:14:20 +00006482
Samuel Antaoee8fb302016-01-06 13:42:12 +00006483void CGOpenMPRuntime::emitTargetOutlinedFunction(
6484 const OMPExecutableDirective &D, StringRef ParentName,
6485 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006486 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00006487 assert(!ParentName.empty() && "Invalid target region parent name!");
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00006488 HasEmittedTargetRegion = true;
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006489 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
6490 IsOffloadEntry, CodeGen);
6491}
6492
6493void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
6494 const OMPExecutableDirective &D, StringRef ParentName,
6495 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6496 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antao2de62b02016-02-13 23:35:10 +00006497 // Create a unique name for the entry function using the source location
6498 // information of the current target region. The name will be something like:
Samuel Antaoee8fb302016-01-06 13:42:12 +00006499 //
Samuel Antao2de62b02016-02-13 23:35:10 +00006500 // __omp_offloading_DD_FFFF_PP_lBB
Samuel Antaoee8fb302016-01-06 13:42:12 +00006501 //
6502 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
Samuel Antao2de62b02016-02-13 23:35:10 +00006503 // mangled name of the function that encloses the target region and BB is the
6504 // line number of the target region.
Samuel Antaoee8fb302016-01-06 13:42:12 +00006505
6506 unsigned DeviceID;
6507 unsigned FileID;
6508 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00006509 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00006510 Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006511 SmallString<64> EntryFnName;
6512 {
6513 llvm::raw_svector_ostream OS(EntryFnName);
Samuel Antao2de62b02016-02-13 23:35:10 +00006514 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
6515 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00006516 }
6517
Alexey Bataev475a7442018-01-12 19:39:11 +00006518 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006519
Samuel Antaobed3c462015-10-02 16:14:20 +00006520 CodeGenFunction CGF(CGM, true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006521 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
Samuel Antaobed3c462015-10-02 16:14:20 +00006522 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006523
Samuel Antao6d004262016-06-16 18:39:34 +00006524 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006525
6526 // If this target outline function is not an offload entry, we don't need to
6527 // register it.
6528 if (!IsOffloadEntry)
6529 return;
6530
6531 // The target region ID is used by the runtime library to identify the current
6532 // target region, so it only has to be unique and not necessarily point to
6533 // anything. It could be the pointer to the outlined function that implements
6534 // the target region, but we aren't using that so that the compiler doesn't
6535 // need to keep that, and could therefore inline the host function if proven
6536 // worthwhile during optimization. In the other hand, if emitting code for the
6537 // device, the ID has to be the function address so that it can retrieved from
6538 // the offloading entry and launched by the runtime library. We also mark the
6539 // outlined function to have external linkage in case we are emitting code for
6540 // the device, because these functions will be entry points to the device.
6541
6542 if (CGM.getLangOpts().OpenMPIsDevice) {
6543 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
Alexey Bataev9a700172018-05-08 14:16:57 +00006544 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Rafael Espindolacbca4872018-01-11 22:15:12 +00006545 OutlinedFn->setDSOLocal(false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006546 } else {
Alexey Bataevc15ea702018-05-09 18:02:37 +00006547 std::string Name = getName({EntryFnName, "region_id"});
Samuel Antaoee8fb302016-01-06 13:42:12 +00006548 OutlinedFnID = new llvm::GlobalVariable(
6549 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
Alexey Bataev9a700172018-05-08 14:16:57 +00006550 llvm::GlobalValue::WeakAnyLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006551 llvm::Constant::getNullValue(CGM.Int8Ty), Name);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006552 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00006553
6554 // Register the information for the entry associated with this target region.
6555 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
Samuel Antaof83efdb2017-01-05 16:02:49 +00006556 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID,
Alexey Bataev03f270c2018-03-30 18:31:07 +00006557 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion);
Samuel Antaobed3c462015-10-02 16:14:20 +00006558}
6559
Alexey Bataev5c427362019-04-10 19:11:33 +00006560/// Checks if the expression is constant or does not have non-trivial function
6561/// calls.
6562static bool isTrivial(ASTContext &Ctx, const Expr * E) {
6563 // We can skip constant expressions.
6564 // We can skip expressions with trivial calls or simple expressions.
6565 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) ||
6566 !E->hasNonTrivialCall(Ctx)) &&
6567 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true);
6568}
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006569
Alexey Bataev5c427362019-04-10 19:11:33 +00006570const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx,
6571 const Stmt *Body) {
6572 const Stmt *Child = Body->IgnoreContainers();
6573 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) {
6574 Child = nullptr;
6575 for (const Stmt *S : C->body()) {
6576 if (const auto *E = dyn_cast<Expr>(S)) {
6577 if (isTrivial(Ctx, E))
6578 continue;
6579 }
6580 // Some of the statements can be ignored.
6581 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) ||
6582 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S))
6583 continue;
6584 // Analyze declarations.
6585 if (const auto *DS = dyn_cast<DeclStmt>(S)) {
6586 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) {
6587 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6588 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6589 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6590 isa<UsingDirectiveDecl>(D) ||
6591 isa<OMPDeclareReductionDecl>(D) ||
6592 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6593 return true;
6594 const auto *VD = dyn_cast<VarDecl>(D);
6595 if (!VD)
6596 return false;
6597 return VD->isConstexpr() ||
6598 ((VD->getType().isTrivialType(Ctx) ||
6599 VD->getType()->isReferenceType()) &&
6600 (!VD->hasInit() || isTrivial(Ctx, VD->getInit())));
6601 }))
6602 continue;
6603 }
6604 // Found multiple children - cannot get the one child only.
6605 if (Child)
6606 return nullptr;
6607 Child = S;
6608 }
6609 if (Child)
6610 Child = Child->IgnoreContainers();
6611 }
6612 return Child;
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006613}
6614
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006615/// Emit the number of teams for a target directive. Inspect the num_teams
6616/// clause associated with a teams construct combined or closely nested
6617/// with the target directive.
6618///
6619/// Emit a team of size one for directives such as 'target parallel' that
6620/// have no associated teams construct.
6621///
6622/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006623static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006624emitNumTeamsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006625 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006626 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6627 "Clauses associated with the teams directive expected to be emitted "
6628 "only for the host!");
6629 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6630 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6631 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006632 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006633 switch (DirectiveKind) {
6634 case OMPD_target: {
6635 const auto *CS = D.getInnermostCapturedStmt();
6636 const auto *Body =
6637 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
6638 const Stmt *ChildStmt =
6639 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body);
6640 if (const auto *NestedDir =
6641 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6642 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) {
6643 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) {
6644 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6645 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6646 const Expr *NumTeams =
6647 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6648 llvm::Value *NumTeamsVal =
6649 CGF.EmitScalarExpr(NumTeams,
6650 /*IgnoreResultAssign*/ true);
6651 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006652 /*isSigned=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00006653 }
6654 return Bld.getInt32(0);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006655 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006656 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) ||
6657 isOpenMPSimdDirective(NestedDir->getDirectiveKind()))
6658 return Bld.getInt32(1);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006659 return Bld.getInt32(0);
6660 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006661 return nullptr;
Samuel Antaob68e2db2016-03-03 16:20:23 +00006662 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006663 case OMPD_target_teams:
6664 case OMPD_target_teams_distribute:
6665 case OMPD_target_teams_distribute_simd:
6666 case OMPD_target_teams_distribute_parallel_for:
6667 case OMPD_target_teams_distribute_parallel_for_simd: {
6668 if (D.hasClausesOfKind<OMPNumTeamsClause>()) {
6669 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF);
6670 const Expr *NumTeams =
6671 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6672 llvm::Value *NumTeamsVal =
6673 CGF.EmitScalarExpr(NumTeams,
6674 /*IgnoreResultAssign*/ true);
6675 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006676 /*isSigned=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00006677 }
6678 return Bld.getInt32(0);
6679 }
6680 case OMPD_target_parallel:
6681 case OMPD_target_parallel_for:
6682 case OMPD_target_parallel_for_simd:
6683 case OMPD_target_simd:
6684 return Bld.getInt32(1);
6685 case OMPD_parallel:
6686 case OMPD_for:
6687 case OMPD_parallel_for:
6688 case OMPD_parallel_sections:
6689 case OMPD_for_simd:
6690 case OMPD_parallel_for_simd:
6691 case OMPD_cancel:
6692 case OMPD_cancellation_point:
6693 case OMPD_ordered:
6694 case OMPD_threadprivate:
6695 case OMPD_allocate:
6696 case OMPD_task:
6697 case OMPD_simd:
6698 case OMPD_sections:
6699 case OMPD_section:
6700 case OMPD_single:
6701 case OMPD_master:
6702 case OMPD_critical:
6703 case OMPD_taskyield:
6704 case OMPD_barrier:
6705 case OMPD_taskwait:
6706 case OMPD_taskgroup:
6707 case OMPD_atomic:
6708 case OMPD_flush:
6709 case OMPD_teams:
6710 case OMPD_target_data:
6711 case OMPD_target_exit_data:
6712 case OMPD_target_enter_data:
6713 case OMPD_distribute:
6714 case OMPD_distribute_simd:
6715 case OMPD_distribute_parallel_for:
6716 case OMPD_distribute_parallel_for_simd:
6717 case OMPD_teams_distribute:
6718 case OMPD_teams_distribute_simd:
6719 case OMPD_teams_distribute_parallel_for:
6720 case OMPD_teams_distribute_parallel_for_simd:
6721 case OMPD_target_update:
6722 case OMPD_declare_simd:
6723 case OMPD_declare_target:
6724 case OMPD_end_declare_target:
6725 case OMPD_declare_reduction:
6726 case OMPD_declare_mapper:
6727 case OMPD_taskloop:
6728 case OMPD_taskloop_simd:
6729 case OMPD_requires:
6730 case OMPD_unknown:
6731 break;
6732 }
6733 llvm_unreachable("Unexpected directive kind.");
6734}
Samuel Antaob68e2db2016-03-03 16:20:23 +00006735
Alexey Bataev5c427362019-04-10 19:11:33 +00006736static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS,
6737 llvm::Value *DefaultThreadLimitVal) {
6738 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6739 CGF.getContext(), CS->getCapturedStmt());
6740 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6741 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) {
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006742 llvm::Value *NumThreads = nullptr;
6743 llvm::Value *CondVal = nullptr;
6744 // Handle if clause. If if clause present, the number of threads is
6745 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6746 if (Dir->hasClausesOfKind<OMPIfClause>()) {
6747 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6748 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6749 const OMPIfClause *IfClause = nullptr;
6750 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) {
6751 if (C->getNameModifier() == OMPD_unknown ||
6752 C->getNameModifier() == OMPD_parallel) {
6753 IfClause = C;
6754 break;
6755 }
6756 }
6757 if (IfClause) {
6758 const Expr *Cond = IfClause->getCondition();
6759 bool Result;
6760 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6761 if (!Result)
6762 return CGF.Builder.getInt32(1);
6763 } else {
6764 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange());
6765 if (const auto *PreInit =
6766 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) {
6767 for (const auto *I : PreInit->decls()) {
6768 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6769 CGF.EmitVarDecl(cast<VarDecl>(*I));
6770 } else {
6771 CodeGenFunction::AutoVarEmission Emission =
6772 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6773 CGF.EmitAutoVarCleanups(Emission);
6774 }
6775 }
6776 }
6777 CondVal = CGF.EvaluateExprAsBool(Cond);
6778 }
6779 }
6780 }
6781 // Check the value of num_threads clause iff if clause was not specified
6782 // or is not evaluated to false.
Alexey Bataev5c427362019-04-10 19:11:33 +00006783 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) {
6784 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6785 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6786 const auto *NumThreadsClause =
6787 Dir->getSingleClause<OMPNumThreadsClause>();
6788 CodeGenFunction::LexicalScope Scope(
6789 CGF, NumThreadsClause->getNumThreads()->getSourceRange());
6790 if (const auto *PreInit =
6791 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6792 for (const auto *I : PreInit->decls()) {
6793 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6794 CGF.EmitVarDecl(cast<VarDecl>(*I));
6795 } else {
6796 CodeGenFunction::AutoVarEmission Emission =
6797 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6798 CGF.EmitAutoVarCleanups(Emission);
6799 }
6800 }
6801 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006802 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads());
Alexey Bataev5c427362019-04-10 19:11:33 +00006803 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006804 /*isSigned=*/false);
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006805 if (DefaultThreadLimitVal)
6806 NumThreads = CGF.Builder.CreateSelect(
6807 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads),
6808 DefaultThreadLimitVal, NumThreads);
6809 } else {
6810 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal
6811 : CGF.Builder.getInt32(0);
Alexey Bataev5c427362019-04-10 19:11:33 +00006812 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006813 // Process condition of the if clause.
6814 if (CondVal) {
6815 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads,
6816 CGF.Builder.getInt32(1));
6817 }
6818 return NumThreads;
Alexey Bataev5c427362019-04-10 19:11:33 +00006819 }
6820 if (isOpenMPSimdDirective(Dir->getDirectiveKind()))
6821 return CGF.Builder.getInt32(1);
6822 return DefaultThreadLimitVal;
6823 }
6824 return DefaultThreadLimitVal ? DefaultThreadLimitVal
6825 : CGF.Builder.getInt32(0);
Samuel Antaob68e2db2016-03-03 16:20:23 +00006826}
6827
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006828/// Emit the number of threads for a target directive. Inspect the
6829/// thread_limit clause associated with a teams construct combined or closely
6830/// nested with the target directive.
6831///
6832/// Emit the num_threads clause for directives such as 'target parallel' that
6833/// have no associated teams construct.
6834///
6835/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006836static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006837emitNumThreadsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006838 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006839 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6840 "Clauses associated with the teams directive expected to be emitted "
6841 "only for the host!");
6842 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6843 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6844 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006845 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006846 llvm::Value *ThreadLimitVal = nullptr;
6847 llvm::Value *NumThreadsVal = nullptr;
6848 switch (DirectiveKind) {
6849 case OMPD_target: {
6850 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6851 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6852 return NumThreads;
6853 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6854 CGF.getContext(), CS->getCapturedStmt());
6855 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6856 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) {
6857 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6858 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6859 const auto *ThreadLimitClause =
6860 Dir->getSingleClause<OMPThreadLimitClause>();
6861 CodeGenFunction::LexicalScope Scope(
6862 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange());
6863 if (const auto *PreInit =
6864 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6865 for (const auto *I : PreInit->decls()) {
6866 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6867 CGF.EmitVarDecl(cast<VarDecl>(*I));
6868 } else {
6869 CodeGenFunction::AutoVarEmission Emission =
6870 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6871 CGF.EmitAutoVarCleanups(Emission);
6872 }
6873 }
6874 }
6875 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6876 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6877 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006878 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006879 }
6880 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) &&
6881 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) {
6882 CS = Dir->getInnermostCapturedStmt();
6883 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6884 CGF.getContext(), CS->getCapturedStmt());
6885 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6886 }
6887 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) &&
6888 !isOpenMPSimdDirective(Dir->getDirectiveKind())) {
6889 CS = Dir->getInnermostCapturedStmt();
6890 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6891 return NumThreads;
6892 }
6893 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind()))
6894 return Bld.getInt32(1);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006895 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006896 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6897 }
6898 case OMPD_target_teams: {
6899 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6900 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6901 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6902 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6903 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6904 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006905 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006906 }
6907 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6908 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6909 return NumThreads;
6910 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6911 CGF.getContext(), CS->getCapturedStmt());
6912 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6913 if (Dir->getDirectiveKind() == OMPD_distribute) {
6914 CS = Dir->getInnermostCapturedStmt();
6915 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6916 return NumThreads;
6917 }
6918 }
6919 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6920 }
6921 case OMPD_target_teams_distribute:
6922 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6923 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6924 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6925 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6926 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6927 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006928 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006929 }
6930 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal);
6931 case OMPD_target_parallel:
6932 case OMPD_target_parallel_for:
6933 case OMPD_target_parallel_for_simd:
6934 case OMPD_target_teams_distribute_parallel_for:
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006935 case OMPD_target_teams_distribute_parallel_for_simd: {
6936 llvm::Value *CondVal = nullptr;
6937 // Handle if clause. If if clause present, the number of threads is
6938 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6939 if (D.hasClausesOfKind<OMPIfClause>()) {
6940 const OMPIfClause *IfClause = nullptr;
6941 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) {
6942 if (C->getNameModifier() == OMPD_unknown ||
6943 C->getNameModifier() == OMPD_parallel) {
6944 IfClause = C;
6945 break;
6946 }
6947 }
6948 if (IfClause) {
6949 const Expr *Cond = IfClause->getCondition();
6950 bool Result;
6951 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6952 if (!Result)
6953 return Bld.getInt32(1);
6954 } else {
6955 CodeGenFunction::RunCleanupsScope Scope(CGF);
6956 CondVal = CGF.EvaluateExprAsBool(Cond);
6957 }
6958 }
6959 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006960 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6961 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6962 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6963 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6964 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6965 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006966 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006967 }
6968 if (D.hasClausesOfKind<OMPNumThreadsClause>()) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006969 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
Alexey Bataev5c427362019-04-10 19:11:33 +00006970 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>();
6971 llvm::Value *NumThreads = CGF.EmitScalarExpr(
6972 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true);
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006973 NumThreadsVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006974 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006975 ThreadLimitVal = ThreadLimitVal
Alexey Bataev5c427362019-04-10 19:11:33 +00006976 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal,
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006977 ThreadLimitVal),
6978 NumThreadsVal, ThreadLimitVal)
6979 : NumThreadsVal;
Alexey Bataev50a1c782017-12-01 21:31:08 +00006980 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006981 if (!ThreadLimitVal)
6982 ThreadLimitVal = Bld.getInt32(0);
6983 if (CondVal)
6984 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1));
6985 return ThreadLimitVal;
6986 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006987 case OMPD_target_teams_distribute_simd:
6988 case OMPD_target_simd:
6989 return Bld.getInt32(1);
6990 case OMPD_parallel:
6991 case OMPD_for:
6992 case OMPD_parallel_for:
6993 case OMPD_parallel_sections:
6994 case OMPD_for_simd:
6995 case OMPD_parallel_for_simd:
6996 case OMPD_cancel:
6997 case OMPD_cancellation_point:
6998 case OMPD_ordered:
6999 case OMPD_threadprivate:
7000 case OMPD_allocate:
7001 case OMPD_task:
7002 case OMPD_simd:
7003 case OMPD_sections:
7004 case OMPD_section:
7005 case OMPD_single:
7006 case OMPD_master:
7007 case OMPD_critical:
7008 case OMPD_taskyield:
7009 case OMPD_barrier:
7010 case OMPD_taskwait:
7011 case OMPD_taskgroup:
7012 case OMPD_atomic:
7013 case OMPD_flush:
7014 case OMPD_teams:
7015 case OMPD_target_data:
7016 case OMPD_target_exit_data:
7017 case OMPD_target_enter_data:
7018 case OMPD_distribute:
7019 case OMPD_distribute_simd:
7020 case OMPD_distribute_parallel_for:
7021 case OMPD_distribute_parallel_for_simd:
7022 case OMPD_teams_distribute:
7023 case OMPD_teams_distribute_simd:
7024 case OMPD_teams_distribute_parallel_for:
7025 case OMPD_teams_distribute_parallel_for_simd:
7026 case OMPD_target_update:
7027 case OMPD_declare_simd:
7028 case OMPD_declare_target:
7029 case OMPD_end_declare_target:
7030 case OMPD_declare_reduction:
7031 case OMPD_declare_mapper:
7032 case OMPD_taskloop:
7033 case OMPD_taskloop_simd:
7034 case OMPD_requires:
7035 case OMPD_unknown:
7036 break;
Samuel Antaob68e2db2016-03-03 16:20:23 +00007037 }
Alexey Bataev5c427362019-04-10 19:11:33 +00007038 llvm_unreachable("Unsupported directive kind.");
Samuel Antaob68e2db2016-03-03 16:20:23 +00007039}
7040
Samuel Antao86ace552016-04-27 22:40:57 +00007041namespace {
Alexey Bataevb3638132018-07-19 16:34:13 +00007042LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
7043
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007044// Utility to handle information from clauses associated with a given
Samuel Antao86ace552016-04-27 22:40:57 +00007045// construct that use mappable expressions (e.g. 'map' clause, 'to' clause).
7046// It provides a convenient interface to obtain the information and generate
7047// code for that information.
7048class MappableExprsHandler {
7049public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007050 /// Values for bit flags used to specify the mapping type for
Samuel Antao86ace552016-04-27 22:40:57 +00007051 /// offloading.
Alexey Bataevb3638132018-07-19 16:34:13 +00007052 enum OpenMPOffloadMappingFlags : uint64_t {
7053 /// No flags
7054 OMP_MAP_NONE = 0x0,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007055 /// Allocate memory on the device and move data from host to device.
Samuel Antao86ace552016-04-27 22:40:57 +00007056 OMP_MAP_TO = 0x01,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007057 /// Allocate memory on the device and move data from device to host.
Samuel Antao86ace552016-04-27 22:40:57 +00007058 OMP_MAP_FROM = 0x02,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007059 /// Always perform the requested mapping action on the element, even
Samuel Antao86ace552016-04-27 22:40:57 +00007060 /// if it was already mapped before.
7061 OMP_MAP_ALWAYS = 0x04,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007062 /// Delete the element from the device environment, ignoring the
Samuel Antao86ace552016-04-27 22:40:57 +00007063 /// current reference count associated with the element.
Samuel Antao6782e942016-05-26 16:48:10 +00007064 OMP_MAP_DELETE = 0x08,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007065 /// The element being mapped is a pointer-pointee pair; both the
George Rokos065755d2017-11-07 18:27:04 +00007066 /// pointer and the pointee should be mapped.
7067 OMP_MAP_PTR_AND_OBJ = 0x10,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007068 /// This flags signals that the base address of an entry should be
George Rokos065755d2017-11-07 18:27:04 +00007069 /// passed to the target kernel as an argument.
7070 OMP_MAP_TARGET_PARAM = 0x20,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007071 /// Signal that the runtime library has to return the device pointer
George Rokos065755d2017-11-07 18:27:04 +00007072 /// in the current position for the data being mapped. Used when we have the
7073 /// use_device_ptr clause.
7074 OMP_MAP_RETURN_PARAM = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007075 /// This flag signals that the reference being passed is a pointer to
Samuel Antaod486f842016-05-26 16:53:38 +00007076 /// private data.
George Rokos065755d2017-11-07 18:27:04 +00007077 OMP_MAP_PRIVATE = 0x80,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007078 /// Pass the element to the device by value.
George Rokos065755d2017-11-07 18:27:04 +00007079 OMP_MAP_LITERAL = 0x100,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007080 /// Implicit map
7081 OMP_MAP_IMPLICIT = 0x200,
Alexey Bataevb3638132018-07-19 16:34:13 +00007082 /// The 16 MSBs of the flags indicate whether the entry is member of some
7083 /// struct/class.
7084 OMP_MAP_MEMBER_OF = 0xffff000000000000,
7085 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF),
Samuel Antao86ace552016-04-27 22:40:57 +00007086 };
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
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007151 /// Directive from where the map clauses were extracted.
Samuel Antao44bcdb32016-07-28 15:31:29 +00007152 const OMPExecutableDirective &CurDir;
Samuel Antao86ace552016-04-27 22:40:57 +00007153
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007154 /// Function the directive is being generated for.
Samuel Antao86ace552016-04-27 22:40:57 +00007155 CodeGenFunction &CGF;
7156
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007157 /// Set of all first private variables in the current directive.
Alexey Bataevf288cf92019-06-27 18:53:07 +00007158 /// bool data is set to true if the variable is implicitly marked as
7159 /// firstprivate, false otherwise.
7160 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls;
Samuel Antaod486f842016-05-26 16:53:38 +00007161
Samuel Antao6890b092016-07-28 14:25:09 +00007162 /// Map between device pointer declarations and their expression components.
7163 /// The key value for declarations in 'this' is null.
7164 llvm::DenseMap<
7165 const ValueDecl *,
7166 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7167 DevPointersMap;
7168
Samuel Antao86ace552016-04-27 22:40:57 +00007169 llvm::Value *getExprTypeSize(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007170 QualType ExprTy = E->getType().getCanonicalType();
Samuel Antao86ace552016-04-27 22:40:57 +00007171
7172 // Reference types are ignored for mapping purposes.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007173 if (const auto *RefTy = ExprTy->getAs<ReferenceType>())
Samuel Antao86ace552016-04-27 22:40:57 +00007174 ExprTy = RefTy->getPointeeType().getCanonicalType();
7175
7176 // Given that an array section is considered a built-in type, we need to
7177 // do the calculation based on the length of the section instead of relying
7178 // on CGF.getTypeSize(E->getType()).
7179 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) {
7180 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType(
7181 OAE->getBase()->IgnoreParenImpCasts())
7182 .getCanonicalType();
7183
7184 // If there is no length associated with the expression, that means we
7185 // are using the whole length of the base.
7186 if (!OAE->getLength() && OAE->getColonLoc().isValid())
7187 return CGF.getTypeSize(BaseTy);
7188
7189 llvm::Value *ElemSize;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007190 if (const auto *PTy = BaseTy->getAs<PointerType>()) {
Samuel Antao86ace552016-04-27 22:40:57 +00007191 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007192 } else {
7193 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr());
Samuel Antao86ace552016-04-27 22:40:57 +00007194 assert(ATy && "Expecting array type if not a pointer type.");
7195 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType());
7196 }
7197
7198 // If we don't have a length at this point, that is because we have an
7199 // array section with a single element.
7200 if (!OAE->getLength())
7201 return ElemSize;
7202
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007203 llvm::Value *LengthVal = CGF.EmitScalarExpr(OAE->getLength());
Samuel Antao86ace552016-04-27 22:40:57 +00007204 LengthVal =
7205 CGF.Builder.CreateIntCast(LengthVal, CGF.SizeTy, /*isSigned=*/false);
7206 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize);
7207 }
7208 return CGF.getTypeSize(ExprTy);
7209 }
7210
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007211 /// Return the corresponding bits for a given map clause modifier. Add
Samuel Antao86ace552016-04-27 22:40:57 +00007212 /// a flag marking the map as a pointer if requested. Add a flag marking the
Samuel Antao6782e942016-05-26 16:48:10 +00007213 /// map as the first one of a series of maps that relate to the same map
7214 /// expression.
Kelvin Lief579432018-12-18 22:18:41 +00007215 OpenMPOffloadMappingFlags getMapTypeBits(
7216 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
7217 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const {
Alexey Bataevb3638132018-07-19 16:34:13 +00007218 OpenMPOffloadMappingFlags Bits =
7219 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE;
Samuel Antao86ace552016-04-27 22:40:57 +00007220 switch (MapType) {
7221 case OMPC_MAP_alloc:
Samuel Antao6782e942016-05-26 16:48:10 +00007222 case OMPC_MAP_release:
7223 // alloc and release is the default behavior in the runtime library, i.e.
7224 // if we don't pass any bits alloc/release that is what the runtime is
7225 // going to do. Therefore, we don't need to signal anything for these two
7226 // type modifiers.
Samuel Antao86ace552016-04-27 22:40:57 +00007227 break;
7228 case OMPC_MAP_to:
Alexey Bataevb3638132018-07-19 16:34:13 +00007229 Bits |= OMP_MAP_TO;
Samuel Antao86ace552016-04-27 22:40:57 +00007230 break;
7231 case OMPC_MAP_from:
Alexey Bataevb3638132018-07-19 16:34:13 +00007232 Bits |= OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007233 break;
7234 case OMPC_MAP_tofrom:
Alexey Bataevb3638132018-07-19 16:34:13 +00007235 Bits |= OMP_MAP_TO | OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007236 break;
7237 case OMPC_MAP_delete:
Alexey Bataevb3638132018-07-19 16:34:13 +00007238 Bits |= OMP_MAP_DELETE;
Samuel Antao86ace552016-04-27 22:40:57 +00007239 break;
Alexey Bataevb3638132018-07-19 16:34:13 +00007240 case OMPC_MAP_unknown:
Samuel Antao86ace552016-04-27 22:40:57 +00007241 llvm_unreachable("Unexpected map type!");
Samuel Antao86ace552016-04-27 22:40:57 +00007242 }
7243 if (AddPtrFlag)
George Rokos065755d2017-11-07 18:27:04 +00007244 Bits |= OMP_MAP_PTR_AND_OBJ;
7245 if (AddIsTargetParamFlag)
7246 Bits |= OMP_MAP_TARGET_PARAM;
Kelvin Lief579432018-12-18 22:18:41 +00007247 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always)
7248 != MapModifiers.end())
Samuel Antao86ace552016-04-27 22:40:57 +00007249 Bits |= OMP_MAP_ALWAYS;
7250 return Bits;
7251 }
7252
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007253 /// Return true if the provided expression is a final array section. A
Samuel Antao86ace552016-04-27 22:40:57 +00007254 /// final array section, is one whose length can't be proved to be one.
7255 bool isFinalArraySectionExpression(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007256 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
Samuel Antao86ace552016-04-27 22:40:57 +00007257
7258 // It is not an array section and therefore not a unity-size one.
7259 if (!OASE)
7260 return false;
7261
7262 // An array section with no colon always refer to a single element.
7263 if (OASE->getColonLoc().isInvalid())
7264 return false;
7265
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007266 const Expr *Length = OASE->getLength();
Samuel Antao86ace552016-04-27 22:40:57 +00007267
7268 // If we don't have a length we have to check if the array has size 1
7269 // for this dimension. Also, we should always expect a length if the
7270 // base type is pointer.
7271 if (!Length) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007272 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType(
7273 OASE->getBase()->IgnoreParenImpCasts())
7274 .getCanonicalType();
7275 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
Samuel Antao86ace552016-04-27 22:40:57 +00007276 return ATy->getSize().getSExtValue() != 1;
7277 // If we don't have a constant dimension length, we have to consider
7278 // the current section as having any size, so it is not necessarily
7279 // unitary. If it happen to be unity size, that's user fault.
7280 return true;
7281 }
7282
7283 // Check if the length evaluates to 1.
Fangrui Song407659a2018-11-30 23:41:18 +00007284 Expr::EvalResult Result;
7285 if (!Length->EvaluateAsInt(Result, CGF.getContext()))
Samuel Antao86ace552016-04-27 22:40:57 +00007286 return true; // Can have more that size 1.
7287
Fangrui Song407659a2018-11-30 23:41:18 +00007288 llvm::APSInt ConstLength = Result.Val.getInt();
Samuel Antao86ace552016-04-27 22:40:57 +00007289 return ConstLength.getSExtValue() != 1;
7290 }
7291
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007292 /// Generate the base pointers, section pointers, sizes and map type
Samuel Antao86ace552016-04-27 22:40:57 +00007293 /// bits for the provided map type, map modifier, and expression components.
7294 /// \a IsFirstComponent should be set to true if the provided set of
7295 /// components is the first associated with a capture.
7296 void generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00007297 OpenMPMapClauseKind MapType,
7298 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Samuel Antao86ace552016-04-27 22:40:57 +00007299 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Samuel Antaocc10b852016-07-28 14:23:26 +00007300 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007301 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
Alexey Bataevb3638132018-07-19 16:34:13 +00007302 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007303 bool IsImplicit,
7304 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7305 OverlappedElements = llvm::None) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007306 // The following summarizes what has to be generated for each map and the
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00007307 // types below. The generated information is expressed in this order:
Samuel Antao86ace552016-04-27 22:40:57 +00007308 // base pointer, section pointer, size, flags
7309 // (to add to the ones that come from the map type and modifier).
7310 //
7311 // double d;
7312 // int i[100];
7313 // float *p;
7314 //
7315 // struct S1 {
7316 // int i;
7317 // float f[50];
7318 // }
7319 // struct S2 {
7320 // int i;
7321 // float f[50];
7322 // S1 s;
7323 // double *p;
7324 // struct S2 *ps;
7325 // }
7326 // S2 s;
7327 // S2 *ps;
7328 //
7329 // map(d)
Alexey Bataevb3638132018-07-19 16:34:13 +00007330 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007331 //
7332 // map(i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007333 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007334 //
7335 // map(i[1:23])
Alexey Bataevb3638132018-07-19 16:34:13 +00007336 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007337 //
7338 // map(p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007339 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007340 //
7341 // map(p[1:24])
Alexey Bataevb3638132018-07-19 16:34:13 +00007342 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007343 //
7344 // map(s)
Alexey Bataevb3638132018-07-19 16:34:13 +00007345 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007346 //
7347 // map(s.i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007348 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007349 //
7350 // map(s.s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007351 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007352 //
7353 // map(s.p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007354 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007355 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007356 // map(to: s.p[:22])
7357 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*)
7358 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**)
7359 // &(s.p), &(s.p[0]), 22*sizeof(double),
7360 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***)
7361 // (*) alloc space for struct members, only this is a target parameter
7362 // (**) map the pointer (nothing to be mapped in this example) (the compiler
7363 // optimizes this entry out, same in the examples below)
7364 // (***) map the pointee (map: to)
Samuel Antao86ace552016-04-27 22:40:57 +00007365 //
7366 // map(s.ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007367 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007368 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007369 // map(from: s.ps->s.i)
7370 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7371 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7372 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007373 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007374 // map(to: s.ps->ps)
7375 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7376 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7377 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007378 //
7379 // map(s.ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007380 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7381 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7382 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7383 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007384 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007385 // map(to: s.ps->ps->s.f[:22])
7386 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7387 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7388 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7389 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007390 //
7391 // map(ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007392 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007393 //
7394 // map(ps->i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007395 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007396 //
7397 // map(ps->s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007398 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007399 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007400 // map(from: ps->p)
7401 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007402 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007403 // map(to: ps->p[:22])
7404 // ps, &(ps->p), sizeof(double*), TARGET_PARAM
7405 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1)
7406 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007407 //
7408 // map(ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007409 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007410 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007411 // map(from: ps->ps->s.i)
7412 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7413 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7414 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007415 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007416 // map(from: ps->ps->ps)
7417 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7418 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7419 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007420 //
7421 // map(ps->ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007422 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7423 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7424 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7425 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007426 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007427 // map(to: ps->ps->ps->s.f[:22])
7428 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7429 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7430 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7431 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
7432 //
7433 // map(to: s.f[:22]) map(from: s.p[:33])
7434 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) +
7435 // sizeof(double*) (**), TARGET_PARAM
7436 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO
7437 // &s, &(s.p), sizeof(double*), MEMBER_OF(1)
7438 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7439 // (*) allocate contiguous space needed to fit all mapped members even if
7440 // we allocate space for members not mapped (in this example,
7441 // s.f[22..49] and s.s are not mapped, yet we must allocate space for
7442 // them as well because they fall between &s.f[0] and &s.p)
7443 //
7444 // map(from: s.f[:22]) map(to: ps->p[:33])
7445 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM
7446 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7447 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*)
7448 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO
7449 // (*) the struct this entry pertains to is the 2nd element in the list of
7450 // arguments, hence MEMBER_OF(2)
7451 //
7452 // map(from: s.f[:22], s.s) map(to: ps->p[:33])
7453 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM
7454 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM
7455 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM
7456 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7457 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*)
7458 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO
7459 // (*) the struct this entry pertains to is the 4th element in the list
7460 // of arguments, hence MEMBER_OF(4)
Samuel Antao86ace552016-04-27 22:40:57 +00007461
7462 // Track if the map information being generated is the first for a capture.
7463 bool IsCaptureFirstInfo = IsFirstComponentList;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007464 // When the variable is on a declare target link or in a to clause with
7465 // unified memory, a reference is needed to hold the host/device address
7466 // of the variable.
7467 bool RequiresReference = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007468
7469 // Scan the components from the base to the complete expression.
7470 auto CI = Components.rbegin();
7471 auto CE = Components.rend();
7472 auto I = CI;
7473
7474 // Track if the map information being generated is the first for a list of
7475 // components.
7476 bool IsExpressionFirstInfo = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00007477 Address BP = Address::invalid();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007478 const Expr *AssocExpr = I->getAssociatedExpression();
7479 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7480 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
Samuel Antao86ace552016-04-27 22:40:57 +00007481
Patrick Lystere13b1e32019-01-02 19:28:48 +00007482 if (isa<MemberExpr>(AssocExpr)) {
Samuel Antao86ace552016-04-27 22:40:57 +00007483 // The base is the 'this' pointer. The content of the pointer is going
7484 // to be the base of the field being mapped.
Alexey Bataevb3638132018-07-19 16:34:13 +00007485 BP = CGF.LoadCXXThisAddress();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007486 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7487 (OASE &&
7488 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
7489 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
Samuel Antao86ace552016-04-27 22:40:57 +00007490 } else {
7491 // The base is the reference to the variable.
7492 // BP = &Var.
Patrick Lystere13b1e32019-01-02 19:28:48 +00007493 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
Alexey Bataev92327c52018-03-26 16:40:55 +00007494 if (const auto *VD =
7495 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7496 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007497 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7498 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7499 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
7500 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) {
7501 RequiresReference = true;
7502 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataev2c1dffe2018-04-16 20:34:41 +00007503 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007504 }
Alexey Bataev92327c52018-03-26 16:40:55 +00007505 }
Samuel Antao86ace552016-04-27 22:40:57 +00007506
7507 // If the variable is a pointer and is being dereferenced (i.e. is not
Nico Webera6916892016-06-10 18:53:04 +00007508 // the last component), the base has to be the pointer itself, not its
Samuel Antao403ffd42016-07-27 22:49:49 +00007509 // reference. References are ignored for mapping purposes.
7510 QualType Ty =
7511 I->getAssociatedDeclaration()->getType().getNonReferenceType();
7512 if (Ty->isAnyPointerType() && std::next(I) != CE) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007513 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
Samuel Antao86ace552016-04-27 22:40:57 +00007514
7515 // We do not need to generate individual map information for the
7516 // pointer, it can be associated with the combined storage.
7517 ++I;
7518 }
7519 }
7520
Alexey Bataevb3638132018-07-19 16:34:13 +00007521 // Track whether a component of the list should be marked as MEMBER_OF some
7522 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry
7523 // in a component list should be marked as MEMBER_OF, all subsequent entries
7524 // do not belong to the base struct. E.g.
7525 // struct S2 s;
7526 // s.ps->ps->ps->f[:]
7527 // (1) (2) (3) (4)
7528 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a
7529 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3)
7530 // is the pointee of ps(2) which is not member of struct s, so it should not
7531 // be marked as such (it is still PTR_AND_OBJ).
7532 // The variable is initialized to false so that PTR_AND_OBJ entries which
7533 // are not struct members are not considered (e.g. array of pointers to
7534 // data).
7535 bool ShouldBeMemberOf = false;
7536
7537 // Variable keeping track of whether or not we have encountered a component
7538 // in the component list which is a member expression. Useful when we have a
7539 // pointer or a final array section, in which case it is the previous
7540 // component in the list which tells us whether we have a member expression.
7541 // E.g. X.f[:]
7542 // While processing the final array section "[:]" it is "f" which tells us
7543 // whether we are dealing with a member of a declared struct.
7544 const MemberExpr *EncounteredME = nullptr;
7545
Samuel Antao86ace552016-04-27 22:40:57 +00007546 for (; I != CE; ++I) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007547 // If the current component is member of a struct (parent struct) mark it.
7548 if (!EncounteredME) {
7549 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7550 // If we encounter a PTR_AND_OBJ entry from now on it should be marked
7551 // as MEMBER_OF the parent struct.
7552 if (EncounteredME)
7553 ShouldBeMemberOf = true;
7554 }
7555
Samuel Antao86ace552016-04-27 22:40:57 +00007556 auto Next = std::next(I);
7557
7558 // We need to generate the addresses and sizes if this is the last
7559 // component, if the component is a pointer or if it is an array section
7560 // whose length can't be proved to be one. If this is a pointer, it
7561 // becomes the base address for the following components.
7562
7563 // A final array section, is one whose length can't be proved to be one.
7564 bool IsFinalArraySection =
7565 isFinalArraySectionExpression(I->getAssociatedExpression());
7566
7567 // Get information on whether the element is a pointer. Have to do a
7568 // special treatment for array sections given that they are built-in
7569 // types.
7570 const auto *OASE =
7571 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression());
7572 bool IsPointer =
Alexey Bataevb3638132018-07-19 16:34:13 +00007573 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE)
7574 .getCanonicalType()
7575 ->isAnyPointerType()) ||
Samuel Antao86ace552016-04-27 22:40:57 +00007576 I->getAssociatedExpression()->getType()->isAnyPointerType();
7577
7578 if (Next == CE || IsPointer || IsFinalArraySection) {
Samuel Antao86ace552016-04-27 22:40:57 +00007579 // If this is not the last component, we expect the pointer to be
7580 // associated with an array expression or member expression.
7581 assert((Next == CE ||
7582 isa<MemberExpr>(Next->getAssociatedExpression()) ||
7583 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||
7584 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) &&
7585 "Unexpected expression");
7586
Alexey Bataevb3638132018-07-19 16:34:13 +00007587 Address LB =
7588 CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getAddress();
Samuel Antao86ace552016-04-27 22:40:57 +00007589
Alexey Bataevb3638132018-07-19 16:34:13 +00007590 // If this component is a pointer inside the base struct then we don't
7591 // need to create any entry for it - it will be combined with the object
7592 // it is pointing to into a single PTR_AND_OBJ entry.
7593 bool IsMemberPointer =
7594 IsPointer && EncounteredME &&
7595 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) ==
7596 EncounteredME);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007597 if (!OverlappedElements.empty()) {
7598 // Handle base element with the info for overlapped elements.
7599 assert(!PartialStruct.Base.isValid() && "The base element is set.");
7600 assert(Next == CE &&
7601 "Expected last element for the overlapped elements.");
7602 assert(!IsPointer &&
7603 "Unexpected base element with the pointer type.");
7604 // Mark the whole struct as the struct that requires allocation on the
7605 // device.
7606 PartialStruct.LowestElem = {0, LB};
7607 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(
7608 I->getAssociatedExpression()->getType());
7609 Address HB = CGF.Builder.CreateConstGEP(
7610 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB,
7611 CGF.VoidPtrTy),
James Y Knight751fe282019-02-09 22:22:28 +00007612 TypeSize.getQuantity() - 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007613 PartialStruct.HighestElem = {
7614 std::numeric_limits<decltype(
7615 PartialStruct.HighestElem.first)>::max(),
7616 HB};
7617 PartialStruct.Base = BP;
7618 // Emit data for non-overlapped data.
7619 OpenMPOffloadMappingFlags Flags =
7620 OMP_MAP_MEMBER_OF |
Kelvin Lief579432018-12-18 22:18:41 +00007621 getMapTypeBits(MapType, MapModifiers, IsImplicit,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007622 /*AddPtrFlag=*/false,
7623 /*AddIsTargetParamFlag=*/false);
7624 LB = BP;
7625 llvm::Value *Size = nullptr;
7626 // Do bitcopy of all non-overlapped structure elements.
7627 for (OMPClauseMappableExprCommon::MappableExprComponentListRef
7628 Component : OverlappedElements) {
7629 Address ComponentLB = Address::invalid();
7630 for (const OMPClauseMappableExprCommon::MappableComponent &MC :
7631 Component) {
7632 if (MC.getAssociatedDeclaration()) {
7633 ComponentLB =
7634 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
7635 .getAddress();
7636 Size = CGF.Builder.CreatePtrDiff(
7637 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()),
7638 CGF.EmitCastToVoidPtr(LB.getPointer()));
7639 break;
7640 }
7641 }
7642 BasePointers.push_back(BP.getPointer());
7643 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007644 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty,
7645 /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007646 Types.push_back(Flags);
James Y Knight751fe282019-02-09 22:22:28 +00007647 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007648 }
7649 BasePointers.push_back(BP.getPointer());
7650 Pointers.push_back(LB.getPointer());
7651 Size = CGF.Builder.CreatePtrDiff(
7652 CGF.EmitCastToVoidPtr(
James Y Knight751fe282019-02-09 22:22:28 +00007653 CGF.Builder.CreateConstGEP(HB, 1).getPointer()),
Alexey Bataeve82445f2018-09-20 13:54:02 +00007654 CGF.EmitCastToVoidPtr(LB.getPointer()));
Alexey Bataeva90fc662019-06-25 16:00:43 +00007655 Sizes.push_back(
7656 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007657 Types.push_back(Flags);
7658 break;
7659 }
7660 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
Alexey Bataevb3638132018-07-19 16:34:13 +00007661 if (!IsMemberPointer) {
7662 BasePointers.push_back(BP.getPointer());
7663 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007664 Sizes.push_back(
7665 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Samuel Antao03a3cec2016-07-27 22:52:16 +00007666
Alexey Bataevb3638132018-07-19 16:34:13 +00007667 // We need to add a pointer flag for each map that comes from the
7668 // same expression except for the first one. We also need to signal
7669 // this map is the first one that relates with the current capture
7670 // (there is a set of entries for each capture).
7671 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
Kelvin Lief579432018-12-18 22:18:41 +00007672 MapType, MapModifiers, IsImplicit,
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007673 !IsExpressionFirstInfo || RequiresReference,
7674 IsCaptureFirstInfo && !RequiresReference);
Alexey Bataevb3638132018-07-19 16:34:13 +00007675
7676 if (!IsExpressionFirstInfo) {
7677 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
7678 // then we reset the TO/FROM/ALWAYS/DELETE flags.
7679 if (IsPointer)
7680 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS |
7681 OMP_MAP_DELETE);
7682
7683 if (ShouldBeMemberOf) {
7684 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag
7685 // should be later updated with the correct value of MEMBER_OF.
7686 Flags |= OMP_MAP_MEMBER_OF;
7687 // From now on, all subsequent PTR_AND_OBJ entries should not be
7688 // marked as MEMBER_OF.
7689 ShouldBeMemberOf = false;
7690 }
7691 }
7692
7693 Types.push_back(Flags);
Samuel Antao03a3cec2016-07-27 22:52:16 +00007694 }
7695
Alexey Bataevb3638132018-07-19 16:34:13 +00007696 // If we have encountered a member expression so far, keep track of the
7697 // mapped member. If the parent is "*this", then the value declaration
7698 // is nullptr.
7699 if (EncounteredME) {
7700 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl());
7701 unsigned FieldIndex = FD->getFieldIndex();
Samuel Antao03a3cec2016-07-27 22:52:16 +00007702
Alexey Bataevb3638132018-07-19 16:34:13 +00007703 // Update info about the lowest and highest elements for this struct
7704 if (!PartialStruct.Base.isValid()) {
7705 PartialStruct.LowestElem = {FieldIndex, LB};
7706 PartialStruct.HighestElem = {FieldIndex, LB};
7707 PartialStruct.Base = BP;
7708 } else if (FieldIndex < PartialStruct.LowestElem.first) {
7709 PartialStruct.LowestElem = {FieldIndex, LB};
7710 } else if (FieldIndex > PartialStruct.HighestElem.first) {
7711 PartialStruct.HighestElem = {FieldIndex, LB};
7712 }
7713 }
Samuel Antao86ace552016-04-27 22:40:57 +00007714
7715 // If we have a final array section, we are done with this expression.
7716 if (IsFinalArraySection)
7717 break;
7718
7719 // The pointer becomes the base for the next element.
7720 if (Next != CE)
7721 BP = LB;
7722
7723 IsExpressionFirstInfo = false;
7724 IsCaptureFirstInfo = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007725 }
7726 }
7727 }
7728
Alexey Bataevb3638132018-07-19 16:34:13 +00007729 /// Return the adjusted map modifiers if the declaration a capture refers to
7730 /// appears in a first-private clause. This is expected to be used only with
7731 /// directives that start with 'target'.
7732 MappableExprsHandler::OpenMPOffloadMappingFlags
7733 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const {
7734 assert(Cap.capturesVariable() && "Expected capture by reference only!");
7735
7736 // A first private variable captured by reference will use only the
7737 // 'private ptr' and 'map to' flag. Return the right flags if the captured
7738 // declaration is known as first-private in this handler.
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007739 if (FirstPrivateDecls.count(Cap.getCapturedVar())) {
7740 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) &&
7741 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef)
7742 return MappableExprsHandler::OMP_MAP_ALWAYS |
7743 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataevc2b831f2019-04-02 16:03:40 +00007744 if (Cap.getCapturedVar()->getType()->isAnyPointerType())
7745 return MappableExprsHandler::OMP_MAP_TO |
7746 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ;
Alexey Bataevb3638132018-07-19 16:34:13 +00007747 return MappableExprsHandler::OMP_MAP_PRIVATE |
7748 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007749 }
Alexey Bataevb3638132018-07-19 16:34:13 +00007750 return MappableExprsHandler::OMP_MAP_TO |
7751 MappableExprsHandler::OMP_MAP_FROM;
7752 }
7753
7754 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) {
7755 // Member of is given by the 16 MSB of the flag, so rotate by 48 bits.
7756 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1)
7757 << 48);
7758 }
7759
7760 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags,
7761 OpenMPOffloadMappingFlags MemberOfFlag) {
7762 // If the entry is PTR_AND_OBJ but has not been marked with the special
7763 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be
7764 // marked as MEMBER_OF.
7765 if ((Flags & OMP_MAP_PTR_AND_OBJ) &&
7766 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF))
7767 return;
7768
7769 // Reset the placeholder value to prepare the flag for the assignment of the
7770 // proper MEMBER_OF value.
7771 Flags &= ~OMP_MAP_MEMBER_OF;
7772 Flags |= MemberOfFlag;
7773 }
7774
Alexey Bataeve82445f2018-09-20 13:54:02 +00007775 void getPlainLayout(const CXXRecordDecl *RD,
7776 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
7777 bool AsBase) const {
7778 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD);
7779
7780 llvm::StructType *St =
7781 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType();
7782
7783 unsigned NumElements = St->getNumElements();
7784 llvm::SmallVector<
7785 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
7786 RecordLayout(NumElements);
7787
7788 // Fill bases.
7789 for (const auto &I : RD->bases()) {
7790 if (I.isVirtual())
7791 continue;
7792 const auto *Base = I.getType()->getAsCXXRecordDecl();
7793 // Ignore empty bases.
7794 if (Base->isEmpty() || CGF.getContext()
7795 .getASTRecordLayout(Base)
7796 .getNonVirtualSize()
7797 .isZero())
7798 continue;
7799
7800 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
7801 RecordLayout[FieldIndex] = Base;
7802 }
7803 // Fill in virtual bases.
7804 for (const auto &I : RD->vbases()) {
7805 const auto *Base = I.getType()->getAsCXXRecordDecl();
7806 // Ignore empty bases.
7807 if (Base->isEmpty())
7808 continue;
7809 unsigned FieldIndex = RL.getVirtualBaseIndex(Base);
7810 if (RecordLayout[FieldIndex])
7811 continue;
7812 RecordLayout[FieldIndex] = Base;
7813 }
7814 // Fill in all the fields.
7815 assert(!RD->isUnion() && "Unexpected union.");
7816 for (const auto *Field : RD->fields()) {
7817 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
7818 // will fill in later.)
Richard Smith78b239e2019-06-20 20:44:45 +00007819 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) {
Alexey Bataeve82445f2018-09-20 13:54:02 +00007820 unsigned FieldIndex = RL.getLLVMFieldNo(Field);
7821 RecordLayout[FieldIndex] = Field;
7822 }
7823 }
7824 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
7825 &Data : RecordLayout) {
7826 if (Data.isNull())
7827 continue;
7828 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>())
7829 getPlainLayout(Base, Layout, /*AsBase=*/true);
7830 else
7831 Layout.push_back(Data.get<const FieldDecl *>());
7832 }
7833 }
7834
Alexey Bataevb3638132018-07-19 16:34:13 +00007835public:
7836 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
7837 : CurDir(Dir), CGF(CGF) {
7838 // Extract firstprivate clause information.
7839 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>())
7840 for (const auto *D : C->varlists())
Alexey Bataevf288cf92019-06-27 18:53:07 +00007841 FirstPrivateDecls.try_emplace(
7842 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit());
Alexey Bataevb3638132018-07-19 16:34:13 +00007843 // Extract device pointer clause information.
7844 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
7845 for (auto L : C->component_lists())
7846 DevPointersMap[L.first].push_back(L.second);
7847 }
7848
7849 /// Generate code for the combined entry if we have a partially mapped struct
7850 /// and take care of the mapping flags of the arguments corresponding to
7851 /// individual struct members.
7852 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers,
7853 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7854 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes,
7855 const StructRangeInfoTy &PartialStruct) const {
7856 // Base is the base of the struct
7857 BasePointers.push_back(PartialStruct.Base.getPointer());
7858 // Pointer is the address of the lowest element
7859 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer();
7860 Pointers.push_back(LB);
7861 // Size is (addr of {highest+1} element) - (addr of lowest element)
7862 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer();
7863 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1);
7864 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy);
7865 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy);
7866 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00007867 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00007868 /*isSigned=*/false);
Alexey Bataevb3638132018-07-19 16:34:13 +00007869 Sizes.push_back(Size);
7870 // Map type is always TARGET_PARAM
7871 Types.push_back(OMP_MAP_TARGET_PARAM);
7872 // Remove TARGET_PARAM flag from the first element
7873 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM;
7874
7875 // All other current entries will be MEMBER_OF the combined entry
7876 // (except for PTR_AND_OBJ entries which do not have a placeholder value
7877 // 0xFFFF in the MEMBER_OF field).
7878 OpenMPOffloadMappingFlags MemberOfFlag =
7879 getMemberOfFlag(BasePointers.size() - 1);
7880 for (auto &M : CurTypes)
7881 setCorrectMemberOfFlag(M, MemberOfFlag);
7882 }
7883
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007884 /// Generate all the base pointers, section pointers, sizes and map
Samuel Antaocc10b852016-07-28 14:23:26 +00007885 /// types for the extracted mappable expressions. Also, for each item that
7886 /// relates with a device pointer, a pair of the relevant declaration and
7887 /// index where it occurs is appended to the device pointers info array.
7888 void generateAllInfo(MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007889 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7890 MapFlagsArrayTy &Types) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007891 // We have to process the component lists that relate with the same
7892 // declaration in a single chunk so that we can generate the map flags
7893 // correctly. Therefore, we organize all lists in a map.
Alexey Bataev5d1c3f62017-06-27 15:46:42 +00007894 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
Samuel Antao8d2d7302016-05-26 18:30:22 +00007895
7896 // Helper function to fill the information map for the different supported
7897 // clauses.
Samuel Antaocc10b852016-07-28 14:23:26 +00007898 auto &&InfoGen = [&Info](
7899 const ValueDecl *D,
7900 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
Kelvin Lief579432018-12-18 22:18:41 +00007901 OpenMPMapClauseKind MapType,
7902 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007903 bool ReturnDevicePointer, bool IsImplicit) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007904 const ValueDecl *VD =
7905 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
Kelvin Lief579432018-12-18 22:18:41 +00007906 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007907 IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00007908 };
Samuel Antao8d2d7302016-05-26 18:30:22 +00007909
Paul Robinson78fb1322016-08-01 22:12:46 +00007910 // FIXME: MSVC 2013 seems to require this-> to find member CurDir.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007911 for (const auto *C : this->CurDir.getClausesOfKind<OMPMapClause>())
7912 for (const auto &L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007913 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(),
Alexey Bataevb3638132018-07-19 16:34:13 +00007914 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007915 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007916 for (const auto *C : this->CurDir.getClausesOfKind<OMPToClause>())
7917 for (const auto &L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007918 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007919 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007920 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007921 for (const auto *C : this->CurDir.getClausesOfKind<OMPFromClause>())
7922 for (const auto &L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007923 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007924 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007925 }
Samuel Antao86ace552016-04-27 22:40:57 +00007926
Samuel Antaocc10b852016-07-28 14:23:26 +00007927 // Look at the use_device_ptr clause information and mark the existing map
7928 // entries as such. If there is no map information for an entry in the
7929 // use_device_ptr list, we create one with map type 'alloc' and zero size
Alexey Bataevb3638132018-07-19 16:34:13 +00007930 // section. It is the user fault if that was not mapped before. If there is
7931 // no map information and the pointer is a struct member, then we defer the
7932 // emission of that entry until the whole struct has been processed.
7933 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>>
7934 DeferredInfo;
7935
Paul Robinson78fb1322016-08-01 22:12:46 +00007936 // FIXME: MSVC 2013 seems to require this-> to find member CurDir.
Alexey Bataevb3638132018-07-19 16:34:13 +00007937 for (const auto *C :
7938 this->CurDir.getClausesOfKind<OMPUseDevicePtrClause>()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007939 for (const auto &L : C->component_lists()) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007940 assert(!L.second.empty() && "Not expecting empty list of components!");
7941 const ValueDecl *VD = L.second.back().getAssociatedDeclaration();
7942 VD = cast<ValueDecl>(VD->getCanonicalDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007943 const Expr *IE = L.second.back().getAssociatedExpression();
Samuel Antaocc10b852016-07-28 14:23:26 +00007944 // If the first component is a member expression, we have to look into
7945 // 'this', which maps to null in the map of map information. Otherwise
7946 // look directly for the information.
7947 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
7948
7949 // We potentially have map information for this declaration already.
7950 // Look for the first set of components that refer to it.
7951 if (It != Info.end()) {
7952 auto CI = std::find_if(
7953 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) {
7954 return MI.Components.back().getAssociatedDeclaration() == VD;
7955 });
7956 // If we found a map entry, signal that the pointer has to be returned
7957 // and move on to the next declaration.
7958 if (CI != It->second.end()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007959 CI->ReturnDevicePointer = true;
Samuel Antaocc10b852016-07-28 14:23:26 +00007960 continue;
7961 }
7962 }
7963
7964 // We didn't find any match in our map information - generate a zero
Alexey Bataevb3638132018-07-19 16:34:13 +00007965 // size array section - if the pointer is a struct member we defer this
7966 // action until the whole struct has been processed.
Paul Robinson78fb1322016-08-01 22:12:46 +00007967 // FIXME: MSVC 2013 seems to require this-> to find member CGF.
Alexey Bataevb3638132018-07-19 16:34:13 +00007968 if (isa<MemberExpr>(IE)) {
7969 // Insert the pointer into Info to be processed by
7970 // generateInfoForComponentList. Because it is a member pointer
7971 // without a pointee, no entry will be generated for it, therefore
7972 // we need to generate one after the whole struct has been processed.
7973 // Nonetheless, generateInfoForComponentList must be called to take
7974 // the pointer into account for the calculation of the range of the
7975 // partial struct.
Kelvin Lief579432018-12-18 22:18:41 +00007976 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007977 /*ReturnDevicePointer=*/false, C->isImplicit());
7978 DeferredInfo[nullptr].emplace_back(IE, VD);
7979 } else {
7980 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar(
7981 this->CGF.EmitLValue(IE), IE->getExprLoc());
7982 BasePointers.emplace_back(Ptr, VD);
7983 Pointers.push_back(Ptr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00007984 Sizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00007985 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM);
7986 }
Samuel Antaocc10b852016-07-28 14:23:26 +00007987 }
Alexey Bataevb3638132018-07-19 16:34:13 +00007988 }
Samuel Antaocc10b852016-07-28 14:23:26 +00007989
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007990 for (const auto &M : Info) {
Samuel Antao86ace552016-04-27 22:40:57 +00007991 // We need to know when we generate information for the first component
7992 // associated with a capture, because the mapping flags depend on it.
7993 bool IsFirstComponentList = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00007994
7995 // Temporary versions of arrays
7996 MapBaseValuesArrayTy CurBasePointers;
7997 MapValuesArrayTy CurPointers;
7998 MapValuesArrayTy CurSizes;
7999 MapFlagsArrayTy CurTypes;
8000 StructRangeInfoTy PartialStruct;
8001
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008002 for (const MapInfo &L : M.second) {
Samuel Antao86ace552016-04-27 22:40:57 +00008003 assert(!L.Components.empty() &&
8004 "Not expecting declaration with no component lists.");
Samuel Antaocc10b852016-07-28 14:23:26 +00008005
8006 // Remember the current base pointer index.
Alexey Bataevb3638132018-07-19 16:34:13 +00008007 unsigned CurrentBasePointersIdx = CurBasePointers.size();
Paul Robinson78fb1322016-08-01 22:12:46 +00008008 // FIXME: MSVC 2013 seems to require this-> to find the member method.
Alexey Bataevf47c4b42017-09-26 13:47:31 +00008009 this->generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00008010 L.MapType, L.MapModifiers, L.Components, CurBasePointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008011 CurPointers, CurSizes, CurTypes, PartialStruct,
8012 IsFirstComponentList, L.IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00008013
8014 // If this entry relates with a device pointer, set the relevant
8015 // declaration and add the 'return pointer' flag.
Alexey Bataevb3638132018-07-19 16:34:13 +00008016 if (L.ReturnDevicePointer) {
8017 assert(CurBasePointers.size() > CurrentBasePointersIdx &&
Samuel Antaocc10b852016-07-28 14:23:26 +00008018 "Unexpected number of mapped base pointers.");
8019
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008020 const ValueDecl *RelevantVD =
8021 L.Components.back().getAssociatedDeclaration();
Samuel Antaocc10b852016-07-28 14:23:26 +00008022 assert(RelevantVD &&
8023 "No relevant declaration related with device pointer??");
8024
Alexey Bataevb3638132018-07-19 16:34:13 +00008025 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD);
8026 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008027 }
Samuel Antao86ace552016-04-27 22:40:57 +00008028 IsFirstComponentList = false;
8029 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008030
8031 // Append any pending zero-length pointers which are struct members and
8032 // used with use_device_ptr.
8033 auto CI = DeferredInfo.find(M.first);
8034 if (CI != DeferredInfo.end()) {
8035 for (const DeferredDevicePtrEntryTy &L : CI->second) {
8036 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer();
8037 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar(
8038 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc());
8039 CurBasePointers.emplace_back(BasePtr, L.VD);
8040 CurPointers.push_back(Ptr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008041 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00008042 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder
8043 // value MEMBER_OF=FFFF so that the entry is later updated with the
8044 // correct value of MEMBER_OF.
8045 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM |
8046 OMP_MAP_MEMBER_OF);
8047 }
8048 }
8049
8050 // If there is an entry in PartialStruct it means we have a struct with
8051 // individual members mapped. Emit an extra combined entry.
8052 if (PartialStruct.Base.isValid())
8053 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8054 PartialStruct);
8055
8056 // We need to append the results of this capture to what we already have.
8057 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8058 Pointers.append(CurPointers.begin(), CurPointers.end());
8059 Sizes.append(CurSizes.begin(), CurSizes.end());
8060 Types.append(CurTypes.begin(), CurTypes.end());
Samuel Antao86ace552016-04-27 22:40:57 +00008061 }
8062 }
8063
Alexey Bataev60705422018-10-30 15:50:12 +00008064 /// Emit capture info for lambdas for variables captured by reference.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008065 void generateInfoForLambdaCaptures(
8066 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers,
8067 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
8068 MapFlagsArrayTy &Types,
8069 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008070 const auto *RD = VD->getType()
8071 .getCanonicalType()
8072 .getNonReferenceType()
8073 ->getAsCXXRecordDecl();
8074 if (!RD || !RD->isLambda())
8075 return;
8076 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD));
8077 LValue VDLVal = CGF.MakeAddrLValue(
8078 VDAddr, VD->getType().getCanonicalType().getNonReferenceType());
8079 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
8080 FieldDecl *ThisCapture = nullptr;
8081 RD->getCaptureFields(Captures, ThisCapture);
8082 if (ThisCapture) {
8083 LValue ThisLVal =
8084 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture);
Alexey Bataev969dbc02018-11-08 15:47:39 +00008085 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture);
8086 LambdaPointers.try_emplace(ThisLVal.getPointer(), VDLVal.getPointer());
8087 BasePointers.push_back(ThisLVal.getPointer());
8088 Pointers.push_back(ThisLValVal.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00008089 Sizes.push_back(
8090 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8091 CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008092 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008093 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8094 }
8095 for (const LambdaCapture &LC : RD->captures()) {
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008096 if (!LC.capturesVariable())
Alexey Bataev60705422018-10-30 15:50:12 +00008097 continue;
8098 const VarDecl *VD = LC.getCapturedVar();
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008099 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType())
8100 continue;
Alexey Bataev60705422018-10-30 15:50:12 +00008101 auto It = Captures.find(VD);
8102 assert(It != Captures.end() && "Found lambda capture without field.");
8103 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second);
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008104 if (LC.getCaptureKind() == LCK_ByRef) {
8105 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second);
8106 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer());
8107 BasePointers.push_back(VarLVal.getPointer());
8108 Pointers.push_back(VarLValVal.getPointer());
8109 Sizes.push_back(CGF.Builder.CreateIntCast(
8110 CGF.getTypeSize(
8111 VD->getType().getCanonicalType().getNonReferenceType()),
8112 CGF.Int64Ty, /*isSigned=*/true));
8113 } else {
8114 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation());
8115 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer());
8116 BasePointers.push_back(VarLVal.getPointer());
8117 Pointers.push_back(VarRVal.getScalarVal());
8118 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0));
8119 }
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008120 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008121 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8122 }
8123 }
8124
8125 /// Set correct indices for lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008126 void adjustMemberOfForLambdaCaptures(
8127 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
8128 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
8129 MapFlagsArrayTy &Types) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008130 for (unsigned I = 0, E = Types.size(); I < E; ++I) {
8131 // Set correct member_of idx for all implicit lambda captures.
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008132 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008133 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT))
8134 continue;
Alexey Bataev969dbc02018-11-08 15:47:39 +00008135 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]);
8136 assert(BasePtr && "Unable to find base lambda address.");
Alexey Bataev60705422018-10-30 15:50:12 +00008137 int TgtIdx = -1;
8138 for (unsigned J = I; J > 0; --J) {
8139 unsigned Idx = J - 1;
8140 if (Pointers[Idx] != BasePtr)
8141 continue;
8142 TgtIdx = Idx;
8143 break;
8144 }
8145 assert(TgtIdx != -1 && "Unable to find parent lambda.");
8146 // All other current entries will be MEMBER_OF the combined entry
8147 // (except for PTR_AND_OBJ entries which do not have a placeholder value
8148 // 0xFFFF in the MEMBER_OF field).
8149 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx);
8150 setCorrectMemberOfFlag(Types[I], MemberOfFlag);
8151 }
8152 }
8153
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008154 /// Generate the base pointers, section pointers, sizes and map types
Samuel Antao86ace552016-04-27 22:40:57 +00008155 /// associated to a given capture.
8156 void generateInfoForCapture(const CapturedStmt::Capture *Cap,
Samuel Antao6890b092016-07-28 14:25:09 +00008157 llvm::Value *Arg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008158 MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00008159 MapValuesArrayTy &Pointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008160 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
8161 StructRangeInfoTy &PartialStruct) const {
Samuel Antao86ace552016-04-27 22:40:57 +00008162 assert(!Cap->capturesVariableArrayType() &&
8163 "Not expecting to generate map info for a variable array type!");
8164
Samuel Antao6890b092016-07-28 14:25:09 +00008165 // We need to know when we generating information for the first component
Alexey Bataevb3638132018-07-19 16:34:13 +00008166 const ValueDecl *VD = Cap->capturesThis()
8167 ? nullptr
8168 : Cap->getCapturedVar()->getCanonicalDecl();
Samuel Antao86ace552016-04-27 22:40:57 +00008169
Samuel Antao6890b092016-07-28 14:25:09 +00008170 // If this declaration appears in a is_device_ptr clause we just have to
8171 // pass the pointer by value. If it is a reference to a declaration, we just
Alexey Bataevb3638132018-07-19 16:34:13 +00008172 // pass its value.
8173 if (DevPointersMap.count(VD)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008174 BasePointers.emplace_back(Arg, VD);
Samuel Antao6890b092016-07-28 14:25:09 +00008175 Pointers.push_back(Arg);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008176 Sizes.push_back(
8177 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8178 CGF.Int64Ty, /*isSigned=*/true));
George Rokos065755d2017-11-07 18:27:04 +00008179 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM);
Samuel Antao6890b092016-07-28 14:25:09 +00008180 return;
8181 }
8182
Alexey Bataeve82445f2018-09-20 13:54:02 +00008183 using MapData =
8184 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
Kelvin Lief579432018-12-18 22:18:41 +00008185 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008186 SmallVector<MapData, 4> DeclComponentLists;
Paul Robinson78fb1322016-08-01 22:12:46 +00008187 // FIXME: MSVC 2013 seems to require this-> to find member CurDir.
Alexey Bataeve82445f2018-09-20 13:54:02 +00008188 for (const auto *C : this->CurDir.getClausesOfKind<OMPMapClause>()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008189 for (const auto &L : C->decl_component_lists(VD)) {
Samuel Antao86ace552016-04-27 22:40:57 +00008190 assert(L.first == VD &&
8191 "We got information for the wrong declaration??");
8192 assert(!L.second.empty() &&
8193 "Not expecting declaration with no component lists.");
Alexey Bataeve82445f2018-09-20 13:54:02 +00008194 DeclComponentLists.emplace_back(L.second, C->getMapType(),
Kelvin Lief579432018-12-18 22:18:41 +00008195 C->getMapTypeModifiers(),
Alexey Bataeve82445f2018-09-20 13:54:02 +00008196 C->isImplicit());
Samuel Antao86ace552016-04-27 22:40:57 +00008197 }
Alexey Bataeve82445f2018-09-20 13:54:02 +00008198 }
8199
8200 // Find overlapping elements (including the offset from the base element).
8201 llvm::SmallDenseMap<
8202 const MapData *,
8203 llvm::SmallVector<
8204 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>,
8205 4>
8206 OverlappedData;
8207 size_t Count = 0;
8208 for (const MapData &L : DeclComponentLists) {
8209 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8210 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008211 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008212 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008213 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008214 ++Count;
8215 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) {
8216 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1;
Kelvin Lief579432018-12-18 22:18:41 +00008217 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008218 auto CI = Components.rbegin();
8219 auto CE = Components.rend();
8220 auto SI = Components1.rbegin();
8221 auto SE = Components1.rend();
8222 for (; CI != CE && SI != SE; ++CI, ++SI) {
8223 if (CI->getAssociatedExpression()->getStmtClass() !=
8224 SI->getAssociatedExpression()->getStmtClass())
8225 break;
8226 // Are we dealing with different variables/fields?
8227 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
8228 break;
8229 }
8230 // Found overlapping if, at least for one component, reached the head of
8231 // the components list.
8232 if (CI == CE || SI == SE) {
8233 assert((CI != CE || SI != SE) &&
8234 "Unexpected full match of the mapping components.");
8235 const MapData &BaseData = CI == CE ? L : L1;
8236 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData =
8237 SI == SE ? Components : Components1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008238 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData);
8239 OverlappedElements.getSecond().push_back(SubData);
8240 }
8241 }
8242 }
8243 // Sort the overlapped elements for each item.
8244 llvm::SmallVector<const FieldDecl *, 4> Layout;
8245 if (!OverlappedData.empty()) {
8246 if (const auto *CRD =
8247 VD->getType().getCanonicalType()->getAsCXXRecordDecl())
8248 getPlainLayout(CRD, Layout, /*AsBase=*/false);
8249 else {
8250 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl();
8251 Layout.append(RD->field_begin(), RD->field_end());
8252 }
8253 }
8254 for (auto &Pair : OverlappedData) {
8255 llvm::sort(
8256 Pair.getSecond(),
8257 [&Layout](
8258 OMPClauseMappableExprCommon::MappableExprComponentListRef First,
8259 OMPClauseMappableExprCommon::MappableExprComponentListRef
8260 Second) {
8261 auto CI = First.rbegin();
8262 auto CE = First.rend();
8263 auto SI = Second.rbegin();
8264 auto SE = Second.rend();
8265 for (; CI != CE && SI != SE; ++CI, ++SI) {
8266 if (CI->getAssociatedExpression()->getStmtClass() !=
8267 SI->getAssociatedExpression()->getStmtClass())
8268 break;
8269 // Are we dealing with different variables/fields?
8270 if (CI->getAssociatedDeclaration() !=
8271 SI->getAssociatedDeclaration())
8272 break;
8273 }
Richard Trieu5061e832018-09-21 21:20:33 +00008274
8275 // Lists contain the same elements.
8276 if (CI == CE && SI == SE)
8277 return false;
8278
8279 // List with less elements is less than list with more elements.
8280 if (CI == CE || SI == SE)
8281 return CI == CE;
8282
Alexey Bataeve82445f2018-09-20 13:54:02 +00008283 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
8284 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
8285 if (FD1->getParent() == FD2->getParent())
8286 return FD1->getFieldIndex() < FD2->getFieldIndex();
8287 const auto It =
8288 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) {
8289 return FD == FD1 || FD == FD2;
8290 });
8291 return *It == FD1;
8292 });
8293 }
8294
8295 // Associated with a capture, because the mapping flags depend on it.
8296 // Go through all of the elements with the overlapped elements.
8297 for (const auto &Pair : OverlappedData) {
8298 const MapData &L = *Pair.getFirst();
8299 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8300 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008301 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008302 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008303 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008304 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
8305 OverlappedComponents = Pair.getSecond();
8306 bool IsFirstComponentList = true;
Kelvin Lief579432018-12-18 22:18:41 +00008307 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008308 BasePointers, Pointers, Sizes, Types,
8309 PartialStruct, IsFirstComponentList,
8310 IsImplicit, OverlappedComponents);
8311 }
8312 // Go through other elements without overlapped elements.
8313 bool IsFirstComponentList = OverlappedData.empty();
8314 for (const MapData &L : DeclComponentLists) {
8315 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8316 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008317 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008318 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008319 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008320 auto It = OverlappedData.find(&L);
8321 if (It == OverlappedData.end())
Kelvin Lief579432018-12-18 22:18:41 +00008322 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008323 BasePointers, Pointers, Sizes, Types,
8324 PartialStruct, IsFirstComponentList,
8325 IsImplicit);
8326 IsFirstComponentList = false;
8327 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008328 }
Samuel Antao86ace552016-04-27 22:40:57 +00008329
Alexey Bataevb3638132018-07-19 16:34:13 +00008330 /// Generate the base pointers, section pointers, sizes and map types
8331 /// associated with the declare target link variables.
8332 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers,
8333 MapValuesArrayTy &Pointers,
8334 MapValuesArrayTy &Sizes,
8335 MapFlagsArrayTy &Types) const {
8336 // Map other list items in the map clause which are not captured variables
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00008337 // but "declare target link" global variables.
Alexey Bataevb3638132018-07-19 16:34:13 +00008338 for (const auto *C : this->CurDir.getClausesOfKind<OMPMapClause>()) {
8339 for (const auto &L : C->component_lists()) {
8340 if (!L.first)
8341 continue;
8342 const auto *VD = dyn_cast<VarDecl>(L.first);
8343 if (!VD)
8344 continue;
8345 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00008346 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00008347 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
8348 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)
Alexey Bataevb3638132018-07-19 16:34:13 +00008349 continue;
8350 StructRangeInfoTy PartialStruct;
8351 generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00008352 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008353 Pointers, Sizes, Types, PartialStruct,
8354 /*IsFirstComponentList=*/true, C->isImplicit());
8355 assert(!PartialStruct.Base.isValid() &&
8356 "No partial structs for declare target link expected.");
8357 }
8358 }
Samuel Antao86ace552016-04-27 22:40:57 +00008359 }
Samuel Antaod486f842016-05-26 16:53:38 +00008360
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008361 /// Generate the default map information for a given capture \a CI,
Samuel Antaod486f842016-05-26 16:53:38 +00008362 /// record field declaration \a RI and captured value \a CV.
Samuel Antaocc10b852016-07-28 14:23:26 +00008363 void generateDefaultMapInfo(const CapturedStmt::Capture &CI,
8364 const FieldDecl &RI, llvm::Value *CV,
8365 MapBaseValuesArrayTy &CurBasePointers,
8366 MapValuesArrayTy &CurPointers,
8367 MapValuesArrayTy &CurSizes,
Alexey Bataevb3638132018-07-19 16:34:13 +00008368 MapFlagsArrayTy &CurMapTypes) const {
Alexey Bataevf288cf92019-06-27 18:53:07 +00008369 bool IsImplicit = true;
Samuel Antaod486f842016-05-26 16:53:38 +00008370 // Do the default mapping.
8371 if (CI.capturesThis()) {
8372 CurBasePointers.push_back(CV);
8373 CurPointers.push_back(CV);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008374 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr());
Alexey Bataeva90fc662019-06-25 16:00:43 +00008375 CurSizes.push_back(
8376 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()),
8377 CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008378 // Default map type.
Samuel Antaocc10b852016-07-28 14:23:26 +00008379 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM);
Samuel Antaod486f842016-05-26 16:53:38 +00008380 } else if (CI.capturesVariableByCopy()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008381 CurBasePointers.push_back(CV);
8382 CurPointers.push_back(CV);
Samuel Antaod486f842016-05-26 16:53:38 +00008383 if (!RI.getType()->isAnyPointerType()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008384 // We have to signal to the runtime captures passed by value that are
8385 // not pointers.
George Rokos065755d2017-11-07 18:27:04 +00008386 CurMapTypes.push_back(OMP_MAP_LITERAL);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008387 CurSizes.push_back(CGF.Builder.CreateIntCast(
8388 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008389 } else {
8390 // Pointers are implicitly mapped with a zero size and no flags
8391 // (other than first map that is added for all implicit maps).
Alexey Bataevb3638132018-07-19 16:34:13 +00008392 CurMapTypes.push_back(OMP_MAP_NONE);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008393 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
Samuel Antaod486f842016-05-26 16:53:38 +00008394 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008395 const VarDecl *VD = CI.getCapturedVar();
8396 auto I = FirstPrivateDecls.find(VD);
8397 if (I != FirstPrivateDecls.end())
8398 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008399 } else {
8400 assert(CI.capturesVariable() && "Expected captured reference.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008401 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr());
Samuel Antaod486f842016-05-26 16:53:38 +00008402 QualType ElementType = PtrTy->getPointeeType();
Alexey Bataeva90fc662019-06-25 16:00:43 +00008403 CurSizes.push_back(CGF.Builder.CreateIntCast(
8404 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008405 // The default map type for a scalar/complex type is 'to' because by
8406 // default the value doesn't have to be retrieved. For an aggregate
8407 // type, the default is 'tofrom'.
Alexey Bataevb3638132018-07-19 16:34:13 +00008408 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI));
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008409 const VarDecl *VD = CI.getCapturedVar();
Alexey Bataevf288cf92019-06-27 18:53:07 +00008410 auto I = FirstPrivateDecls.find(VD);
8411 if (I != FirstPrivateDecls.end() &&
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008412 VD->getType().isConstant(CGF.getContext())) {
8413 llvm::Constant *Addr =
8414 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD);
8415 // Copy the value of the original variable to the new global copy.
8416 CGF.Builder.CreateMemCpy(
8417 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(),
8418 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)),
Rui Ueyama49a3ad22019-07-16 04:46:31 +00008419 CurSizes.back(), /*IsVolatile=*/false);
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008420 // Use new global variable as the base pointers.
8421 CurBasePointers.push_back(Addr);
8422 CurPointers.push_back(Addr);
8423 } else {
8424 CurBasePointers.push_back(CV);
Alexey Bataevf288cf92019-06-27 18:53:07 +00008425 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) {
Alexey Bataevc2b831f2019-04-02 16:03:40 +00008426 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue(
8427 CV, ElementType, CGF.getContext().getDeclAlign(VD),
8428 AlignmentSource::Decl));
8429 CurPointers.push_back(PtrAddr.getPointer());
8430 } else {
8431 CurPointers.push_back(CV);
8432 }
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008433 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008434 if (I != FirstPrivateDecls.end())
8435 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008436 }
George Rokos065755d2017-11-07 18:27:04 +00008437 // Every default map produces a single argument which is a target parameter.
8438 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM;
Alexey Bataevb3638132018-07-19 16:34:13 +00008439
8440 // Add flag stating this is an implicit map.
Alexey Bataevf288cf92019-06-27 18:53:07 +00008441 if (IsImplicit)
8442 CurMapTypes.back() |= OMP_MAP_IMPLICIT;
Samuel Antaod486f842016-05-26 16:53:38 +00008443 }
Samuel Antao86ace552016-04-27 22:40:57 +00008444};
Samuel Antaodf158d52016-04-27 22:58:19 +00008445} // anonymous namespace
8446
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008447/// Emit the arrays used to pass the captures and map information to the
Samuel Antaodf158d52016-04-27 22:58:19 +00008448/// offloading runtime library. If there is no map or capture information,
8449/// return nullptr by reference.
8450static void
Samuel Antaocc10b852016-07-28 14:23:26 +00008451emitOffloadingArrays(CodeGenFunction &CGF,
8452 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers,
Samuel Antaodf158d52016-04-27 22:58:19 +00008453 MappableExprsHandler::MapValuesArrayTy &Pointers,
8454 MappableExprsHandler::MapValuesArrayTy &Sizes,
Samuel Antaocc10b852016-07-28 14:23:26 +00008455 MappableExprsHandler::MapFlagsArrayTy &MapTypes,
8456 CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008457 CodeGenModule &CGM = CGF.CGM;
8458 ASTContext &Ctx = CGF.getContext();
Samuel Antaodf158d52016-04-27 22:58:19 +00008459
Samuel Antaocc10b852016-07-28 14:23:26 +00008460 // Reset the array information.
8461 Info.clearArrayInfo();
8462 Info.NumberOfPtrs = BasePointers.size();
Samuel Antaodf158d52016-04-27 22:58:19 +00008463
Samuel Antaocc10b852016-07-28 14:23:26 +00008464 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008465 // Detect if we have any capture size requiring runtime evaluation of the
8466 // size so that a constant array could be eventually used.
8467 bool hasRuntimeEvaluationCaptureSize = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008468 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008469 if (!isa<llvm::Constant>(S)) {
8470 hasRuntimeEvaluationCaptureSize = true;
8471 break;
8472 }
8473
Samuel Antaocc10b852016-07-28 14:23:26 +00008474 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true);
Samuel Antaodf158d52016-04-27 22:58:19 +00008475 QualType PointerArrayType =
8476 Ctx.getConstantArrayType(Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal,
8477 /*IndexTypeQuals=*/0);
8478
Samuel Antaocc10b852016-07-28 14:23:26 +00008479 Info.BasePointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008480 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
Samuel Antaocc10b852016-07-28 14:23:26 +00008481 Info.PointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008482 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
8483
8484 // If we don't have any VLA types or other types that require runtime
8485 // evaluation, we can use a constant array for the map sizes, otherwise we
8486 // need to fill up the arrays as we do for the pointers.
Alexey Bataeva90fc662019-06-25 16:00:43 +00008487 QualType Int64Ty =
8488 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Samuel Antaodf158d52016-04-27 22:58:19 +00008489 if (hasRuntimeEvaluationCaptureSize) {
Alexey Bataeva90fc662019-06-25 16:00:43 +00008490 QualType SizeArrayType =
8491 Ctx.getConstantArrayType(Int64Ty, PointerNumAP, ArrayType::Normal,
8492 /*IndexTypeQuals=*/0);
Samuel Antaocc10b852016-07-28 14:23:26 +00008493 Info.SizesArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008494 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
8495 } else {
8496 // We expect all the sizes to be constant, so we collect them to create
8497 // a constant array.
8498 SmallVector<llvm::Constant *, 16> ConstSizes;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008499 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008500 ConstSizes.push_back(cast<llvm::Constant>(S));
8501
8502 auto *SizesArrayInit = llvm::ConstantArray::get(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008503 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008504 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008505 auto *SizesArrayGbl = new llvm::GlobalVariable(
8506 CGM.getModule(), SizesArrayInit->getType(),
8507 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008508 SizesArrayInit, Name);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008509 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008510 Info.SizesArray = SizesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008511 }
8512
8513 // The map types are always constant so we don't need to generate code to
8514 // fill arrays. Instead, we create an array constant.
Alexey Bataevb3638132018-07-19 16:34:13 +00008515 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0);
8516 llvm::copy(MapTypes, Mapping.begin());
Samuel Antaodf158d52016-04-27 22:58:19 +00008517 llvm::Constant *MapTypesArrayInit =
Alexey Bataevb3638132018-07-19 16:34:13 +00008518 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008519 std::string MaptypesName =
8520 CGM.getOpenMPRuntime().getName({"offload_maptypes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008521 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
8522 CGM.getModule(), MapTypesArrayInit->getType(),
8523 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008524 MapTypesArrayInit, MaptypesName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008525 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008526 Info.MapTypesArray = MapTypesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008527
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008528 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) {
8529 llvm::Value *BPVal = *BasePointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008530 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008531 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008532 Info.BasePointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008533 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8534 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008535 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8536 CGF.Builder.CreateStore(BPVal, BPAddr);
8537
Samuel Antaocc10b852016-07-28 14:23:26 +00008538 if (Info.requiresDevicePointerInfo())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008539 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl())
Alexey Bataev43a919f2018-04-13 17:48:43 +00008540 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr);
Samuel Antaocc10b852016-07-28 14:23:26 +00008541
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008542 llvm::Value *PVal = Pointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008543 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008544 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008545 Info.PointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008546 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8547 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008548 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8549 CGF.Builder.CreateStore(PVal, PAddr);
8550
8551 if (hasRuntimeEvaluationCaptureSize) {
8552 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008553 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008554 Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008555 /*Idx0=*/0,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008556 /*Idx1=*/I);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008557 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty));
Samuel Antaodf158d52016-04-27 22:58:19 +00008558 CGF.Builder.CreateStore(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008559 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true),
Samuel Antaodf158d52016-04-27 22:58:19 +00008560 SAddr);
8561 }
8562 }
8563 }
8564}
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008565/// Emit the arguments to be passed to the runtime library based on the
Samuel Antaodf158d52016-04-27 22:58:19 +00008566/// arrays of pointers, sizes and map types.
8567static void emitOffloadingArraysArgument(
8568 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg,
8569 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008570 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008571 CodeGenModule &CGM = CGF.CGM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008572 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008573 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008574 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8575 Info.BasePointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008576 /*Idx0=*/0, /*Idx1=*/0);
8577 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008578 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8579 Info.PointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008580 /*Idx0=*/0,
8581 /*Idx1=*/0);
8582 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008583 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008584 /*Idx0=*/0, /*Idx1=*/0);
8585 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
George Rokos63bc9d62017-11-21 18:25:12 +00008586 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008587 Info.MapTypesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008588 /*Idx0=*/0,
8589 /*Idx1=*/0);
8590 } else {
8591 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
8592 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008593 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008594 MapTypesArrayArg =
George Rokos63bc9d62017-11-21 18:25:12 +00008595 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008596 }
Samuel Antao86ace552016-04-27 22:40:57 +00008597}
8598
Alexey Bataev7bb33532019-01-07 21:30:43 +00008599/// Check for inner distribute directive.
8600static const OMPExecutableDirective *
8601getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
8602 const auto *CS = D.getInnermostCapturedStmt();
8603 const auto *Body =
8604 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00008605 const Stmt *ChildStmt =
8606 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
Alexey Bataev7bb33532019-01-07 21:30:43 +00008607
Alexey Bataev5c427362019-04-10 19:11:33 +00008608 if (const auto *NestedDir =
8609 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008610 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind();
8611 switch (D.getDirectiveKind()) {
8612 case OMPD_target:
8613 if (isOpenMPDistributeDirective(DKind))
8614 return NestedDir;
8615 if (DKind == OMPD_teams) {
8616 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
8617 /*IgnoreCaptured=*/true);
8618 if (!Body)
8619 return nullptr;
Alexey Bataev5c427362019-04-10 19:11:33 +00008620 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
8621 if (const auto *NND =
8622 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008623 DKind = NND->getDirectiveKind();
8624 if (isOpenMPDistributeDirective(DKind))
8625 return NND;
8626 }
8627 }
8628 return nullptr;
8629 case OMPD_target_teams:
8630 if (isOpenMPDistributeDirective(DKind))
8631 return NestedDir;
8632 return nullptr;
8633 case OMPD_target_parallel:
8634 case OMPD_target_simd:
8635 case OMPD_target_parallel_for:
8636 case OMPD_target_parallel_for_simd:
8637 return nullptr;
8638 case OMPD_target_teams_distribute:
8639 case OMPD_target_teams_distribute_simd:
8640 case OMPD_target_teams_distribute_parallel_for:
8641 case OMPD_target_teams_distribute_parallel_for_simd:
8642 case OMPD_parallel:
8643 case OMPD_for:
8644 case OMPD_parallel_for:
8645 case OMPD_parallel_sections:
8646 case OMPD_for_simd:
8647 case OMPD_parallel_for_simd:
8648 case OMPD_cancel:
8649 case OMPD_cancellation_point:
8650 case OMPD_ordered:
8651 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00008652 case OMPD_allocate:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008653 case OMPD_task:
8654 case OMPD_simd:
8655 case OMPD_sections:
8656 case OMPD_section:
8657 case OMPD_single:
8658 case OMPD_master:
8659 case OMPD_critical:
8660 case OMPD_taskyield:
8661 case OMPD_barrier:
8662 case OMPD_taskwait:
8663 case OMPD_taskgroup:
8664 case OMPD_atomic:
8665 case OMPD_flush:
8666 case OMPD_teams:
8667 case OMPD_target_data:
8668 case OMPD_target_exit_data:
8669 case OMPD_target_enter_data:
8670 case OMPD_distribute:
8671 case OMPD_distribute_simd:
8672 case OMPD_distribute_parallel_for:
8673 case OMPD_distribute_parallel_for_simd:
8674 case OMPD_teams_distribute:
8675 case OMPD_teams_distribute_simd:
8676 case OMPD_teams_distribute_parallel_for:
8677 case OMPD_teams_distribute_parallel_for_simd:
8678 case OMPD_target_update:
8679 case OMPD_declare_simd:
8680 case OMPD_declare_target:
8681 case OMPD_end_declare_target:
8682 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00008683 case OMPD_declare_mapper:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008684 case OMPD_taskloop:
8685 case OMPD_taskloop_simd:
8686 case OMPD_requires:
8687 case OMPD_unknown:
8688 llvm_unreachable("Unexpected directive.");
8689 }
8690 }
8691
8692 return nullptr;
8693}
8694
8695void CGOpenMPRuntime::emitTargetNumIterationsCall(
8696 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *Device,
8697 const llvm::function_ref<llvm::Value *(
8698 CodeGenFunction &CGF, const OMPLoopDirective &D)> &SizeEmitter) {
8699 OpenMPDirectiveKind Kind = D.getDirectiveKind();
8700 const OMPExecutableDirective *TD = &D;
8701 // Get nested teams distribute kind directive, if any.
8702 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind))
8703 TD = getNestedDistributeDirective(CGM.getContext(), D);
8704 if (!TD)
8705 return;
8706 const auto *LD = cast<OMPLoopDirective>(TD);
8707 auto &&CodeGen = [LD, &Device, &SizeEmitter, this](CodeGenFunction &CGF,
8708 PrePostActionTy &) {
8709 llvm::Value *NumIterations = SizeEmitter(CGF, *LD);
8710
8711 // Emit device ID if any.
8712 llvm::Value *DeviceID;
8713 if (Device)
8714 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
8715 CGF.Int64Ty, /*isSigned=*/true);
8716 else
8717 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
8718
8719 llvm::Value *Args[] = {DeviceID, NumIterations};
8720 CGF.EmitRuntimeCall(
8721 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args);
8722 };
8723 emitInlinedDirective(CGF, OMPD_unknown, CodeGen);
8724}
8725
Samuel Antaobed3c462015-10-02 16:14:20 +00008726void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
8727 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00008728 llvm::Function *OutlinedFn,
Samuel Antaoee8fb302016-01-06 13:42:12 +00008729 llvm::Value *OutlinedFnID,
Alexey Bataev8451efa2018-01-15 19:06:12 +00008730 const Expr *IfCond, const Expr *Device) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00008731 if (!CGF.HaveInsertPoint())
8732 return;
Samuel Antaobed3c462015-10-02 16:14:20 +00008733
Samuel Antaoee8fb302016-01-06 13:42:12 +00008734 assert(OutlinedFn && "Invalid outlined function!");
8735
Alexey Bataev8451efa2018-01-15 19:06:12 +00008736 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>();
8737 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
Alexey Bataev475a7442018-01-12 19:39:11 +00008738 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Alexey Bataev8451efa2018-01-15 19:06:12 +00008739 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF,
8740 PrePostActionTy &) {
8741 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
8742 };
8743 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen);
Samuel Antao86ace552016-04-27 22:40:57 +00008744
Alexey Bataev8451efa2018-01-15 19:06:12 +00008745 CodeGenFunction::OMPTargetDataInfo InputInfo;
8746 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobed3c462015-10-02 16:14:20 +00008747 // Fill up the pointer arrays and transfer execution to the device.
Alexey Bataev8451efa2018-01-15 19:06:12 +00008748 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo,
8749 &MapTypesArray, &CS, RequiresOuterTask,
8750 &CapturedVars](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobed3c462015-10-02 16:14:20 +00008751 // On top of the arrays that were filled up, the target offloading call
8752 // takes as arguments the device id as well as the host pointer. The host
8753 // pointer is used by the runtime library to identify the current target
8754 // region, so it only has to be unique and not necessarily point to
8755 // anything. It could be the pointer to the outlined function that
8756 // implements the target region, but we aren't using that so that the
8757 // compiler doesn't need to keep that, and could therefore inline the host
8758 // function if proven worthwhile during optimization.
8759
Samuel Antaoee8fb302016-01-06 13:42:12 +00008760 // From this point on, we need to have an ID of the target region defined.
8761 assert(OutlinedFnID && "Invalid outlined function ID!");
Samuel Antaobed3c462015-10-02 16:14:20 +00008762
8763 // Emit device ID if any.
8764 llvm::Value *DeviceID;
George Rokos63bc9d62017-11-21 18:25:12 +00008765 if (Device) {
Samuel Antaobed3c462015-10-02 16:14:20 +00008766 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00008767 CGF.Int64Ty, /*isSigned=*/true);
8768 } else {
8769 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
8770 }
Samuel Antaobed3c462015-10-02 16:14:20 +00008771
Samuel Antaodf158d52016-04-27 22:58:19 +00008772 // Emit the number of elements in the offloading arrays.
Alexey Bataev8451efa2018-01-15 19:06:12 +00008773 llvm::Value *PointerNum =
8774 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaodf158d52016-04-27 22:58:19 +00008775
Samuel Antaob68e2db2016-03-03 16:20:23 +00008776 // Return value of the runtime offloading call.
8777 llvm::Value *Return;
8778
Alexey Bataev5c427362019-04-10 19:11:33 +00008779 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D);
8780 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D);
Samuel Antaob68e2db2016-03-03 16:20:23 +00008781
Alexey Bataeva9f77c62017-12-13 21:04:20 +00008782 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00008783 // The target region is an outlined function launched by the runtime
8784 // via calls __tgt_target() or __tgt_target_teams().
8785 //
8786 // __tgt_target() launches a target region with one team and one thread,
8787 // executing a serial region. This master thread may in turn launch
8788 // more threads within its team upon encountering a parallel region,
8789 // however, no additional teams can be launched on the device.
8790 //
8791 // __tgt_target_teams() launches a target region with one or more teams,
8792 // each with one or more threads. This call is required for target
8793 // constructs such as:
8794 // 'target teams'
8795 // 'target' / 'teams'
8796 // 'target teams distribute parallel for'
8797 // 'target parallel'
8798 // and so on.
8799 //
8800 // Note that on the host and CPU targets, the runtime implementation of
8801 // these calls simply call the outlined function without forking threads.
8802 // The outlined functions themselves have runtime calls to
8803 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by
8804 // the compiler in emitTeamsCall() and emitParallelCall().
8805 //
8806 // In contrast, on the NVPTX target, the implementation of
8807 // __tgt_target_teams() launches a GPU kernel with the requested number
8808 // of teams and threads so no additional calls to the runtime are required.
Samuel Antaob68e2db2016-03-03 16:20:23 +00008809 if (NumTeams) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00008810 // If we have NumTeams defined this means that we have an enclosed teams
8811 // region. Therefore we also expect to have NumThreads defined. These two
8812 // values should be defined in the presence of a teams directive,
8813 // regardless of having any clauses associated. If the user is using teams
8814 // but no clauses, these two values will be the default that should be
8815 // passed to the runtime library - a 32-bit integer with the value zero.
8816 assert(NumThreads && "Thread limit expression should be available along "
8817 "with number of teams.");
Alexey Bataev8451efa2018-01-15 19:06:12 +00008818 llvm::Value *OffloadingArgs[] = {DeviceID,
8819 OutlinedFnID,
8820 PointerNum,
8821 InputInfo.BasePointersArray.getPointer(),
8822 InputInfo.PointersArray.getPointer(),
8823 InputInfo.SizesArray.getPointer(),
8824 MapTypesArray,
8825 NumTeams,
8826 NumThreads};
Samuel Antaob68e2db2016-03-03 16:20:23 +00008827 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00008828 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait
8829 : OMPRTL__tgt_target_teams),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00008830 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00008831 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00008832 llvm::Value *OffloadingArgs[] = {DeviceID,
8833 OutlinedFnID,
8834 PointerNum,
8835 InputInfo.BasePointersArray.getPointer(),
8836 InputInfo.PointersArray.getPointer(),
8837 InputInfo.SizesArray.getPointer(),
8838 MapTypesArray};
Alexey Bataeva9f77c62017-12-13 21:04:20 +00008839 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00008840 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait
8841 : OMPRTL__tgt_target),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00008842 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00008843 }
Samuel Antaobed3c462015-10-02 16:14:20 +00008844
Alexey Bataev2a007e02017-10-02 14:20:58 +00008845 // Check the error code and execute the host version if required.
8846 llvm::BasicBlock *OffloadFailedBlock =
8847 CGF.createBasicBlock("omp_offload.failed");
8848 llvm::BasicBlock *OffloadContBlock =
8849 CGF.createBasicBlock("omp_offload.cont");
8850 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return);
8851 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
8852
8853 CGF.EmitBlock(OffloadFailedBlock);
Alexey Bataev8451efa2018-01-15 19:06:12 +00008854 if (RequiresOuterTask) {
8855 CapturedVars.clear();
8856 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
8857 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00008858 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev2a007e02017-10-02 14:20:58 +00008859 CGF.EmitBranch(OffloadContBlock);
8860
8861 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00008862 };
8863
Samuel Antaoee8fb302016-01-06 13:42:12 +00008864 // Notify that the host version must be executed.
Alexey Bataev8451efa2018-01-15 19:06:12 +00008865 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars,
8866 RequiresOuterTask](CodeGenFunction &CGF,
8867 PrePostActionTy &) {
8868 if (RequiresOuterTask) {
8869 CapturedVars.clear();
8870 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
8871 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00008872 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev8451efa2018-01-15 19:06:12 +00008873 };
8874
8875 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray,
8876 &CapturedVars, RequiresOuterTask,
8877 &CS](CodeGenFunction &CGF, PrePostActionTy &) {
8878 // Fill up the arrays with all the captured variables.
8879 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
8880 MappableExprsHandler::MapValuesArrayTy Pointers;
8881 MappableExprsHandler::MapValuesArrayTy Sizes;
8882 MappableExprsHandler::MapFlagsArrayTy MapTypes;
8883
Alexey Bataev8451efa2018-01-15 19:06:12 +00008884 // Get mappable expression information.
8885 MappableExprsHandler MEHandler(D, CGF);
Alexey Bataev969dbc02018-11-08 15:47:39 +00008886 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
Alexey Bataev8451efa2018-01-15 19:06:12 +00008887
8888 auto RI = CS.getCapturedRecordDecl()->field_begin();
8889 auto CV = CapturedVars.begin();
8890 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
8891 CE = CS.capture_end();
8892 CI != CE; ++CI, ++RI, ++CV) {
Alexey Bataevb3638132018-07-19 16:34:13 +00008893 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers;
8894 MappableExprsHandler::MapValuesArrayTy CurPointers;
8895 MappableExprsHandler::MapValuesArrayTy CurSizes;
8896 MappableExprsHandler::MapFlagsArrayTy CurMapTypes;
8897 MappableExprsHandler::StructRangeInfoTy PartialStruct;
Alexey Bataev8451efa2018-01-15 19:06:12 +00008898
8899 // VLA sizes are passed to the outlined region by copy and do not have map
8900 // information associated.
8901 if (CI->capturesVariableArrayType()) {
8902 CurBasePointers.push_back(*CV);
8903 CurPointers.push_back(*CV);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008904 CurSizes.push_back(CGF.Builder.CreateIntCast(
8905 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev8451efa2018-01-15 19:06:12 +00008906 // Copy to the device as an argument. No need to retrieve it.
8907 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL |
Alexey Bataevf288cf92019-06-27 18:53:07 +00008908 MappableExprsHandler::OMP_MAP_TARGET_PARAM |
8909 MappableExprsHandler::OMP_MAP_IMPLICIT);
Alexey Bataev8451efa2018-01-15 19:06:12 +00008910 } else {
8911 // If we have any information in the map clause, we use it, otherwise we
8912 // just do a default mapping.
8913 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008914 CurSizes, CurMapTypes, PartialStruct);
Alexey Bataev8451efa2018-01-15 19:06:12 +00008915 if (CurBasePointers.empty())
8916 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers,
8917 CurPointers, CurSizes, CurMapTypes);
Alexey Bataev60705422018-10-30 15:50:12 +00008918 // Generate correct mapping for variables captured by reference in
8919 // lambdas.
8920 if (CI->capturesVariable())
Alexey Bataev969dbc02018-11-08 15:47:39 +00008921 MEHandler.generateInfoForLambdaCaptures(
8922 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes,
8923 CurMapTypes, LambdaPointers);
Alexey Bataev8451efa2018-01-15 19:06:12 +00008924 }
8925 // We expect to have at least an element of information for this capture.
8926 assert(!CurBasePointers.empty() &&
8927 "Non-existing map pointer for capture!");
8928 assert(CurBasePointers.size() == CurPointers.size() &&
8929 CurBasePointers.size() == CurSizes.size() &&
8930 CurBasePointers.size() == CurMapTypes.size() &&
8931 "Inconsistent map information sizes!");
8932
Alexey Bataevb3638132018-07-19 16:34:13 +00008933 // If there is an entry in PartialStruct it means we have a struct with
8934 // individual members mapped. Emit an extra combined entry.
8935 if (PartialStruct.Base.isValid())
8936 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes,
8937 CurMapTypes, PartialStruct);
8938
Alexey Bataev8451efa2018-01-15 19:06:12 +00008939 // We need to append the results of this capture to what we already have.
8940 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8941 Pointers.append(CurPointers.begin(), CurPointers.end());
8942 Sizes.append(CurSizes.begin(), CurSizes.end());
8943 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end());
8944 }
Alexey Bataev60705422018-10-30 15:50:12 +00008945 // Adjust MEMBER_OF flags for the lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008946 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers,
8947 Pointers, MapTypes);
Alexey Bataev92327c52018-03-26 16:40:55 +00008948 // Map other list items in the map clause which are not captured variables
8949 // but "declare target link" global variables.
Alexey Bataevb3638132018-07-19 16:34:13 +00008950 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes,
8951 MapTypes);
Alexey Bataev8451efa2018-01-15 19:06:12 +00008952
8953 TargetDataInfo Info;
8954 // Fill up the arrays and create the arguments.
8955 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
8956 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
8957 Info.PointersArray, Info.SizesArray,
8958 Info.MapTypesArray, Info);
8959 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
8960 InputInfo.BasePointersArray =
8961 Address(Info.BasePointersArray, CGM.getPointerAlign());
8962 InputInfo.PointersArray =
8963 Address(Info.PointersArray, CGM.getPointerAlign());
8964 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign());
8965 MapTypesArray = Info.MapTypesArray;
8966 if (RequiresOuterTask)
8967 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
8968 else
8969 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
8970 };
8971
8972 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask](
8973 CodeGenFunction &CGF, PrePostActionTy &) {
8974 if (RequiresOuterTask) {
8975 CodeGenFunction::OMPTargetDataInfo InputInfo;
8976 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo);
8977 } else {
8978 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen);
8979 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00008980 };
8981
8982 // If we have a target function ID it means that we need to support
8983 // offloading, otherwise, just execute on the host. We need to execute on host
8984 // regardless of the conditional in the if clause if, e.g., the user do not
8985 // specify target triples.
8986 if (OutlinedFnID) {
Alexey Bataev8451efa2018-01-15 19:06:12 +00008987 if (IfCond) {
8988 emitOMPIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
8989 } else {
8990 RegionCodeGenTy ThenRCG(TargetThenGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00008991 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00008992 }
8993 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00008994 RegionCodeGenTy ElseRCG(TargetElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00008995 ElseRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00008996 }
Samuel Antaobed3c462015-10-02 16:14:20 +00008997}
Samuel Antaoee8fb302016-01-06 13:42:12 +00008998
8999void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
9000 StringRef ParentName) {
9001 if (!S)
9002 return;
9003
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009004 // Codegen OMP target directives that offload compute to the device.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009005 bool RequiresDeviceCodegen =
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009006 isa<OMPExecutableDirective>(S) &&
9007 isOpenMPTargetExecutionDirective(
9008 cast<OMPExecutableDirective>(S)->getDirectiveKind());
Samuel Antaoee8fb302016-01-06 13:42:12 +00009009
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009010 if (RequiresDeviceCodegen) {
9011 const auto &E = *cast<OMPExecutableDirective>(S);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009012 unsigned DeviceID;
9013 unsigned FileID;
9014 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009015 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID,
Samuel Antao2de62b02016-02-13 23:35:10 +00009016 FileID, Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009017
9018 // Is this a target region that should not be emitted as an entry point? If
9019 // so just signal we are done with this target region.
Samuel Antao2de62b02016-02-13 23:35:10 +00009020 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
9021 ParentName, Line))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009022 return;
9023
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009024 switch (E.getDirectiveKind()) {
9025 case OMPD_target:
9026 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName,
9027 cast<OMPTargetDirective>(E));
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009028 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009029 case OMPD_target_parallel:
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009030 CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009031 CGM, ParentName, cast<OMPTargetParallelDirective>(E));
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009032 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009033 case OMPD_target_teams:
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009034 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009035 CGM, ParentName, cast<OMPTargetTeamsDirective>(E));
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009036 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009037 case OMPD_target_teams_distribute:
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009038 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009039 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E));
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009040 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009041 case OMPD_target_teams_distribute_simd:
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009042 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009043 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E));
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009044 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009045 case OMPD_target_parallel_for:
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009046 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009047 CGM, ParentName, cast<OMPTargetParallelForDirective>(E));
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009048 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009049 case OMPD_target_parallel_for_simd:
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009050 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009051 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E));
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009052 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009053 case OMPD_target_simd:
Alexey Bataevf8365372017-11-17 17:57:25 +00009054 CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009055 CGM, ParentName, cast<OMPTargetSimdDirective>(E));
Alexey Bataevf8365372017-11-17 17:57:25 +00009056 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009057 case OMPD_target_teams_distribute_parallel_for:
Carlo Bertolli52978c32018-01-03 21:12:44 +00009058 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
9059 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009060 cast<OMPTargetTeamsDistributeParallelForDirective>(E));
Carlo Bertolli52978c32018-01-03 21:12:44 +00009061 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009062 case OMPD_target_teams_distribute_parallel_for_simd:
Alexey Bataev647dd842018-01-15 20:59:40 +00009063 CodeGenFunction::
9064 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
9065 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009066 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E));
Alexey Bataev647dd842018-01-15 20:59:40 +00009067 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009068 case OMPD_parallel:
9069 case OMPD_for:
9070 case OMPD_parallel_for:
9071 case OMPD_parallel_sections:
9072 case OMPD_for_simd:
9073 case OMPD_parallel_for_simd:
9074 case OMPD_cancel:
9075 case OMPD_cancellation_point:
9076 case OMPD_ordered:
9077 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00009078 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009079 case OMPD_task:
9080 case OMPD_simd:
9081 case OMPD_sections:
9082 case OMPD_section:
9083 case OMPD_single:
9084 case OMPD_master:
9085 case OMPD_critical:
9086 case OMPD_taskyield:
9087 case OMPD_barrier:
9088 case OMPD_taskwait:
9089 case OMPD_taskgroup:
9090 case OMPD_atomic:
9091 case OMPD_flush:
9092 case OMPD_teams:
9093 case OMPD_target_data:
9094 case OMPD_target_exit_data:
9095 case OMPD_target_enter_data:
9096 case OMPD_distribute:
9097 case OMPD_distribute_simd:
9098 case OMPD_distribute_parallel_for:
9099 case OMPD_distribute_parallel_for_simd:
9100 case OMPD_teams_distribute:
9101 case OMPD_teams_distribute_simd:
9102 case OMPD_teams_distribute_parallel_for:
9103 case OMPD_teams_distribute_parallel_for_simd:
9104 case OMPD_target_update:
9105 case OMPD_declare_simd:
9106 case OMPD_declare_target:
9107 case OMPD_end_declare_target:
9108 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00009109 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009110 case OMPD_taskloop:
9111 case OMPD_taskloop_simd:
Kelvin Li1408f912018-09-26 04:28:39 +00009112 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009113 case OMPD_unknown:
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009114 llvm_unreachable("Unknown target directive for OpenMP device codegen.");
9115 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009116 return;
9117 }
9118
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009119 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
Alexey Bataev475a7442018-01-12 19:39:11 +00009120 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009121 return;
9122
9123 scanForTargetRegionsFunctions(
Alexey Bataev475a7442018-01-12 19:39:11 +00009124 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009125 return;
9126 }
9127
9128 // If this is a lambda function, look into its body.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009129 if (const auto *L = dyn_cast<LambdaExpr>(S))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009130 S = L->getBody();
9131
9132 // Keep looking for target regions recursively.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009133 for (const Stmt *II : S->children())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009134 scanForTargetRegionsFunctions(II, ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009135}
9136
9137bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009138 // If emitting code for the host, we do not process FD here. Instead we do
9139 // the normal code generation.
9140 if (!CGM.getLangOpts().OpenMPIsDevice)
9141 return false;
9142
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009143 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009144 StringRef Name = CGM.getMangledName(GD);
9145 // Try to detect target regions in the function.
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009146 if (const auto *FD = dyn_cast<FunctionDecl>(VD))
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009147 scanForTargetRegionsFunctions(FD->getBody(), Name);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009148
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009149 // Do not to emit function if it is not marked as declare target.
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009150 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009151 AlreadyEmittedTargetFunctions.count(Name) == 0;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009152}
9153
9154bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
9155 if (!CGM.getLangOpts().OpenMPIsDevice)
9156 return false;
9157
9158 // Check if there are Ctors/Dtors in this declaration and look for target
9159 // regions in it. We use the complete variant to produce the kernel name
9160 // mangling.
9161 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009162 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
9163 for (const CXXConstructorDecl *Ctor : RD->ctors()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009164 StringRef ParentName =
9165 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
9166 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
9167 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009168 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009169 StringRef ParentName =
9170 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
9171 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
9172 }
9173 }
9174
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009175 // Do not to emit variable if it is not marked as declare target.
Alexey Bataev92327c52018-03-26 16:40:55 +00009176 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009177 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
9178 cast<VarDecl>(GD.getDecl()));
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009179 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
9180 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9181 HasRequiresUnifiedSharedMemory)) {
Alexey Bataevd01b7492018-08-15 19:45:12 +00009182 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009183 return true;
9184 }
9185 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009186}
9187
Alexey Bataev1af5bd52019-03-05 17:47:18 +00009188llvm::Constant *
9189CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF,
9190 const VarDecl *VD) {
9191 assert(VD->getType().isConstant(CGM.getContext()) &&
9192 "Expected constant variable.");
9193 StringRef VarName;
9194 llvm::Constant *Addr;
9195 llvm::GlobalValue::LinkageTypes Linkage;
9196 QualType Ty = VD->getType();
9197 SmallString<128> Buffer;
9198 {
9199 unsigned DeviceID;
9200 unsigned FileID;
9201 unsigned Line;
9202 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID,
9203 FileID, Line);
9204 llvm::raw_svector_ostream OS(Buffer);
9205 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID)
9206 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
9207 VarName = OS.str();
9208 }
9209 Linkage = llvm::GlobalValue::InternalLinkage;
9210 Addr =
9211 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName,
9212 getDefaultFirstprivateAddressSpace());
9213 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage);
9214 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty);
9215 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr));
9216 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9217 VarName, Addr, VarSize,
9218 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage);
9219 return Addr;
9220}
9221
Alexey Bataev03f270c2018-03-30 18:31:07 +00009222void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
9223 llvm::Constant *Addr) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009224 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9225 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
9226 if (!Res) {
9227 if (CGM.getLangOpts().OpenMPIsDevice) {
9228 // Register non-target variables being emitted in device code (debug info
9229 // may cause this).
9230 StringRef VarName = CGM.getMangledName(VD);
9231 EmittedNonTargetVariables.try_emplace(VarName, Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009232 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009233 return;
Alexey Bataev03f270c2018-03-30 18:31:07 +00009234 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009235 // Register declare target variables.
9236 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
9237 StringRef VarName;
9238 CharUnits VarSize;
9239 llvm::GlobalValue::LinkageTypes Linkage;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009240
9241 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9242 !HasRequiresUnifiedSharedMemory) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009243 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9244 VarName = CGM.getMangledName(VD);
9245 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) {
9246 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType());
9247 assert(!VarSize.isZero() && "Expected non-zero size of the variable");
9248 } else {
9249 VarSize = CharUnits::Zero();
9250 }
9251 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
9252 // Temp solution to prevent optimizations of the internal variables.
9253 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) {
9254 std::string RefName = getName({VarName, "ref"});
9255 if (!CGM.GetGlobalValue(RefName)) {
9256 llvm::Constant *AddrRef =
9257 getOrCreateInternalVariable(Addr->getType(), RefName);
9258 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef);
9259 GVAddrRef->setConstant(/*Val=*/true);
9260 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage);
9261 GVAddrRef->setInitializer(Addr);
9262 CGM.addCompilerUsedGlobal(GVAddrRef);
9263 }
9264 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009265 } else {
9266 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
9267 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9268 HasRequiresUnifiedSharedMemory)) &&
9269 "Declare target attribute must link or to with unified memory.");
9270 if (*Res == OMPDeclareTargetDeclAttr::MT_Link)
9271 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink;
9272 else
9273 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9274
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009275 if (CGM.getLangOpts().OpenMPIsDevice) {
9276 VarName = Addr->getName();
9277 Addr = nullptr;
9278 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009279 VarName = getAddrOfDeclareTargetVar(VD).getName();
9280 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009281 }
9282 VarSize = CGM.getPointerSize();
9283 Linkage = llvm::GlobalValue::WeakAnyLinkage;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009284 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009285
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009286 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9287 VarName, Addr, VarSize, Flags, Linkage);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009288}
9289
Samuel Antaoee8fb302016-01-06 13:42:12 +00009290bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009291 if (isa<FunctionDecl>(GD.getDecl()) ||
9292 isa<OMPDeclareReductionDecl>(GD.getDecl()))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009293 return emitTargetFunctions(GD);
9294
9295 return emitTargetGlobalVariable(GD);
9296}
9297
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009298void CGOpenMPRuntime::emitDeferredTargetDecls() const {
9299 for (const VarDecl *VD : DeferredGlobalVariables) {
9300 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009301 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009302 if (!Res)
9303 continue;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009304 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9305 !HasRequiresUnifiedSharedMemory) {
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009306 CGM.EmitGlobal(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009307 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009308 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
9309 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9310 HasRequiresUnifiedSharedMemory)) &&
9311 "Expected link clause or to clause with unified memory.");
9312 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009313 }
9314 }
9315}
9316
Alexey Bataev60705422018-10-30 15:50:12 +00009317void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas(
9318 CodeGenFunction &CGF, const OMPExecutableDirective &D) const {
9319 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) &&
9320 " Expected target-based directive.");
9321}
9322
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009323void CGOpenMPRuntime::checkArchForUnifiedAddressing(
9324 const OMPRequiresDecl *D) {
9325 for (const OMPClause *Clause : D->clauselists()) {
9326 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
9327 HasRequiresUnifiedSharedMemory = true;
9328 break;
9329 }
9330 }
9331}
9332
Alexey Bataevc5687252019-03-21 19:35:27 +00009333bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD,
9334 LangAS &AS) {
9335 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())
9336 return false;
9337 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
9338 switch(A->getAllocatorType()) {
9339 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
9340 // Not supported, fallback to the default mem space.
9341 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
9342 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
9343 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
9344 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
9345 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
9346 case OMPAllocateDeclAttr::OMPConstMemAlloc:
9347 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
9348 AS = LangAS::Default;
9349 return true;
9350 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
9351 llvm_unreachable("Expected predefined allocator for the variables with the "
9352 "static storage.");
9353 }
9354 return false;
9355}
9356
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00009357bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const {
9358 return HasRequiresUnifiedSharedMemory;
9359}
9360
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009361CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
9362 CodeGenModule &CGM)
9363 : CGM(CGM) {
9364 if (CGM.getLangOpts().OpenMPIsDevice) {
9365 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
9366 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
9367 }
9368}
9369
9370CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() {
9371 if (CGM.getLangOpts().OpenMPIsDevice)
9372 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
9373}
9374
Alexey Bataev6d944102018-05-02 15:45:28 +00009375bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009376 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal)
9377 return true;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009378
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009379 StringRef Name = CGM.getMangledName(GD);
Alexey Bataev6d944102018-05-02 15:45:28 +00009380 const auto *D = cast<FunctionDecl>(GD.getDecl());
Alexey Bataev34f8a702018-03-28 14:28:54 +00009381 // Do not to emit function if it is marked as declare target as it was already
9382 // emitted.
Alexey Bataev97b72212018-08-14 18:31:20 +00009383 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009384 if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) {
9385 if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name)))
Alexey Bataev34f8a702018-03-28 14:28:54 +00009386 return !F->isDeclaration();
9387 return false;
9388 }
9389 return true;
9390 }
9391
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009392 return !AlreadyEmittedTargetFunctions.insert(Name).second;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009393}
9394
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009395llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() {
9396 // If we don't have entries or if we are emitting code for the device, we
9397 // don't need to do anything.
9398 if (CGM.getLangOpts().OMPTargetTriples.empty() ||
9399 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice ||
9400 (OffloadEntriesInfoManager.empty() &&
9401 !HasEmittedDeclareTargetRegion &&
9402 !HasEmittedTargetRegion))
9403 return nullptr;
9404
9405 // Create and register the function that handles the requires directives.
9406 ASTContext &C = CGM.getContext();
9407
9408 llvm::Function *RequiresRegFn;
9409 {
9410 CodeGenFunction CGF(CGM);
9411 const auto &FI = CGM.getTypes().arrangeNullaryFunction();
9412 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
9413 std::string ReqName = getName({"omp_offloading", "requires_reg"});
9414 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI);
9415 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {});
9416 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE;
9417 // TODO: check for other requires clauses.
9418 // The requires directive takes effect only when a target region is
9419 // present in the compilation unit. Otherwise it is ignored and not
9420 // passed to the runtime. This avoids the runtime from throwing an error
9421 // for mismatching requires clauses across compilation units that don't
9422 // contain at least 1 target region.
9423 assert((HasEmittedTargetRegion ||
9424 HasEmittedDeclareTargetRegion ||
9425 !OffloadEntriesInfoManager.empty()) &&
9426 "Target or declare target region expected.");
9427 if (HasRequiresUnifiedSharedMemory)
9428 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY;
9429 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires),
9430 llvm::ConstantInt::get(CGM.Int64Ty, Flags));
9431 CGF.FinishFunction();
9432 }
9433 return RequiresRegFn;
9434}
9435
Samuel Antaoee8fb302016-01-06 13:42:12 +00009436llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() {
9437 // If we have offloading in the current module, we need to emit the entries
9438 // now and register the offloading descriptor.
9439 createOffloadEntriesAndInfoMetadata();
9440
9441 // Create and register the offloading binary descriptors. This is the main
9442 // entity that captures all the information about offloading in the current
9443 // compilation unit.
9444 return createOffloadingBinaryDescriptorRegistration();
9445}
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009446
9447void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
9448 const OMPExecutableDirective &D,
9449 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00009450 llvm::Function *OutlinedFn,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009451 ArrayRef<llvm::Value *> CapturedVars) {
9452 if (!CGF.HaveInsertPoint())
9453 return;
9454
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009455 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009456 CodeGenFunction::RunCleanupsScope Scope(CGF);
9457
9458 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
9459 llvm::Value *Args[] = {
9460 RTLoc,
9461 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
9462 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
9463 llvm::SmallVector<llvm::Value *, 16> RealArgs;
9464 RealArgs.append(std::begin(Args), std::end(Args));
9465 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
9466
James Y Knight9871db02019-02-05 16:42:33 +00009467 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009468 CGF.EmitRuntimeCall(RTLFn, RealArgs);
9469}
9470
9471void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
Carlo Bertollic6872252016-04-04 15:55:02 +00009472 const Expr *NumTeams,
9473 const Expr *ThreadLimit,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009474 SourceLocation Loc) {
9475 if (!CGF.HaveInsertPoint())
9476 return;
9477
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009478 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009479
Carlo Bertollic6872252016-04-04 15:55:02 +00009480 llvm::Value *NumTeamsVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009481 NumTeams
Carlo Bertollic6872252016-04-04 15:55:02 +00009482 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
9483 CGF.CGM.Int32Ty, /* isSigned = */ true)
9484 : CGF.Builder.getInt32(0);
9485
9486 llvm::Value *ThreadLimitVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009487 ThreadLimit
Carlo Bertollic6872252016-04-04 15:55:02 +00009488 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
9489 CGF.CGM.Int32Ty, /* isSigned = */ true)
9490 : CGF.Builder.getInt32(0);
9491
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009492 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
Carlo Bertollic6872252016-04-04 15:55:02 +00009493 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
9494 ThreadLimitVal};
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009495 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams),
9496 PushNumTeamsArgs);
9497}
Samuel Antaodf158d52016-04-27 22:58:19 +00009498
Samuel Antaocc10b852016-07-28 14:23:26 +00009499void CGOpenMPRuntime::emitTargetDataCalls(
9500 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
9501 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009502 if (!CGF.HaveInsertPoint())
9503 return;
9504
Samuel Antaocc10b852016-07-28 14:23:26 +00009505 // Action used to replace the default codegen action and turn privatization
9506 // off.
9507 PrePostActionTy NoPrivAction;
Samuel Antaodf158d52016-04-27 22:58:19 +00009508
9509 // Generate the code for the opening of the data environment. Capture all the
9510 // arguments of the runtime call by reference because they are used in the
9511 // closing of the region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009512 auto &&BeginThenGen = [this, &D, Device, &Info,
9513 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009514 // Fill up the arrays with all the mapped variables.
Samuel Antaocc10b852016-07-28 14:23:26 +00009515 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
Samuel Antaodf158d52016-04-27 22:58:19 +00009516 MappableExprsHandler::MapValuesArrayTy Pointers;
9517 MappableExprsHandler::MapValuesArrayTy Sizes;
9518 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9519
9520 // Get map clause information.
9521 MappableExprsHandler MCHandler(D, CGF);
9522 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
Samuel Antaodf158d52016-04-27 22:58:19 +00009523
9524 // Fill up the arrays and create the arguments.
Samuel Antaocc10b852016-07-28 14:23:26 +00009525 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +00009526
9527 llvm::Value *BasePointersArrayArg = nullptr;
9528 llvm::Value *PointersArrayArg = nullptr;
9529 llvm::Value *SizesArrayArg = nullptr;
9530 llvm::Value *MapTypesArrayArg = nullptr;
9531 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00009532 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +00009533
9534 // Emit device ID if any.
9535 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +00009536 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009537 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009538 CGF.Int64Ty, /*isSigned=*/true);
9539 } else {
9540 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9541 }
Samuel Antaodf158d52016-04-27 22:58:19 +00009542
9543 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009544 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +00009545
9546 llvm::Value *OffloadingArgs[] = {
9547 DeviceID, PointerNum, BasePointersArrayArg,
9548 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009549 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin),
Samuel Antaodf158d52016-04-27 22:58:19 +00009550 OffloadingArgs);
Samuel Antaocc10b852016-07-28 14:23:26 +00009551
9552 // If device pointer privatization is required, emit the body of the region
9553 // here. It will have to be duplicated: with and without privatization.
9554 if (!Info.CaptureDeviceAddrMap.empty())
9555 CodeGen(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +00009556 };
9557
9558 // Generate code for the closing of the data region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009559 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF,
9560 PrePostActionTy &) {
Samuel Antaocc10b852016-07-28 14:23:26 +00009561 assert(Info.isValid() && "Invalid data environment closing arguments.");
Samuel Antaodf158d52016-04-27 22:58:19 +00009562
9563 llvm::Value *BasePointersArrayArg = nullptr;
9564 llvm::Value *PointersArrayArg = nullptr;
9565 llvm::Value *SizesArrayArg = nullptr;
9566 llvm::Value *MapTypesArrayArg = nullptr;
9567 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00009568 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +00009569
9570 // Emit device ID if any.
9571 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +00009572 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009573 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009574 CGF.Int64Ty, /*isSigned=*/true);
9575 } else {
9576 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9577 }
Samuel Antaodf158d52016-04-27 22:58:19 +00009578
9579 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009580 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +00009581
9582 llvm::Value *OffloadingArgs[] = {
9583 DeviceID, PointerNum, BasePointersArrayArg,
9584 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009585 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end),
Samuel Antaodf158d52016-04-27 22:58:19 +00009586 OffloadingArgs);
9587 };
9588
Samuel Antaocc10b852016-07-28 14:23:26 +00009589 // If we need device pointer privatization, we need to emit the body of the
9590 // region with no privatization in the 'else' branch of the conditional.
9591 // Otherwise, we don't have to do anything.
9592 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF,
9593 PrePostActionTy &) {
9594 if (!Info.CaptureDeviceAddrMap.empty()) {
9595 CodeGen.setAction(NoPrivAction);
9596 CodeGen(CGF);
9597 }
9598 };
9599
9600 // We don't have to do anything to close the region if the if clause evaluates
9601 // to false.
9602 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
Samuel Antaodf158d52016-04-27 22:58:19 +00009603
9604 if (IfCond) {
Samuel Antaocc10b852016-07-28 14:23:26 +00009605 emitOMPIfClause(CGF, IfCond, BeginThenGen, BeginElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +00009606 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +00009607 RegionCodeGenTy RCG(BeginThenGen);
9608 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +00009609 }
9610
Samuel Antaocc10b852016-07-28 14:23:26 +00009611 // If we don't require privatization of device pointers, we emit the body in
9612 // between the runtime calls. This avoids duplicating the body code.
9613 if (Info.CaptureDeviceAddrMap.empty()) {
9614 CodeGen.setAction(NoPrivAction);
9615 CodeGen(CGF);
9616 }
Samuel Antaodf158d52016-04-27 22:58:19 +00009617
9618 if (IfCond) {
Samuel Antaocc10b852016-07-28 14:23:26 +00009619 emitOMPIfClause(CGF, IfCond, EndThenGen, EndElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +00009620 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +00009621 RegionCodeGenTy RCG(EndThenGen);
9622 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +00009623 }
9624}
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009625
Samuel Antao8d2d7302016-05-26 18:30:22 +00009626void CGOpenMPRuntime::emitTargetDataStandAloneCall(
Samuel Antao8dd66282016-04-27 23:14:30 +00009627 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
9628 const Expr *Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009629 if (!CGF.HaveInsertPoint())
9630 return;
9631
Samuel Antao8dd66282016-04-27 23:14:30 +00009632 assert((isa<OMPTargetEnterDataDirective>(D) ||
Samuel Antao8d2d7302016-05-26 18:30:22 +00009633 isa<OMPTargetExitDataDirective>(D) ||
9634 isa<OMPTargetUpdateDirective>(D)) &&
9635 "Expecting either target enter, exit data, or update directives.");
Samuel Antao8dd66282016-04-27 23:14:30 +00009636
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009637 CodeGenFunction::OMPTargetDataInfo InputInfo;
9638 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009639 // Generate the code for the opening of the data environment.
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009640 auto &&ThenGen = [this, &D, Device, &InputInfo,
9641 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009642 // Emit device ID if any.
9643 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +00009644 if (Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009645 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009646 CGF.Int64Ty, /*isSigned=*/true);
9647 } else {
9648 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9649 }
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009650
9651 // Emit the number of elements in the offloading arrays.
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009652 llvm::Constant *PointerNum =
9653 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009654
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009655 llvm::Value *OffloadingArgs[] = {DeviceID,
9656 PointerNum,
9657 InputInfo.BasePointersArray.getPointer(),
9658 InputInfo.PointersArray.getPointer(),
9659 InputInfo.SizesArray.getPointer(),
9660 MapTypesArray};
Samuel Antao8d2d7302016-05-26 18:30:22 +00009661
Samuel Antao8d2d7302016-05-26 18:30:22 +00009662 // Select the right runtime function call for each expected standalone
9663 // directive.
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00009664 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Samuel Antao8d2d7302016-05-26 18:30:22 +00009665 OpenMPRTLFunction RTLFn;
9666 switch (D.getDirectiveKind()) {
Samuel Antao8d2d7302016-05-26 18:30:22 +00009667 case OMPD_target_enter_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00009668 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait
9669 : OMPRTL__tgt_target_data_begin;
Samuel Antao8d2d7302016-05-26 18:30:22 +00009670 break;
9671 case OMPD_target_exit_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00009672 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait
9673 : OMPRTL__tgt_target_data_end;
Samuel Antao8d2d7302016-05-26 18:30:22 +00009674 break;
9675 case OMPD_target_update:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00009676 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait
9677 : OMPRTL__tgt_target_data_update;
Samuel Antao8d2d7302016-05-26 18:30:22 +00009678 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009679 case OMPD_parallel:
9680 case OMPD_for:
9681 case OMPD_parallel_for:
9682 case OMPD_parallel_sections:
9683 case OMPD_for_simd:
9684 case OMPD_parallel_for_simd:
9685 case OMPD_cancel:
9686 case OMPD_cancellation_point:
9687 case OMPD_ordered:
9688 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00009689 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009690 case OMPD_task:
9691 case OMPD_simd:
9692 case OMPD_sections:
9693 case OMPD_section:
9694 case OMPD_single:
9695 case OMPD_master:
9696 case OMPD_critical:
9697 case OMPD_taskyield:
9698 case OMPD_barrier:
9699 case OMPD_taskwait:
9700 case OMPD_taskgroup:
9701 case OMPD_atomic:
9702 case OMPD_flush:
9703 case OMPD_teams:
9704 case OMPD_target_data:
9705 case OMPD_distribute:
9706 case OMPD_distribute_simd:
9707 case OMPD_distribute_parallel_for:
9708 case OMPD_distribute_parallel_for_simd:
9709 case OMPD_teams_distribute:
9710 case OMPD_teams_distribute_simd:
9711 case OMPD_teams_distribute_parallel_for:
9712 case OMPD_teams_distribute_parallel_for_simd:
9713 case OMPD_declare_simd:
9714 case OMPD_declare_target:
9715 case OMPD_end_declare_target:
9716 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00009717 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009718 case OMPD_taskloop:
9719 case OMPD_taskloop_simd:
9720 case OMPD_target:
9721 case OMPD_target_simd:
9722 case OMPD_target_teams_distribute:
9723 case OMPD_target_teams_distribute_simd:
9724 case OMPD_target_teams_distribute_parallel_for:
9725 case OMPD_target_teams_distribute_parallel_for_simd:
9726 case OMPD_target_teams:
9727 case OMPD_target_parallel:
9728 case OMPD_target_parallel_for:
9729 case OMPD_target_parallel_for_simd:
Kelvin Li1408f912018-09-26 04:28:39 +00009730 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009731 case OMPD_unknown:
9732 llvm_unreachable("Unexpected standalone target data directive.");
9733 break;
Samuel Antao8d2d7302016-05-26 18:30:22 +00009734 }
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009735 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009736 };
9737
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009738 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray](
9739 CodeGenFunction &CGF, PrePostActionTy &) {
9740 // Fill up the arrays with all the mapped variables.
9741 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
9742 MappableExprsHandler::MapValuesArrayTy Pointers;
9743 MappableExprsHandler::MapValuesArrayTy Sizes;
9744 MappableExprsHandler::MapFlagsArrayTy MapTypes;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009745
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009746 // Get map clause information.
9747 MappableExprsHandler MEHandler(D, CGF);
9748 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
9749
9750 TargetDataInfo Info;
9751 // Fill up the arrays and create the arguments.
9752 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
9753 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
9754 Info.PointersArray, Info.SizesArray,
9755 Info.MapTypesArray, Info);
9756 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
9757 InputInfo.BasePointersArray =
9758 Address(Info.BasePointersArray, CGM.getPointerAlign());
9759 InputInfo.PointersArray =
9760 Address(Info.PointersArray, CGM.getPointerAlign());
9761 InputInfo.SizesArray =
9762 Address(Info.SizesArray, CGM.getPointerAlign());
9763 MapTypesArray = Info.MapTypesArray;
9764 if (D.hasClausesOfKind<OMPDependClause>())
9765 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
9766 else
Alexey Bataev768f1f22018-01-09 19:59:25 +00009767 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009768 };
9769
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009770 if (IfCond) {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009771 emitOMPIfClause(CGF, IfCond, TargetThenGen,
9772 [](CodeGenFunction &CGF, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009773 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009774 RegionCodeGenTy ThenRCG(TargetThenGen);
9775 ThenRCG(CGF);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009776 }
9777}
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009778
9779namespace {
9780 /// Kind of parameter in a function with 'declare simd' directive.
9781 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector };
9782 /// Attribute set of the parameter.
9783 struct ParamAttrTy {
9784 ParamKindTy Kind = Vector;
9785 llvm::APSInt StrideOrArg;
9786 llvm::APSInt Alignment;
9787 };
9788} // namespace
9789
9790static unsigned evaluateCDTSize(const FunctionDecl *FD,
9791 ArrayRef<ParamAttrTy> ParamAttrs) {
9792 // Every vector variant of a SIMD-enabled function has a vector length (VLEN).
9793 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument
9794 // of that clause. The VLEN value must be power of 2.
9795 // In other case the notion of the function`s "characteristic data type" (CDT)
9796 // is used to compute the vector length.
9797 // CDT is defined in the following order:
9798 // a) For non-void function, the CDT is the return type.
9799 // b) If the function has any non-uniform, non-linear parameters, then the
9800 // CDT is the type of the first such parameter.
9801 // c) If the CDT determined by a) or b) above is struct, union, or class
9802 // type which is pass-by-value (except for the type that maps to the
9803 // built-in complex data type), the characteristic data type is int.
9804 // d) If none of the above three cases is applicable, the CDT is int.
9805 // The VLEN is then determined based on the CDT and the size of vector
9806 // register of that ISA for which current vector version is generated. The
9807 // VLEN is computed using the formula below:
9808 // VLEN = sizeof(vector_register) / sizeof(CDT),
9809 // where vector register size specified in section 3.2.1 Registers and the
9810 // Stack Frame of original AMD64 ABI document.
9811 QualType RetType = FD->getReturnType();
9812 if (RetType.isNull())
9813 return 0;
9814 ASTContext &C = FD->getASTContext();
9815 QualType CDT;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009816 if (!RetType.isNull() && !RetType->isVoidType()) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009817 CDT = RetType;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009818 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009819 unsigned Offset = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009820 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009821 if (ParamAttrs[Offset].Kind == Vector)
9822 CDT = C.getPointerType(C.getRecordType(MD->getParent()));
9823 ++Offset;
9824 }
9825 if (CDT.isNull()) {
9826 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
9827 if (ParamAttrs[I + Offset].Kind == Vector) {
9828 CDT = FD->getParamDecl(I)->getType();
9829 break;
9830 }
9831 }
9832 }
9833 }
9834 if (CDT.isNull())
9835 CDT = C.IntTy;
9836 CDT = CDT->getCanonicalTypeUnqualified();
9837 if (CDT->isRecordType() || CDT->isUnionType())
9838 CDT = C.IntTy;
9839 return C.getTypeSize(CDT);
9840}
9841
9842static void
9843emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
Benjamin Kramer81cb4b72016-11-24 16:01:20 +00009844 const llvm::APSInt &VLENVal,
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009845 ArrayRef<ParamAttrTy> ParamAttrs,
9846 OMPDeclareSimdDeclAttr::BranchStateTy State) {
9847 struct ISADataTy {
9848 char ISA;
9849 unsigned VecRegSize;
9850 };
9851 ISADataTy ISAData[] = {
9852 {
9853 'b', 128
9854 }, // SSE
9855 {
9856 'c', 256
9857 }, // AVX
9858 {
9859 'd', 256
9860 }, // AVX2
9861 {
9862 'e', 512
9863 }, // AVX512
9864 };
9865 llvm::SmallVector<char, 2> Masked;
9866 switch (State) {
9867 case OMPDeclareSimdDeclAttr::BS_Undefined:
9868 Masked.push_back('N');
9869 Masked.push_back('M');
9870 break;
9871 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
9872 Masked.push_back('N');
9873 break;
9874 case OMPDeclareSimdDeclAttr::BS_Inbranch:
9875 Masked.push_back('M');
9876 break;
9877 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009878 for (char Mask : Masked) {
9879 for (const ISADataTy &Data : ISAData) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009880 SmallString<256> Buffer;
9881 llvm::raw_svector_ostream Out(Buffer);
9882 Out << "_ZGV" << Data.ISA << Mask;
9883 if (!VLENVal) {
Simon Pilgrim823a99c2019-05-22 13:02:19 +00009884 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs);
9885 assert(NumElts && "Non-zero simdlen/cdtsize expected");
9886 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009887 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009888 Out << VLENVal;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009889 }
9890 for (const ParamAttrTy &ParamAttr : ParamAttrs) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009891 switch (ParamAttr.Kind){
9892 case LinearWithVarStride:
9893 Out << 's' << ParamAttr.StrideOrArg;
9894 break;
9895 case Linear:
9896 Out << 'l';
9897 if (!!ParamAttr.StrideOrArg)
9898 Out << ParamAttr.StrideOrArg;
9899 break;
9900 case Uniform:
9901 Out << 'u';
9902 break;
9903 case Vector:
9904 Out << 'v';
9905 break;
9906 }
9907 if (!!ParamAttr.Alignment)
9908 Out << 'a' << ParamAttr.Alignment;
9909 }
9910 Out << '_' << Fn->getName();
9911 Fn->addFnAttr(Out.str());
9912 }
9913 }
9914}
9915
Alexey Bataeva0a22642019-04-16 13:56:21 +00009916// This are the Functions that are needed to mangle the name of the
9917// vector functions generated by the compiler, according to the rules
9918// defined in the "Vector Function ABI specifications for AArch64",
9919// available at
9920// https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi.
9921
9922/// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI.
9923///
9924/// TODO: Need to implement the behavior for reference marked with a
9925/// var or no linear modifiers (1.b in the section). For this, we
9926/// need to extend ParamKindTy to support the linear modifiers.
9927static bool getAArch64MTV(QualType QT, ParamKindTy Kind) {
9928 QT = QT.getCanonicalType();
9929
9930 if (QT->isVoidType())
9931 return false;
9932
9933 if (Kind == ParamKindTy::Uniform)
9934 return false;
9935
9936 if (Kind == ParamKindTy::Linear)
9937 return false;
9938
9939 // TODO: Handle linear references with modifiers
9940
9941 if (Kind == ParamKindTy::LinearWithVarStride)
9942 return false;
9943
9944 return true;
9945}
9946
9947/// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
9948static bool getAArch64PBV(QualType QT, ASTContext &C) {
9949 QT = QT.getCanonicalType();
9950 unsigned Size = C.getTypeSize(QT);
9951
9952 // Only scalars and complex within 16 bytes wide set PVB to true.
9953 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
9954 return false;
9955
9956 if (QT->isFloatingType())
9957 return true;
9958
9959 if (QT->isIntegerType())
9960 return true;
9961
9962 if (QT->isPointerType())
9963 return true;
9964
9965 // TODO: Add support for complex types (section 3.1.2, item 2).
9966
9967 return false;
9968}
9969
9970/// Computes the lane size (LS) of a return type or of an input parameter,
9971/// as defined by `LS(P)` in 3.2.1 of the AAVFABI.
9972/// TODO: Add support for references, section 3.2.1, item 1.
9973static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) {
9974 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) {
9975 QualType PTy = QT.getCanonicalType()->getPointeeType();
9976 if (getAArch64PBV(PTy, C))
9977 return C.getTypeSize(PTy);
9978 }
9979 if (getAArch64PBV(QT, C))
9980 return C.getTypeSize(QT);
9981
9982 return C.getTypeSize(C.getUIntPtrType());
9983}
9984
9985// Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the
9986// signature of the scalar function, as defined in 3.2.2 of the
9987// AAVFABI.
9988static std::tuple<unsigned, unsigned, bool>
9989getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) {
9990 QualType RetType = FD->getReturnType().getCanonicalType();
9991
9992 ASTContext &C = FD->getASTContext();
9993
9994 bool OutputBecomesInput = false;
9995
9996 llvm::SmallVector<unsigned, 8> Sizes;
9997 if (!RetType->isVoidType()) {
9998 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C));
9999 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {}))
10000 OutputBecomesInput = true;
10001 }
10002 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10003 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType();
10004 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C));
10005 }
10006
10007 assert(!Sizes.empty() && "Unable to determine NDS and WDS.");
10008 // The LS of a function parameter / return value can only be a power
10009 // of 2, starting from 8 bits, up to 128.
10010 assert(std::all_of(Sizes.begin(), Sizes.end(),
10011 [](unsigned Size) {
10012 return Size == 8 || Size == 16 || Size == 32 ||
10013 Size == 64 || Size == 128;
10014 }) &&
10015 "Invalid size");
10016
10017 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)),
10018 *std::max_element(std::begin(Sizes), std::end(Sizes)),
10019 OutputBecomesInput);
10020}
10021
10022/// Mangle the parameter part of the vector function name according to
10023/// their OpenMP classification. The mangling function is defined in
10024/// section 3.5 of the AAVFABI.
10025static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) {
10026 SmallString<256> Buffer;
10027 llvm::raw_svector_ostream Out(Buffer);
10028 for (const auto &ParamAttr : ParamAttrs) {
10029 switch (ParamAttr.Kind) {
10030 case LinearWithVarStride:
10031 Out << "ls" << ParamAttr.StrideOrArg;
10032 break;
10033 case Linear:
10034 Out << 'l';
10035 // Don't print the step value if it is not present or if it is
10036 // equal to 1.
10037 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1)
10038 Out << ParamAttr.StrideOrArg;
10039 break;
10040 case Uniform:
10041 Out << 'u';
10042 break;
10043 case Vector:
10044 Out << 'v';
10045 break;
10046 }
10047
10048 if (!!ParamAttr.Alignment)
10049 Out << 'a' << ParamAttr.Alignment;
10050 }
10051
10052 return Out.str();
10053}
10054
10055// Function used to add the attribute. The parameter `VLEN` is
10056// templated to allow the use of "x" when targeting scalable functions
10057// for SVE.
10058template <typename T>
10059static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix,
10060 char ISA, StringRef ParSeq,
10061 StringRef MangledName, bool OutputBecomesInput,
10062 llvm::Function *Fn) {
10063 SmallString<256> Buffer;
10064 llvm::raw_svector_ostream Out(Buffer);
10065 Out << Prefix << ISA << LMask << VLEN;
10066 if (OutputBecomesInput)
10067 Out << "v";
10068 Out << ParSeq << "_" << MangledName;
10069 Fn->addFnAttr(Out.str());
10070}
10071
10072// Helper function to generate the Advanced SIMD names depending on
10073// the value of the NDS when simdlen is not present.
10074static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask,
10075 StringRef Prefix, char ISA,
10076 StringRef ParSeq, StringRef MangledName,
10077 bool OutputBecomesInput,
10078 llvm::Function *Fn) {
10079 switch (NDS) {
10080 case 8:
10081 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10082 OutputBecomesInput, Fn);
10083 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName,
10084 OutputBecomesInput, Fn);
10085 break;
10086 case 16:
10087 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10088 OutputBecomesInput, Fn);
10089 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10090 OutputBecomesInput, Fn);
10091 break;
10092 case 32:
10093 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10094 OutputBecomesInput, Fn);
10095 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10096 OutputBecomesInput, Fn);
10097 break;
10098 case 64:
10099 case 128:
10100 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10101 OutputBecomesInput, Fn);
10102 break;
10103 default:
10104 llvm_unreachable("Scalar type is too wide.");
10105 }
10106}
10107
10108/// Emit vector function attributes for AArch64, as defined in the AAVFABI.
10109static void emitAArch64DeclareSimdFunction(
10110 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN,
10111 ArrayRef<ParamAttrTy> ParamAttrs,
10112 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
10113 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) {
10114
10115 // Get basic data for building the vector signature.
10116 const auto Data = getNDSWDS(FD, ParamAttrs);
10117 const unsigned NDS = std::get<0>(Data);
10118 const unsigned WDS = std::get<1>(Data);
10119 const bool OutputBecomesInput = std::get<2>(Data);
10120
10121 // Check the values provided via `simdlen` by the user.
10122 // 1. A `simdlen(1)` doesn't produce vector signatures,
10123 if (UserVLEN == 1) {
10124 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10125 DiagnosticsEngine::Warning,
10126 "The clause simdlen(1) has no effect when targeting aarch64.");
10127 CGM.getDiags().Report(SLoc, DiagID);
10128 return;
10129 }
10130
10131 // 2. Section 3.3.1, item 1: user input must be a power of 2 for
10132 // Advanced SIMD output.
10133 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
10134 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10135 DiagnosticsEngine::Warning, "The value specified in simdlen must be a "
10136 "power of 2 when targeting Advanced SIMD.");
10137 CGM.getDiags().Report(SLoc, DiagID);
10138 return;
10139 }
10140
10141 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural
10142 // limits.
10143 if (ISA == 's' && UserVLEN != 0) {
10144 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
10145 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10146 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit "
10147 "lanes in the architectural constraints "
10148 "for SVE (min is 128-bit, max is "
10149 "2048-bit, by steps of 128-bit)");
10150 CGM.getDiags().Report(SLoc, DiagID) << WDS;
10151 return;
10152 }
10153 }
10154
10155 // Sort out parameter sequence.
10156 const std::string ParSeq = mangleVectorParameters(ParamAttrs);
10157 StringRef Prefix = "_ZGV";
10158 // Generate simdlen from user input (if any).
10159 if (UserVLEN) {
10160 if (ISA == 's') {
10161 // SVE generates only a masked function.
10162 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10163 OutputBecomesInput, Fn);
10164 } else {
10165 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10166 // Advanced SIMD generates one or two functions, depending on
10167 // the `[not]inbranch` clause.
10168 switch (State) {
10169 case OMPDeclareSimdDeclAttr::BS_Undefined:
10170 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10171 OutputBecomesInput, Fn);
10172 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10173 OutputBecomesInput, Fn);
10174 break;
10175 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10176 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10177 OutputBecomesInput, Fn);
10178 break;
10179 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10180 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10181 OutputBecomesInput, Fn);
10182 break;
10183 }
10184 }
10185 } else {
10186 // If no user simdlen is provided, follow the AAVFABI rules for
10187 // generating the vector length.
10188 if (ISA == 's') {
10189 // SVE, section 3.4.1, item 1.
10190 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName,
10191 OutputBecomesInput, Fn);
10192 } else {
10193 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10194 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or
10195 // two vector names depending on the use of the clause
10196 // `[not]inbranch`.
10197 switch (State) {
10198 case OMPDeclareSimdDeclAttr::BS_Undefined:
10199 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10200 OutputBecomesInput, Fn);
10201 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10202 OutputBecomesInput, Fn);
10203 break;
10204 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10205 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10206 OutputBecomesInput, Fn);
10207 break;
10208 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10209 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10210 OutputBecomesInput, Fn);
10211 break;
10212 }
10213 }
10214 }
10215}
10216
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010217void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
10218 llvm::Function *Fn) {
10219 ASTContext &C = CGM.getContext();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010220 FD = FD->getMostRecentDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010221 // Map params to their positions in function decl.
10222 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
10223 if (isa<CXXMethodDecl>(FD))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010224 ParamPositions.try_emplace(FD, 0);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010225 unsigned ParamPos = ParamPositions.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010226 for (const ParmVarDecl *P : FD->parameters()) {
10227 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010228 ++ParamPos;
10229 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010230 while (FD) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010231 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010232 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
10233 // Mark uniform parameters.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010234 for (const Expr *E : Attr->uniforms()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010235 E = E->IgnoreParenImpCasts();
10236 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010237 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010238 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010239 } else {
10240 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10241 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010242 Pos = ParamPositions[PVD];
10243 }
10244 ParamAttrs[Pos].Kind = Uniform;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010245 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010246 // Get alignment info.
10247 auto NI = Attr->alignments_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010248 for (const Expr *E : Attr->aligneds()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010249 E = E->IgnoreParenImpCasts();
10250 unsigned Pos;
10251 QualType ParmTy;
10252 if (isa<CXXThisExpr>(E)) {
10253 Pos = ParamPositions[FD];
10254 ParmTy = E->getType();
10255 } else {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010256 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10257 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010258 Pos = ParamPositions[PVD];
10259 ParmTy = PVD->getType();
10260 }
10261 ParamAttrs[Pos].Alignment =
10262 (*NI)
10263 ? (*NI)->EvaluateKnownConstInt(C)
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010264 : llvm::APSInt::getUnsigned(
10265 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy))
10266 .getQuantity());
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010267 ++NI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010268 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010269 // Mark linear parameters.
10270 auto SI = Attr->steps_begin();
10271 auto MI = Attr->modifiers_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010272 for (const Expr *E : Attr->linears()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010273 E = E->IgnoreParenImpCasts();
10274 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010275 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010276 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010277 } else {
10278 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10279 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010280 Pos = ParamPositions[PVD];
10281 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010282 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010283 ParamAttr.Kind = Linear;
10284 if (*SI) {
Fangrui Song407659a2018-11-30 23:41:18 +000010285 Expr::EvalResult Result;
10286 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010287 if (const auto *DRE =
10288 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
10289 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010290 ParamAttr.Kind = LinearWithVarStride;
10291 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(
10292 ParamPositions[StridePVD->getCanonicalDecl()]);
10293 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010294 }
Fangrui Song407659a2018-11-30 23:41:18 +000010295 } else {
10296 ParamAttr.StrideOrArg = Result.Val.getInt();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010297 }
10298 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010299 ++SI;
10300 ++MI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010301 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010302 llvm::APSInt VLENVal;
Alexey Bataeva0a22642019-04-16 13:56:21 +000010303 SourceLocation ExprLoc;
10304 const Expr *VLENExpr = Attr->getSimdlen();
10305 if (VLENExpr) {
10306 VLENVal = VLENExpr->EvaluateKnownConstInt(C);
10307 ExprLoc = VLENExpr->getExprLoc();
10308 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010309 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
10310 if (CGM.getTriple().getArch() == llvm::Triple::x86 ||
Alexey Bataeva0a22642019-04-16 13:56:21 +000010311 CGM.getTriple().getArch() == llvm::Triple::x86_64) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010312 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
Alexey Bataeva0a22642019-04-16 13:56:21 +000010313 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) {
10314 unsigned VLEN = VLENVal.getExtValue();
10315 StringRef MangledName = Fn->getName();
10316 if (CGM.getTarget().hasFeature("sve"))
10317 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10318 MangledName, 's', 128, Fn, ExprLoc);
10319 if (CGM.getTarget().hasFeature("neon"))
10320 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10321 MangledName, 'n', 128, Fn, ExprLoc);
10322 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010323 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010324 FD = FD->getPreviousDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010325 }
10326}
Alexey Bataev8b427062016-05-25 12:36:08 +000010327
10328namespace {
10329/// Cleanup action for doacross support.
10330class DoacrossCleanupTy final : public EHScopeStack::Cleanup {
10331public:
10332 static const int DoacrossFinArgs = 2;
10333
10334private:
James Y Knight9871db02019-02-05 16:42:33 +000010335 llvm::FunctionCallee RTLFn;
Alexey Bataev8b427062016-05-25 12:36:08 +000010336 llvm::Value *Args[DoacrossFinArgs];
10337
10338public:
James Y Knight9871db02019-02-05 16:42:33 +000010339 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
10340 ArrayRef<llvm::Value *> CallArgs)
Alexey Bataev8b427062016-05-25 12:36:08 +000010341 : RTLFn(RTLFn) {
10342 assert(CallArgs.size() == DoacrossFinArgs);
10343 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10344 }
10345 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10346 if (!CGF.HaveInsertPoint())
10347 return;
10348 CGF.EmitRuntimeCall(RTLFn, Args);
10349 }
10350};
10351} // namespace
10352
10353void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000010354 const OMPLoopDirective &D,
10355 ArrayRef<Expr *> NumIterations) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010356 if (!CGF.HaveInsertPoint())
10357 return;
10358
10359 ASTContext &C = CGM.getContext();
10360 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
10361 RecordDecl *RD;
10362 if (KmpDimTy.isNull()) {
10363 // Build struct kmp_dim { // loop bounds info casted to kmp_int64
10364 // kmp_int64 lo; // lower
10365 // kmp_int64 up; // upper
10366 // kmp_int64 st; // stride
10367 // };
10368 RD = C.buildImplicitRecord("kmp_dim");
10369 RD->startDefinition();
10370 addFieldToRecordDecl(C, RD, Int64Ty);
10371 addFieldToRecordDecl(C, RD, Int64Ty);
10372 addFieldToRecordDecl(C, RD, Int64Ty);
10373 RD->completeDefinition();
10374 KmpDimTy = C.getRecordType(RD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010375 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010376 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010377 }
Alexey Bataevf138fda2018-08-13 19:04:24 +000010378 llvm::APInt Size(/*numBits=*/32, NumIterations.size());
10379 QualType ArrayTy =
10380 C.getConstantArrayType(KmpDimTy, Size, ArrayType::Normal, 0);
Alexey Bataev8b427062016-05-25 12:36:08 +000010381
Alexey Bataevf138fda2018-08-13 19:04:24 +000010382 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
10383 CGF.EmitNullInitialization(DimsAddr, ArrayTy);
Alexey Bataev8b427062016-05-25 12:36:08 +000010384 enum { LowerFD = 0, UpperFD, StrideFD };
10385 // Fill dims with data.
Alexey Bataevf138fda2018-08-13 19:04:24 +000010386 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +000010387 LValue DimsLVal = CGF.MakeAddrLValue(
10388 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010389 // dims.upper = num_iterations;
10390 LValue UpperLVal = CGF.EmitLValueForField(
10391 DimsLVal, *std::next(RD->field_begin(), UpperFD));
10392 llvm::Value *NumIterVal =
10393 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]),
10394 D.getNumIterations()->getType(), Int64Ty,
10395 D.getNumIterations()->getExprLoc());
10396 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
10397 // dims.stride = 1;
10398 LValue StrideLVal = CGF.EmitLValueForField(
10399 DimsLVal, *std::next(RD->field_begin(), StrideFD));
10400 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
10401 StrideLVal);
10402 }
Alexey Bataev8b427062016-05-25 12:36:08 +000010403
10404 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
10405 // kmp_int32 num_dims, struct kmp_dim * dims);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010406 llvm::Value *Args[] = {
10407 emitUpdateLocation(CGF, D.getBeginLoc()),
10408 getThreadID(CGF, D.getBeginLoc()),
10409 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()),
10410 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knight751fe282019-02-09 22:22:28 +000010411 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(),
Alexey Bataevf138fda2018-08-13 19:04:24 +000010412 CGM.VoidPtrTy)};
Alexey Bataev8b427062016-05-25 12:36:08 +000010413
James Y Knight9871db02019-02-05 16:42:33 +000010414 llvm::FunctionCallee RTLFn =
10415 createRuntimeFunction(OMPRTL__kmpc_doacross_init);
Alexey Bataev8b427062016-05-25 12:36:08 +000010416 CGF.EmitRuntimeCall(RTLFn, Args);
10417 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
Stephen Kelly1c301dc2018-08-09 21:09:38 +000010418 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())};
James Y Knight9871db02019-02-05 16:42:33 +000010419 llvm::FunctionCallee FiniRTLFn =
10420 createRuntimeFunction(OMPRTL__kmpc_doacross_fini);
Alexey Bataev8b427062016-05-25 12:36:08 +000010421 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
10422 llvm::makeArrayRef(FiniArgs));
10423}
10424
10425void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
10426 const OMPDependClause *C) {
10427 QualType Int64Ty =
10428 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010429 llvm::APInt Size(/*numBits=*/32, C->getNumLoops());
10430 QualType ArrayTy = CGM.getContext().getConstantArrayType(
10431 Int64Ty, Size, ArrayType::Normal, 0);
10432 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr");
10433 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) {
10434 const Expr *CounterVal = C->getLoopData(I);
10435 assert(CounterVal);
10436 llvm::Value *CntVal = CGF.EmitScalarConversion(
10437 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
10438 CounterVal->getExprLoc());
James Y Knight751fe282019-02-09 22:22:28 +000010439 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I),
10440 /*Volatile=*/false, Int64Ty);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010441 }
10442 llvm::Value *Args[] = {
10443 emitUpdateLocation(CGF, C->getBeginLoc()),
10444 getThreadID(CGF, C->getBeginLoc()),
James Y Knight751fe282019-02-09 22:22:28 +000010445 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()};
James Y Knight9871db02019-02-05 16:42:33 +000010446 llvm::FunctionCallee RTLFn;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010447 if (C->getDependencyKind() == OMPC_DEPEND_source) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010448 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010449 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010450 assert(C->getDependencyKind() == OMPC_DEPEND_sink);
10451 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait);
10452 }
10453 CGF.EmitRuntimeCall(RTLFn, Args);
10454}
10455
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010456void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000010457 llvm::FunctionCallee Callee,
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010458 ArrayRef<llvm::Value *> Args) const {
10459 assert(Loc.isValid() && "Outlined function call location must be valid.");
Alexey Bataev3c595a62017-08-14 15:01:03 +000010460 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
10461
James Y Knight9871db02019-02-05 16:42:33 +000010462 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010463 if (Fn->doesNotThrow()) {
Alexey Bataev3c595a62017-08-14 15:01:03 +000010464 CGF.EmitNounwindRuntimeCall(Fn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010465 return;
10466 }
10467 }
Alexey Bataev3c595a62017-08-14 15:01:03 +000010468 CGF.EmitRuntimeCall(Callee, Args);
10469}
10470
10471void CGOpenMPRuntime::emitOutlinedFunctionCall(
James Y Knight9871db02019-02-05 16:42:33 +000010472 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn,
Alexey Bataev3c595a62017-08-14 15:01:03 +000010473 ArrayRef<llvm::Value *> Args) const {
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010474 emitCall(CGF, Loc, OutlinedFn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010475}
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010476
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +000010477void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) {
10478 if (const auto *FD = dyn_cast<FunctionDecl>(D))
10479 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
10480 HasEmittedDeclareTargetRegion = true;
10481}
10482
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010483Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
10484 const VarDecl *NativeParam,
10485 const VarDecl *TargetParam) const {
10486 return CGF.GetAddrOfLocalVar(NativeParam);
10487}
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010488
Alexey Bataev4f680db2019-03-19 16:41:16 +000010489namespace {
10490/// Cleanup action for allocate support.
10491class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup {
10492public:
10493 static const int CleanupArgs = 3;
10494
10495private:
10496 llvm::FunctionCallee RTLFn;
10497 llvm::Value *Args[CleanupArgs];
10498
10499public:
10500 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
10501 ArrayRef<llvm::Value *> CallArgs)
10502 : RTLFn(RTLFn) {
10503 assert(CallArgs.size() == CleanupArgs &&
10504 "Size of arguments does not match.");
10505 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10506 }
10507 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10508 if (!CGF.HaveInsertPoint())
10509 return;
10510 CGF.EmitRuntimeCall(RTLFn, Args);
10511 }
10512};
10513} // namespace
10514
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000010515Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF,
10516 const VarDecl *VD) {
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010517 if (!VD)
10518 return Address::invalid();
Alexey Bataev4f680db2019-03-19 16:41:16 +000010519 const VarDecl *CVD = VD->getCanonicalDecl();
10520 if (!CVD->hasAttr<OMPAllocateDeclAttr>())
10521 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010522 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
10523 // Use the default allocation.
Alexey Bataev0fd3c682019-04-02 19:44:46 +000010524 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
10525 !AA->getAllocator())
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010526 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010527 llvm::Value *Size;
10528 CharUnits Align = CGM.getContext().getDeclAlign(CVD);
10529 if (CVD->getType()->isVariablyModifiedType()) {
10530 Size = CGF.getTypeSize(CVD->getType());
Alexey Bataev9c397812019-04-03 17:57:06 +000010531 // Align the size: ((size + align - 1) / align) * align
10532 Size = CGF.Builder.CreateNUWAdd(
10533 Size, CGM.getSize(Align - CharUnits::fromQuantity(1)));
10534 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align));
10535 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align));
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010536 } else {
10537 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType());
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010538 Size = CGM.getSize(Sz.alignTo(Align));
Alexey Bataev4f680db2019-03-19 16:41:16 +000010539 }
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010540 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc());
10541 assert(AA->getAllocator() &&
10542 "Expected allocator expression for non-default allocator.");
10543 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator());
Alexey Bataev6cf7b712019-04-08 19:06:42 +000010544 // According to the standard, the original allocator type is a enum (integer).
10545 // Convert to pointer type, if required.
10546 if (Allocator->getType()->isIntegerTy())
10547 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy);
10548 else if (Allocator->getType()->isPointerTy())
10549 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator,
10550 CGM.VoidPtrTy);
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010551 llvm::Value *Args[] = {ThreadID, Size, Allocator};
10552
10553 llvm::Value *Addr =
10554 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args,
10555 CVD->getName() + ".void.addr");
10556 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr,
10557 Allocator};
10558 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free);
10559
10560 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
10561 llvm::makeArrayRef(FiniArgs));
10562 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
10563 Addr,
10564 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())),
10565 CVD->getName() + ".addr");
10566 return Address(Addr, Align);
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000010567}
10568
James Y Knight9871db02019-02-05 16:42:33 +000010569llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010570 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
10571 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
10572 llvm_unreachable("Not supported in SIMD-only mode");
10573}
10574
James Y Knight9871db02019-02-05 16:42:33 +000010575llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010576 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
10577 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
10578 llvm_unreachable("Not supported in SIMD-only mode");
10579}
10580
James Y Knight9871db02019-02-05 16:42:33 +000010581llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010582 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
10583 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
10584 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
10585 bool Tied, unsigned &NumberOfParts) {
10586 llvm_unreachable("Not supported in SIMD-only mode");
10587}
10588
10589void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF,
10590 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000010591 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010592 ArrayRef<llvm::Value *> CapturedVars,
10593 const Expr *IfCond) {
10594 llvm_unreachable("Not supported in SIMD-only mode");
10595}
10596
10597void CGOpenMPSIMDRuntime::emitCriticalRegion(
10598 CodeGenFunction &CGF, StringRef CriticalName,
10599 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
10600 const Expr *Hint) {
10601 llvm_unreachable("Not supported in SIMD-only mode");
10602}
10603
10604void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF,
10605 const RegionCodeGenTy &MasterOpGen,
10606 SourceLocation Loc) {
10607 llvm_unreachable("Not supported in SIMD-only mode");
10608}
10609
10610void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
10611 SourceLocation Loc) {
10612 llvm_unreachable("Not supported in SIMD-only mode");
10613}
10614
10615void CGOpenMPSIMDRuntime::emitTaskgroupRegion(
10616 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen,
10617 SourceLocation Loc) {
10618 llvm_unreachable("Not supported in SIMD-only mode");
10619}
10620
10621void CGOpenMPSIMDRuntime::emitSingleRegion(
10622 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen,
10623 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars,
10624 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs,
10625 ArrayRef<const Expr *> AssignmentOps) {
10626 llvm_unreachable("Not supported in SIMD-only mode");
10627}
10628
10629void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF,
10630 const RegionCodeGenTy &OrderedOpGen,
10631 SourceLocation Loc,
10632 bool IsThreads) {
10633 llvm_unreachable("Not supported in SIMD-only mode");
10634}
10635
10636void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF,
10637 SourceLocation Loc,
10638 OpenMPDirectiveKind Kind,
10639 bool EmitChecks,
10640 bool ForceSimpleCall) {
10641 llvm_unreachable("Not supported in SIMD-only mode");
10642}
10643
10644void CGOpenMPSIMDRuntime::emitForDispatchInit(
10645 CodeGenFunction &CGF, SourceLocation Loc,
10646 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
10647 bool Ordered, const DispatchRTInput &DispatchValues) {
10648 llvm_unreachable("Not supported in SIMD-only mode");
10649}
10650
10651void CGOpenMPSIMDRuntime::emitForStaticInit(
10652 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind,
10653 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) {
10654 llvm_unreachable("Not supported in SIMD-only mode");
10655}
10656
10657void CGOpenMPSIMDRuntime::emitDistributeStaticInit(
10658 CodeGenFunction &CGF, SourceLocation Loc,
10659 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) {
10660 llvm_unreachable("Not supported in SIMD-only mode");
10661}
10662
10663void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
10664 SourceLocation Loc,
10665 unsigned IVSize,
10666 bool IVSigned) {
10667 llvm_unreachable("Not supported in SIMD-only mode");
10668}
10669
10670void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF,
10671 SourceLocation Loc,
10672 OpenMPDirectiveKind DKind) {
10673 llvm_unreachable("Not supported in SIMD-only mode");
10674}
10675
10676llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF,
10677 SourceLocation Loc,
10678 unsigned IVSize, bool IVSigned,
10679 Address IL, Address LB,
10680 Address UB, Address ST) {
10681 llvm_unreachable("Not supported in SIMD-only mode");
10682}
10683
10684void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
10685 llvm::Value *NumThreads,
10686 SourceLocation Loc) {
10687 llvm_unreachable("Not supported in SIMD-only mode");
10688}
10689
10690void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF,
10691 OpenMPProcBindClauseKind ProcBind,
10692 SourceLocation Loc) {
10693 llvm_unreachable("Not supported in SIMD-only mode");
10694}
10695
10696Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
10697 const VarDecl *VD,
10698 Address VDAddr,
10699 SourceLocation Loc) {
10700 llvm_unreachable("Not supported in SIMD-only mode");
10701}
10702
10703llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition(
10704 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit,
10705 CodeGenFunction *CGF) {
10706 llvm_unreachable("Not supported in SIMD-only mode");
10707}
10708
10709Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate(
10710 CodeGenFunction &CGF, QualType VarType, StringRef Name) {
10711 llvm_unreachable("Not supported in SIMD-only mode");
10712}
10713
10714void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF,
10715 ArrayRef<const Expr *> Vars,
10716 SourceLocation Loc) {
10717 llvm_unreachable("Not supported in SIMD-only mode");
10718}
10719
10720void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
10721 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000010722 llvm::Function *TaskFunction,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010723 QualType SharedsTy, Address Shareds,
10724 const Expr *IfCond,
10725 const OMPTaskDataTy &Data) {
10726 llvm_unreachable("Not supported in SIMD-only mode");
10727}
10728
10729void CGOpenMPSIMDRuntime::emitTaskLoopCall(
10730 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000010731 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010732 const Expr *IfCond, const OMPTaskDataTy &Data) {
10733 llvm_unreachable("Not supported in SIMD-only mode");
10734}
10735
10736void CGOpenMPSIMDRuntime::emitReduction(
10737 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates,
10738 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
10739 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) {
10740 assert(Options.SimpleReduction && "Only simple reduction is expected.");
10741 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
10742 ReductionOps, Options);
10743}
10744
10745llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit(
10746 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
10747 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
10748 llvm_unreachable("Not supported in SIMD-only mode");
10749}
10750
10751void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
10752 SourceLocation Loc,
10753 ReductionCodeGen &RCG,
10754 unsigned N) {
10755 llvm_unreachable("Not supported in SIMD-only mode");
10756}
10757
10758Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
10759 SourceLocation Loc,
10760 llvm::Value *ReductionsPtr,
10761 LValue SharedLVal) {
10762 llvm_unreachable("Not supported in SIMD-only mode");
10763}
10764
10765void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
10766 SourceLocation Loc) {
10767 llvm_unreachable("Not supported in SIMD-only mode");
10768}
10769
10770void CGOpenMPSIMDRuntime::emitCancellationPointCall(
10771 CodeGenFunction &CGF, SourceLocation Loc,
10772 OpenMPDirectiveKind CancelRegion) {
10773 llvm_unreachable("Not supported in SIMD-only mode");
10774}
10775
10776void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF,
10777 SourceLocation Loc, const Expr *IfCond,
10778 OpenMPDirectiveKind CancelRegion) {
10779 llvm_unreachable("Not supported in SIMD-only mode");
10780}
10781
10782void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction(
10783 const OMPExecutableDirective &D, StringRef ParentName,
10784 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
10785 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
10786 llvm_unreachable("Not supported in SIMD-only mode");
10787}
10788
10789void CGOpenMPSIMDRuntime::emitTargetCall(CodeGenFunction &CGF,
10790 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000010791 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010792 llvm::Value *OutlinedFnID,
James Y Knight9871db02019-02-05 16:42:33 +000010793 const Expr *IfCond,
10794 const Expr *Device) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010795 llvm_unreachable("Not supported in SIMD-only mode");
10796}
10797
10798bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) {
10799 llvm_unreachable("Not supported in SIMD-only mode");
10800}
10801
10802bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
10803 llvm_unreachable("Not supported in SIMD-only mode");
10804}
10805
10806bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) {
10807 return false;
10808}
10809
10810llvm::Function *CGOpenMPSIMDRuntime::emitRegistrationFunction() {
10811 return nullptr;
10812}
10813
10814void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF,
10815 const OMPExecutableDirective &D,
10816 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000010817 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010818 ArrayRef<llvm::Value *> CapturedVars) {
10819 llvm_unreachable("Not supported in SIMD-only mode");
10820}
10821
10822void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
10823 const Expr *NumTeams,
10824 const Expr *ThreadLimit,
10825 SourceLocation Loc) {
10826 llvm_unreachable("Not supported in SIMD-only mode");
10827}
10828
10829void CGOpenMPSIMDRuntime::emitTargetDataCalls(
10830 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10831 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
10832 llvm_unreachable("Not supported in SIMD-only mode");
10833}
10834
10835void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
10836 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10837 const Expr *Device) {
10838 llvm_unreachable("Not supported in SIMD-only mode");
10839}
10840
10841void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000010842 const OMPLoopDirective &D,
10843 ArrayRef<Expr *> NumIterations) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010844 llvm_unreachable("Not supported in SIMD-only mode");
10845}
10846
10847void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
10848 const OMPDependClause *C) {
10849 llvm_unreachable("Not supported in SIMD-only mode");
10850}
10851
10852const VarDecl *
10853CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD,
10854 const VarDecl *NativeParam) const {
10855 llvm_unreachable("Not supported in SIMD-only mode");
10856}
10857
10858Address
10859CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF,
10860 const VarDecl *NativeParam,
10861 const VarDecl *TargetParam) const {
10862 llvm_unreachable("Not supported in SIMD-only mode");
10863}