blob: f80249483c7a466eee086883d364910e4bc013c4 [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"
Alexey Bataev4e8231b2019-11-05 15:13:30 -050023#include "llvm/ADT/SetOperations.h"
Teresa Johnsonffc4e242016-11-11 05:35:12 +000024#include "llvm/Bitcode/BitcodeReader.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000025#include "llvm/IR/DerivedTypes.h"
26#include "llvm/IR/GlobalValue.h"
27#include "llvm/IR/Value.h"
Samuel Antaoee8fb302016-01-06 13:42:12 +000028#include "llvm/Support/Format.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000029#include "llvm/Support/raw_ostream.h"
Alexey Bataev23b69422014-06-18 07:08:49 +000030#include <cassert>
Alexey Bataev9959db52014-05-06 10:08:46 +000031
32using namespace clang;
33using namespace CodeGen;
34
Benjamin Kramerc52193f2014-10-10 13:57:57 +000035namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000036/// Base class for handling code generation inside OpenMP regions.
Alexey Bataev18095712014-10-10 12:19:54 +000037class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
38public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000039 /// Kinds of OpenMP regions used in codegen.
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000040 enum CGOpenMPRegionKind {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000041 /// Region with outlined function for standalone 'parallel'
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000042 /// directive.
43 ParallelOutlinedRegion,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000044 /// Region with outlined function for standalone 'task' directive.
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000045 TaskOutlinedRegion,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000046 /// Region for constructs that do not require function outlining,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000047 /// like 'for', 'sections', 'atomic' etc. directives.
48 InlinedRegion,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000049 /// Region with outlined function for standalone 'target' directive.
Samuel Antaobed3c462015-10-02 16:14:20 +000050 TargetRegion,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000051 };
Alexey Bataev18095712014-10-10 12:19:54 +000052
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000053 CGOpenMPRegionInfo(const CapturedStmt &CS,
54 const CGOpenMPRegionKind RegionKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +000055 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
56 bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000057 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
Alexey Bataev25e5b442015-09-15 12:52:43 +000058 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000059
60 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +000061 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
62 bool HasCancel)
Alexey Bataev81c7ea02015-07-03 09:56:58 +000063 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
Alexey Bataev25e5b442015-09-15 12:52:43 +000064 Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000065
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000066 /// Get a variable or parameter for storing global thread id
Alexey Bataev18095712014-10-10 12:19:54 +000067 /// inside OpenMP construct.
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000068 virtual const VarDecl *getThreadIDVariable() const = 0;
Alexey Bataev18095712014-10-10 12:19:54 +000069
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000070 /// Emit the captured statement body.
Hans Wennborg7eb54642015-09-10 17:07:54 +000071 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000072
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000073 /// Get an LValue for the current ThreadID variable.
Alexey Bataev62b63b12015-03-10 07:28:44 +000074 /// \return LValue for thread id variable. This LValue always has type int32*.
75 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
Alexey Bataev18095712014-10-10 12:19:54 +000076
Alexey Bataev48591dd2016-04-20 04:01:36 +000077 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {}
78
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000079 CGOpenMPRegionKind getRegionKind() const { return RegionKind; }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000080
Alexey Bataev81c7ea02015-07-03 09:56:58 +000081 OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
82
Alexey Bataev25e5b442015-09-15 12:52:43 +000083 bool hasCancel() const { return HasCancel; }
84
Alexey Bataev18095712014-10-10 12:19:54 +000085 static bool classof(const CGCapturedStmtInfo *Info) {
86 return Info->getKind() == CR_OpenMP;
87 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000088
Alexey Bataev48591dd2016-04-20 04:01:36 +000089 ~CGOpenMPRegionInfo() override = default;
90
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000091protected:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000092 CGOpenMPRegionKind RegionKind;
Hans Wennborg45c74392016-01-12 20:54:36 +000093 RegionCodeGenTy CodeGen;
Alexey Bataev81c7ea02015-07-03 09:56:58 +000094 OpenMPDirectiveKind Kind;
Alexey Bataev25e5b442015-09-15 12:52:43 +000095 bool HasCancel;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000096};
Alexey Bataev18095712014-10-10 12:19:54 +000097
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000098/// API for captured statement code generation in OpenMP constructs.
Alexey Bataev48591dd2016-04-20 04:01:36 +000099class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000100public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000101 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000102 const RegionCodeGenTy &CodeGen,
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +0000103 OpenMPDirectiveKind Kind, bool HasCancel,
104 StringRef HelperName)
Alexey Bataev25e5b442015-09-15 12:52:43 +0000105 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind,
106 HasCancel),
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +0000107 ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000108 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
109 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000110
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000111 /// Get a variable or parameter for storing global thread id
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000112 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000113 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000114
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000115 /// Get the name of the capture helper.
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +0000116 StringRef getHelperName() const override { return HelperName; }
Alexey Bataev18095712014-10-10 12:19:54 +0000117
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000118 static bool classof(const CGCapturedStmtInfo *Info) {
119 return CGOpenMPRegionInfo::classof(Info) &&
120 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
121 ParallelOutlinedRegion;
122 }
123
Alexey Bataev18095712014-10-10 12:19:54 +0000124private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000125 /// A variable or parameter storing global thread id for OpenMP
Alexey Bataev18095712014-10-10 12:19:54 +0000126 /// constructs.
127 const VarDecl *ThreadIDVar;
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +0000128 StringRef HelperName;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000129};
130
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000131/// API for captured statement code generation in OpenMP constructs.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000132class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000133public:
Alexey Bataev48591dd2016-04-20 04:01:36 +0000134 class UntiedTaskActionTy final : public PrePostActionTy {
135 bool Untied;
136 const VarDecl *PartIDVar;
137 const RegionCodeGenTy UntiedCodeGen;
138 llvm::SwitchInst *UntiedSwitch = nullptr;
139
140 public:
141 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar,
142 const RegionCodeGenTy &UntiedCodeGen)
143 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
144 void Enter(CodeGenFunction &CGF) override {
145 if (Untied) {
146 // Emit task switching point.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000147 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue(
Alexey Bataev48591dd2016-04-20 04:01:36 +0000148 CGF.GetAddrOfLocalVar(PartIDVar),
149 PartIDVar->getType()->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000150 llvm::Value *Res =
151 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation());
152 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done.");
Alexey Bataev48591dd2016-04-20 04:01:36 +0000153 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB);
154 CGF.EmitBlock(DoneBB);
155 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
156 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
157 UntiedSwitch->addCase(CGF.Builder.getInt32(0),
158 CGF.Builder.GetInsertBlock());
159 emitUntiedSwitch(CGF);
160 }
161 }
162 void emitUntiedSwitch(CodeGenFunction &CGF) const {
163 if (Untied) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000164 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue(
Alexey Bataev48591dd2016-04-20 04:01:36 +0000165 CGF.GetAddrOfLocalVar(PartIDVar),
166 PartIDVar->getType()->castAs<PointerType>());
167 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
168 PartIdLVal);
169 UntiedCodeGen(CGF);
170 CodeGenFunction::JumpDest CurPoint =
171 CGF.getJumpDestInCurrentScope(".untied.next.");
172 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
173 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
174 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
175 CGF.Builder.GetInsertBlock());
176 CGF.EmitBranchThroughCleanup(CurPoint);
177 CGF.EmitBlock(CurPoint.getBlock());
178 }
179 }
180 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); }
181 };
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000182 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
Alexey Bataev62b63b12015-03-10 07:28:44 +0000183 const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000184 const RegionCodeGenTy &CodeGen,
Alexey Bataev48591dd2016-04-20 04:01:36 +0000185 OpenMPDirectiveKind Kind, bool HasCancel,
186 const UntiedTaskActionTy &Action)
Alexey Bataev25e5b442015-09-15 12:52:43 +0000187 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel),
Alexey Bataev48591dd2016-04-20 04:01:36 +0000188 ThreadIDVar(ThreadIDVar), Action(Action) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000189 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
190 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000191
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000192 /// Get a variable or parameter for storing global thread id
Alexey Bataev62b63b12015-03-10 07:28:44 +0000193 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000194 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000195
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000196 /// Get an LValue for the current ThreadID variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000197 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000198
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000199 /// Get the name of the capture helper.
Alexey Bataev62b63b12015-03-10 07:28:44 +0000200 StringRef getHelperName() const override { return ".omp_outlined."; }
201
Alexey Bataev48591dd2016-04-20 04:01:36 +0000202 void emitUntiedSwitch(CodeGenFunction &CGF) override {
203 Action.emitUntiedSwitch(CGF);
204 }
205
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000206 static bool classof(const CGCapturedStmtInfo *Info) {
207 return CGOpenMPRegionInfo::classof(Info) &&
208 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
209 TaskOutlinedRegion;
210 }
211
Alexey Bataev62b63b12015-03-10 07:28:44 +0000212private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000213 /// A variable or parameter storing global thread id for OpenMP
Alexey Bataev62b63b12015-03-10 07:28:44 +0000214 /// constructs.
215 const VarDecl *ThreadIDVar;
Alexey Bataev48591dd2016-04-20 04:01:36 +0000216 /// Action for emitting code for untied tasks.
217 const UntiedTaskActionTy &Action;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000218};
219
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000220/// API for inlined captured statement code generation in OpenMP
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000221/// constructs.
222class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
223public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000224 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000225 const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000226 OpenMPDirectiveKind Kind, bool HasCancel)
227 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel),
228 OldCSI(OldCSI),
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000229 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000230
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000231 // Retrieve the value of the context parameter.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000232 llvm::Value *getContextValue() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000233 if (OuterRegionInfo)
234 return OuterRegionInfo->getContextValue();
235 llvm_unreachable("No context value for inlined OpenMP region");
236 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000237
Hans Wennborg7eb54642015-09-10 17:07:54 +0000238 void setContextValue(llvm::Value *V) override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000239 if (OuterRegionInfo) {
240 OuterRegionInfo->setContextValue(V);
241 return;
242 }
243 llvm_unreachable("No context value for inlined OpenMP region");
244 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000245
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000246 /// Lookup the captured field decl for a variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000247 const FieldDecl *lookup(const VarDecl *VD) const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000248 if (OuterRegionInfo)
249 return OuterRegionInfo->lookup(VD);
Alexey Bataev69c62a92015-04-15 04:52:20 +0000250 // If there is no outer outlined region,no need to lookup in a list of
251 // captured variables, we can use the original one.
252 return nullptr;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000253 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000254
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000255 FieldDecl *getThisFieldDecl() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000256 if (OuterRegionInfo)
257 return OuterRegionInfo->getThisFieldDecl();
258 return nullptr;
259 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000260
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000261 /// Get a variable or parameter for storing global thread id
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000262 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000263 const VarDecl *getThreadIDVariable() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000264 if (OuterRegionInfo)
265 return OuterRegionInfo->getThreadIDVariable();
266 return nullptr;
267 }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000268
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000269 /// Get an LValue for the current ThreadID variable.
Alexey Bataev311a9282017-10-12 13:51:32 +0000270 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override {
271 if (OuterRegionInfo)
272 return OuterRegionInfo->getThreadIDVariableLValue(CGF);
273 llvm_unreachable("No LValue for inlined OpenMP construct");
274 }
275
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000276 /// Get the name of the capture helper.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000277 StringRef getHelperName() const override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000278 if (auto *OuterRegionInfo = getOldCSI())
279 return OuterRegionInfo->getHelperName();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000280 llvm_unreachable("No helper name for inlined OpenMP construct");
281 }
282
Alexey Bataev48591dd2016-04-20 04:01:36 +0000283 void emitUntiedSwitch(CodeGenFunction &CGF) override {
284 if (OuterRegionInfo)
285 OuterRegionInfo->emitUntiedSwitch(CGF);
286 }
287
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000288 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; }
289
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000290 static bool classof(const CGCapturedStmtInfo *Info) {
291 return CGOpenMPRegionInfo::classof(Info) &&
292 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
293 }
294
Alexey Bataev48591dd2016-04-20 04:01:36 +0000295 ~CGOpenMPInlinedRegionInfo() override = default;
296
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000297private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000298 /// CodeGen info about outer OpenMP region.
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000299 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
300 CGOpenMPRegionInfo *OuterRegionInfo;
Alexey Bataev18095712014-10-10 12:19:54 +0000301};
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000302
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000303/// API for captured statement code generation in OpenMP target
Samuel Antaobed3c462015-10-02 16:14:20 +0000304/// constructs. For this captures, implicit parameters are used instead of the
Samuel Antaoee8fb302016-01-06 13:42:12 +0000305/// captured fields. The name of the target region has to be unique in a given
306/// application so it is provided by the client, because only the client has
307/// the information to generate that.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000308class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo {
Samuel Antaobed3c462015-10-02 16:14:20 +0000309public:
310 CGOpenMPTargetRegionInfo(const CapturedStmt &CS,
Samuel Antaoee8fb302016-01-06 13:42:12 +0000311 const RegionCodeGenTy &CodeGen, StringRef HelperName)
Samuel Antaobed3c462015-10-02 16:14:20 +0000312 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
Samuel Antaoee8fb302016-01-06 13:42:12 +0000313 /*HasCancel=*/false),
314 HelperName(HelperName) {}
Samuel Antaobed3c462015-10-02 16:14:20 +0000315
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000316 /// This is unused for target regions because each starts executing
Samuel Antaobed3c462015-10-02 16:14:20 +0000317 /// with a single thread.
318 const VarDecl *getThreadIDVariable() const override { return nullptr; }
319
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000320 /// Get the name of the capture helper.
Samuel Antaoee8fb302016-01-06 13:42:12 +0000321 StringRef getHelperName() const override { return HelperName; }
Samuel Antaobed3c462015-10-02 16:14:20 +0000322
323 static bool classof(const CGCapturedStmtInfo *Info) {
324 return CGOpenMPRegionInfo::classof(Info) &&
325 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion;
326 }
Samuel Antaoee8fb302016-01-06 13:42:12 +0000327
328private:
329 StringRef HelperName;
Samuel Antaobed3c462015-10-02 16:14:20 +0000330};
331
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000332static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000333 llvm_unreachable("No codegen for expressions");
334}
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000335/// API for generation of expressions captured in a innermost OpenMP
Samuel Antaob68e2db2016-03-03 16:20:23 +0000336/// region.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000337class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000338public:
339 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS)
340 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
341 OMPD_unknown,
342 /*HasCancel=*/false),
343 PrivScope(CGF) {
344 // Make sure the globals captured in the provided statement are local by
345 // using the privatization logic. We assume the same variable is not
346 // captured more than once.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000347 for (const auto &C : CS.captures()) {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000348 if (!C.capturesVariable() && !C.capturesVariableByCopy())
349 continue;
350
351 const VarDecl *VD = C.getCapturedVar();
352 if (VD->isLocalVarDeclOrParm())
353 continue;
354
Bruno Ricci5fc4db72018-12-21 14:10:18 +0000355 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
Samuel Antaob68e2db2016-03-03 16:20:23 +0000356 /*RefersToEnclosingVariableOrCapture=*/false,
357 VD->getType().getNonReferenceType(), VK_LValue,
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000358 C.getLocation());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000359 PrivScope.addPrivate(
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -0800360 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(); });
Samuel Antaob68e2db2016-03-03 16:20:23 +0000361 }
362 (void)PrivScope.Privatize();
363 }
364
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000365 /// Lookup the captured field decl for a variable.
Samuel Antaob68e2db2016-03-03 16:20:23 +0000366 const FieldDecl *lookup(const VarDecl *VD) const override {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000367 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
Samuel Antaob68e2db2016-03-03 16:20:23 +0000368 return FD;
369 return nullptr;
370 }
371
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000372 /// Emit the captured statement body.
Samuel Antaob68e2db2016-03-03 16:20:23 +0000373 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override {
374 llvm_unreachable("No body for expressions");
375 }
376
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000377 /// Get a variable or parameter for storing global thread id
Samuel Antaob68e2db2016-03-03 16:20:23 +0000378 /// inside OpenMP construct.
379 const VarDecl *getThreadIDVariable() const override {
380 llvm_unreachable("No thread id for expressions");
381 }
382
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000383 /// Get the name of the capture helper.
Samuel Antaob68e2db2016-03-03 16:20:23 +0000384 StringRef getHelperName() const override {
385 llvm_unreachable("No helper name for expressions");
386 }
387
388 static bool classof(const CGCapturedStmtInfo *Info) { return false; }
389
390private:
391 /// Private scope to capture global variables.
392 CodeGenFunction::OMPPrivateScope PrivScope;
393};
394
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000395/// RAII for emitting code of OpenMP constructs.
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000396class InlinedOpenMPRegionRAII {
397 CodeGenFunction &CGF;
Alexey Bataev4ba78a42016-04-27 07:56:03 +0000398 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
399 FieldDecl *LambdaThisCaptureField = nullptr;
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000400 const CodeGen::CGBlockInfo *BlockInfo = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000401
402public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000403 /// Constructs region for combined constructs.
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000404 /// \param CodeGen Code generation sequence for combined directives. Includes
405 /// a list of functions used for code generation of implicitly inlined
406 /// regions.
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000407 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000408 OpenMPDirectiveKind Kind, bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000409 : CGF(CGF) {
410 // Start emission for the construct.
Alexey Bataev25e5b442015-09-15 12:52:43 +0000411 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(
412 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
Alexey Bataev4ba78a42016-04-27 07:56:03 +0000413 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
414 LambdaThisCaptureField = CGF.LambdaThisCaptureField;
415 CGF.LambdaThisCaptureField = nullptr;
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000416 BlockInfo = CGF.BlockInfo;
417 CGF.BlockInfo = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000418 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000419
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000420 ~InlinedOpenMPRegionRAII() {
421 // Restore original CapturedStmtInfo only if we're done with code emission.
422 auto *OldCSI =
423 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
424 delete CGF.CapturedStmtInfo;
425 CGF.CapturedStmtInfo = OldCSI;
Alexey Bataev4ba78a42016-04-27 07:56:03 +0000426 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
427 CGF.LambdaThisCaptureField = LambdaThisCaptureField;
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000428 CGF.BlockInfo = BlockInfo;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000429 }
430};
431
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000432/// Values for bit flags used in the ident_t to describe the fields.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000433/// All enumeric elements are named and described in accordance with the code
James Y Knight5d71fc52019-01-29 16:37:27 +0000434/// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h
Alexey Bataev0f87dbe2017-08-14 17:56:13 +0000435enum OpenMPLocationFlags : unsigned {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000436 /// Use trampoline for internal microtask.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000437 OMP_IDENT_IMD = 0x01,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000438 /// Use c-style ident structure.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000439 OMP_IDENT_KMPC = 0x02,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000440 /// Atomic reduction option for kmpc_reduce.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000441 OMP_ATOMIC_REDUCE = 0x10,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000442 /// Explicit 'barrier' directive.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000443 OMP_IDENT_BARRIER_EXPL = 0x20,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000444 /// Implicit barrier in code.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000445 OMP_IDENT_BARRIER_IMPL = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000446 /// Implicit barrier in 'for' directive.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000447 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000448 /// Implicit barrier in 'sections' directive.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000449 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000450 /// Implicit barrier in 'single' directive.
Alexey Bataev0f87dbe2017-08-14 17:56:13 +0000451 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
452 /// Call of __kmp_for_static_init for static loop.
453 OMP_IDENT_WORK_LOOP = 0x200,
454 /// Call of __kmp_for_static_init for sections.
455 OMP_IDENT_WORK_SECTIONS = 0x400,
456 /// Call of __kmp_for_static_init for distribute.
457 OMP_IDENT_WORK_DISTRIBUTE = 0x800,
458 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE)
Alexey Bataev50b3c952016-02-19 10:38:26 +0000459};
460
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +0000461namespace {
462LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
463/// Values for bit flags for marking which requires clauses have been used.
464enum OpenMPOffloadingRequiresDirFlags : int64_t {
465 /// flag undefined.
466 OMP_REQ_UNDEFINED = 0x000,
467 /// no requires clause present.
468 OMP_REQ_NONE = 0x001,
469 /// reverse_offload clause.
470 OMP_REQ_REVERSE_OFFLOAD = 0x002,
471 /// unified_address clause.
472 OMP_REQ_UNIFIED_ADDRESS = 0x004,
473 /// unified_shared_memory clause.
474 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
475 /// dynamic_allocators clause.
476 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010,
477 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS)
478};
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +0000479
480enum OpenMPOffloadingReservedDeviceIDs {
481 /// Device ID if the device was not defined, runtime should get it
482 /// from environment variables in the spec.
483 OMP_DEVICEID_UNDEF = -1,
484};
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +0000485} // anonymous namespace
486
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000487/// Describes ident structure that describes a source location.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000488/// All descriptions are taken from
James Y Knight5d71fc52019-01-29 16:37:27 +0000489/// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h
Alexey Bataev50b3c952016-02-19 10:38:26 +0000490/// Original structure:
491/// typedef struct ident {
492/// kmp_int32 reserved_1; /**< might be used in Fortran;
493/// see above */
494/// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags;
495/// KMP_IDENT_KMPC identifies this union
496/// member */
497/// kmp_int32 reserved_2; /**< not really used in Fortran any more;
498/// see above */
499///#if USE_ITT_BUILD
500/// /* but currently used for storing
501/// region-specific ITT */
502/// /* contextual information. */
503///#endif /* USE_ITT_BUILD */
504/// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for
505/// C++ */
506/// char const *psource; /**< String describing the source location.
507/// The string is composed of semi-colon separated
508// fields which describe the source file,
509/// the function and a pair of line numbers that
510/// delimit the construct.
511/// */
512/// } ident_t;
513enum IdentFieldIndex {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000514 /// might be used in Fortran
Alexey Bataev50b3c952016-02-19 10:38:26 +0000515 IdentField_Reserved_1,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000516 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000517 IdentField_Flags,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000518 /// Not really used in Fortran any more
Alexey Bataev50b3c952016-02-19 10:38:26 +0000519 IdentField_Reserved_2,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000520 /// Source[4] in Fortran, do not use for C++
Alexey Bataev50b3c952016-02-19 10:38:26 +0000521 IdentField_Reserved_3,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000522 /// String describing the source location. The string is composed of
Alexey Bataev50b3c952016-02-19 10:38:26 +0000523 /// semi-colon separated fields which describe the source file, the function
524 /// and a pair of line numbers that delimit the construct.
525 IdentField_PSource
526};
527
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000528/// Schedule types for 'omp for' loops (these enumerators are taken from
Alexey Bataev50b3c952016-02-19 10:38:26 +0000529/// the enum sched_type in kmp.h).
530enum OpenMPSchedType {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000531 /// Lower bound for default (unordered) versions.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000532 OMP_sch_lower = 32,
533 OMP_sch_static_chunked = 33,
534 OMP_sch_static = 34,
535 OMP_sch_dynamic_chunked = 35,
536 OMP_sch_guided_chunked = 36,
537 OMP_sch_runtime = 37,
538 OMP_sch_auto = 38,
Alexey Bataev6cff6242016-05-30 13:05:14 +0000539 /// static with chunk adjustment (e.g., simd)
Samuel Antao4c8035b2016-12-12 18:00:20 +0000540 OMP_sch_static_balanced_chunked = 45,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000541 /// Lower bound for 'ordered' versions.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000542 OMP_ord_lower = 64,
543 OMP_ord_static_chunked = 65,
544 OMP_ord_static = 66,
545 OMP_ord_dynamic_chunked = 67,
546 OMP_ord_guided_chunked = 68,
547 OMP_ord_runtime = 69,
548 OMP_ord_auto = 70,
549 OMP_sch_default = OMP_sch_static,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000550 /// dist_schedule types
Carlo Bertollifc35ad22016-03-07 16:04:49 +0000551 OMP_dist_sch_static_chunked = 91,
552 OMP_dist_sch_static = 92,
Alexey Bataev9ebd7422016-05-10 09:57:36 +0000553 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers.
554 /// Set if the monotonic schedule modifier was present.
555 OMP_sch_modifier_monotonic = (1 << 29),
556 /// Set if the nonmonotonic schedule modifier was present.
557 OMP_sch_modifier_nonmonotonic = (1 << 30),
Alexey Bataev50b3c952016-02-19 10:38:26 +0000558};
559
560enum OpenMPRTLFunction {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000561 /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000562 /// kmpc_micro microtask, ...);
563 OMPRTL__kmpc_fork_call,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000564 /// Call to void *__kmpc_threadprivate_cached(ident_t *loc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000565 /// kmp_int32 global_tid, void *data, size_t size, void ***cache);
566 OMPRTL__kmpc_threadprivate_cached,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000567 /// Call to void __kmpc_threadprivate_register( ident_t *,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000568 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
569 OMPRTL__kmpc_threadprivate_register,
570 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc);
571 OMPRTL__kmpc_global_thread_num,
572 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
573 // kmp_critical_name *crit);
574 OMPRTL__kmpc_critical,
575 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32
576 // global_tid, kmp_critical_name *crit, uintptr_t hint);
577 OMPRTL__kmpc_critical_with_hint,
578 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
579 // kmp_critical_name *crit);
580 OMPRTL__kmpc_end_critical,
581 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
582 // global_tid);
583 OMPRTL__kmpc_cancel_barrier,
584 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
585 OMPRTL__kmpc_barrier,
586 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
587 OMPRTL__kmpc_for_static_fini,
588 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
589 // global_tid);
590 OMPRTL__kmpc_serialized_parallel,
591 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
592 // global_tid);
593 OMPRTL__kmpc_end_serialized_parallel,
594 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
595 // kmp_int32 num_threads);
596 OMPRTL__kmpc_push_num_threads,
597 // Call to void __kmpc_flush(ident_t *loc);
598 OMPRTL__kmpc_flush,
599 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid);
600 OMPRTL__kmpc_master,
601 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid);
602 OMPRTL__kmpc_end_master,
603 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
604 // int end_part);
605 OMPRTL__kmpc_omp_taskyield,
606 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid);
607 OMPRTL__kmpc_single,
608 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid);
609 OMPRTL__kmpc_end_single,
610 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
611 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
612 // kmp_routine_entry_t *task_entry);
613 OMPRTL__kmpc_omp_task_alloc,
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +0000614 // Call to kmp_task_t * __kmpc_omp_target_task_alloc(ident_t *,
615 // kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t,
616 // size_t sizeof_shareds, kmp_routine_entry_t *task_entry,
617 // kmp_int64 device_id);
618 OMPRTL__kmpc_omp_target_task_alloc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000619 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *
620 // new_task);
621 OMPRTL__kmpc_omp_task,
622 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
623 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
624 // kmp_int32 didit);
625 OMPRTL__kmpc_copyprivate,
626 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
627 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
628 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
629 OMPRTL__kmpc_reduce,
630 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
631 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
632 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
633 // *lck);
634 OMPRTL__kmpc_reduce_nowait,
635 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
636 // kmp_critical_name *lck);
637 OMPRTL__kmpc_end_reduce,
638 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
639 // kmp_critical_name *lck);
640 OMPRTL__kmpc_end_reduce_nowait,
641 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
642 // kmp_task_t * new_task);
643 OMPRTL__kmpc_omp_task_begin_if0,
644 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
645 // kmp_task_t * new_task);
646 OMPRTL__kmpc_omp_task_complete_if0,
647 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
648 OMPRTL__kmpc_ordered,
649 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
650 OMPRTL__kmpc_end_ordered,
651 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
652 // global_tid);
653 OMPRTL__kmpc_omp_taskwait,
654 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
655 OMPRTL__kmpc_taskgroup,
656 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
657 OMPRTL__kmpc_end_taskgroup,
658 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
659 // int proc_bind);
660 OMPRTL__kmpc_push_proc_bind,
661 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32
662 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t
663 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
664 OMPRTL__kmpc_omp_task_with_deps,
665 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32
666 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
667 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
668 OMPRTL__kmpc_omp_wait_deps,
669 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
670 // global_tid, kmp_int32 cncl_kind);
671 OMPRTL__kmpc_cancellationpoint,
672 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
673 // kmp_int32 cncl_kind);
674 OMPRTL__kmpc_cancel,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000675 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid,
676 // kmp_int32 num_teams, kmp_int32 thread_limit);
677 OMPRTL__kmpc_push_num_teams,
Alexey Bataev7292c292016-04-25 12:22:29 +0000678 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
679 // microtask, ...);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000680 OMPRTL__kmpc_fork_teams,
Alexey Bataev7292c292016-04-25 12:22:29 +0000681 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
682 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
683 // sched, kmp_uint64 grainsize, void *task_dup);
684 OMPRTL__kmpc_taskloop,
Alexey Bataev8b427062016-05-25 12:36:08 +0000685 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32
686 // num_dims, struct kmp_dim *dims);
687 OMPRTL__kmpc_doacross_init,
688 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid);
689 OMPRTL__kmpc_doacross_fini,
690 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64
691 // *vec);
692 OMPRTL__kmpc_doacross_post,
693 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64
694 // *vec);
695 OMPRTL__kmpc_doacross_wait,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000696 // Call to void *__kmpc_task_reduction_init(int gtid, int num_data, void
697 // *data);
698 OMPRTL__kmpc_task_reduction_init,
699 // Call to void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
700 // *d);
701 OMPRTL__kmpc_task_reduction_get_th_data,
Alexey Bataev6cf7b712019-04-08 19:06:42 +0000702 // Call to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al);
Alexey Bataev4f680db2019-03-19 16:41:16 +0000703 OMPRTL__kmpc_alloc,
Alexey Bataev6cf7b712019-04-08 19:06:42 +0000704 // Call to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al);
Alexey Bataev4f680db2019-03-19 16:41:16 +0000705 OMPRTL__kmpc_free,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000706
707 //
708 // Offloading related calls
709 //
Alexey Bataev7bb33532019-01-07 21:30:43 +0000710 // Call to void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64
711 // size);
712 OMPRTL__kmpc_push_target_tripcount,
George Rokos63bc9d62017-11-21 18:25:12 +0000713 // Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +0000714 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev50b3c952016-02-19 10:38:26 +0000715 // *arg_types);
716 OMPRTL__tgt_target,
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000717 // Call to int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +0000718 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000719 // *arg_types);
720 OMPRTL__tgt_target_nowait,
George Rokos63bc9d62017-11-21 18:25:12 +0000721 // Call to int32_t __tgt_target_teams(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +0000722 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
George Rokos63bc9d62017-11-21 18:25:12 +0000723 // *arg_types, int32_t num_teams, int32_t thread_limit);
Samuel Antaob68e2db2016-03-03 16:20:23 +0000724 OMPRTL__tgt_target_teams,
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000725 // Call to int32_t __tgt_target_teams_nowait(int64_t device_id, void
Alexey Bataeva90fc662019-06-25 16:00:43 +0000726 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000727 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
728 OMPRTL__tgt_target_teams_nowait,
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +0000729 // Call to void __tgt_register_requires(int64_t flags);
730 OMPRTL__tgt_register_requires,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000731 // Call to void __tgt_register_lib(__tgt_bin_desc *desc);
732 OMPRTL__tgt_register_lib,
733 // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc);
734 OMPRTL__tgt_unregister_lib,
George Rokos63bc9d62017-11-21 18:25:12 +0000735 // Call to void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +0000736 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
Samuel Antaodf158d52016-04-27 22:58:19 +0000737 OMPRTL__tgt_target_data_begin,
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000738 // Call to void __tgt_target_data_begin_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +0000739 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000740 // *arg_types);
741 OMPRTL__tgt_target_data_begin_nowait,
George Rokos63bc9d62017-11-21 18:25:12 +0000742 // Call to void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
743 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types);
Samuel Antaodf158d52016-04-27 22:58:19 +0000744 OMPRTL__tgt_target_data_end,
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000745 // Call to void __tgt_target_data_end_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +0000746 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000747 // *arg_types);
748 OMPRTL__tgt_target_data_end_nowait,
George Rokos63bc9d62017-11-21 18:25:12 +0000749 // Call to void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +0000750 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
Samuel Antao8d2d7302016-05-26 18:30:22 +0000751 OMPRTL__tgt_target_data_update,
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000752 // Call to void __tgt_target_data_update_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +0000753 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000754 // *arg_types);
755 OMPRTL__tgt_target_data_update_nowait,
Michael Krused47b9432019-08-05 18:43:21 +0000756 // Call to int64_t __tgt_mapper_num_components(void *rt_mapper_handle);
757 OMPRTL__tgt_mapper_num_components,
758 // Call to void __tgt_push_mapper_component(void *rt_mapper_handle, void
759 // *base, void *begin, int64_t size, int64_t type);
760 OMPRTL__tgt_push_mapper_component,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000761};
762
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000763/// A basic class for pre|post-action for advanced codegen sequence for OpenMP
764/// region.
765class CleanupTy final : public EHScopeStack::Cleanup {
766 PrePostActionTy *Action;
767
768public:
769 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
770 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
771 if (!CGF.HaveInsertPoint())
772 return;
773 Action->Exit(CGF);
774 }
775};
776
Hans Wennborg7eb54642015-09-10 17:07:54 +0000777} // anonymous namespace
Alexey Bataev18095712014-10-10 12:19:54 +0000778
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000779void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const {
780 CodeGenFunction::RunCleanupsScope Scope(CGF);
781 if (PrePostAction) {
782 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction);
783 Callback(CodeGen, CGF, *PrePostAction);
784 } else {
785 PrePostActionTy Action;
786 Callback(CodeGen, CGF, Action);
787 }
788}
789
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000790/// Check if the combiner is a call to UDR combiner and if it is so return the
791/// UDR decl used for reduction.
792static const OMPDeclareReductionDecl *
793getReductionInit(const Expr *ReductionOp) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000794 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
795 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
796 if (const auto *DRE =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000797 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000798 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000799 return DRD;
800 return nullptr;
801}
802
803static void emitInitWithReductionInitializer(CodeGenFunction &CGF,
804 const OMPDeclareReductionDecl *DRD,
805 const Expr *InitOp,
806 Address Private, Address Original,
807 QualType Ty) {
808 if (DRD->getInitializer()) {
809 std::pair<llvm::Function *, llvm::Function *> Reduction =
810 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000811 const auto *CE = cast<CallExpr>(InitOp);
812 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000813 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
814 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000815 const auto *LHSDRE =
816 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr());
817 const auto *RHSDRE =
818 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000819 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
820 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000821 [=]() { return Private; });
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000822 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000823 [=]() { return Original; });
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000824 (void)PrivateScope.Privatize();
825 RValue Func = RValue::get(Reduction.second);
826 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
827 CGF.EmitIgnoredExpr(InitOp);
828 } else {
829 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty);
Alexey Bataev18fa2322018-05-02 14:20:50 +0000830 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"});
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000831 auto *GV = new llvm::GlobalVariable(
832 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,
Alexey Bataev18fa2322018-05-02 14:20:50 +0000833 llvm::GlobalValue::PrivateLinkage, Init, Name);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000834 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty);
835 RValue InitRVal;
836 switch (CGF.getEvaluationKind(Ty)) {
837 case TEK_Scalar:
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000838 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000839 break;
840 case TEK_Complex:
841 InitRVal =
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000842 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation()));
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000843 break;
844 case TEK_Aggregate:
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -0800845 InitRVal = RValue::getAggregate(LV.getAddress());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000846 break;
847 }
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000848 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000849 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal);
850 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(),
851 /*IsInitializer=*/false);
852 }
853}
854
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000855/// Emit initialization of arrays of complex types.
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000856/// \param DestAddr Address of the array.
857/// \param Type Type of array.
858/// \param Init Initial expression of array.
859/// \param SrcAddr Address of the original array.
860static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
Alexey Bataeva7b19152017-10-12 20:03:39 +0000861 QualType Type, bool EmitDeclareReductionInit,
862 const Expr *Init,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000863 const OMPDeclareReductionDecl *DRD,
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000864 Address SrcAddr = Address::invalid()) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000865 // Perform element-by-element initialization.
866 QualType ElementTy;
867
868 // Drill down to the base element type on both arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000869 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
870 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000871 DestAddr =
872 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType());
873 if (DRD)
874 SrcAddr =
875 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType());
876
877 llvm::Value *SrcBegin = nullptr;
878 if (DRD)
879 SrcBegin = SrcAddr.getPointer();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000880 llvm::Value *DestBegin = DestAddr.getPointer();
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000881 // Cast from pointer to array type to pointer to single element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000882 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000883 // The basic structure here is a while-do loop.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000884 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body");
885 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done");
886 llvm::Value *IsEmpty =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000887 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty");
888 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
889
890 // Enter the loop body, making that address the current address.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000891 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000892 CGF.EmitBlock(BodyBB);
893
894 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
895
896 llvm::PHINode *SrcElementPHI = nullptr;
897 Address SrcElementCurrent = Address::invalid();
898 if (DRD) {
899 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2,
900 "omp.arraycpy.srcElementPast");
901 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
902 SrcElementCurrent =
903 Address(SrcElementPHI,
904 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
905 }
906 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI(
907 DestBegin->getType(), 2, "omp.arraycpy.destElementPast");
908 DestElementPHI->addIncoming(DestBegin, EntryBB);
909 Address DestElementCurrent =
910 Address(DestElementPHI,
911 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize));
912
913 // Emit copy.
914 {
915 CodeGenFunction::RunCleanupsScope InitScope(CGF);
Alexey Bataeva7b19152017-10-12 20:03:39 +0000916 if (EmitDeclareReductionInit) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000917 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent,
918 SrcElementCurrent, ElementTy);
919 } else
920 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(),
921 /*IsInitializer=*/false);
922 }
923
924 if (DRD) {
925 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000926 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000927 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
928 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock());
929 }
930
931 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000932 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000933 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
934 // Check whether we've reached the end.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000935 llvm::Value *Done =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000936 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
937 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
938 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock());
939
940 // Done.
941 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
942}
943
944LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) {
Alexey Bataevf47c4b42017-09-26 13:47:31 +0000945 return CGF.EmitOMPSharedLValue(E);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000946}
947
948LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF,
949 const Expr *E) {
950 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E))
951 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false);
952 return LValue();
953}
954
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000955void ReductionCodeGen::emitAggregateInitialization(
956 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal,
957 const OMPDeclareReductionDecl *DRD) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000958 // Emit VarDecl with copy init for arrays.
959 // Get the address of the original variable captured in current
960 // captured region.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000961 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000962 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
Alexey Bataeva7b19152017-10-12 20:03:39 +0000963 bool EmitDeclareReductionInit =
964 DRD && (DRD->getInitializer() || !PrivateVD->hasInit());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000965 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(),
Alexey Bataeva7b19152017-10-12 20:03:39 +0000966 EmitDeclareReductionInit,
967 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
968 : PrivateVD->getInit(),
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -0800969 DRD, SharedLVal.getAddress());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000970}
971
972ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds,
973 ArrayRef<const Expr *> Privates,
974 ArrayRef<const Expr *> ReductionOps) {
975 ClausesData.reserve(Shareds.size());
976 SharedAddresses.reserve(Shareds.size());
977 Sizes.reserve(Shareds.size());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000978 BaseDecls.reserve(Shareds.size());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000979 auto IPriv = Privates.begin();
980 auto IRed = ReductionOps.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000981 for (const Expr *Ref : Shareds) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000982 ClausesData.emplace_back(Ref, *IPriv, *IRed);
983 std::advance(IPriv, 1);
984 std::advance(IRed, 1);
985 }
986}
987
988void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) {
989 assert(SharedAddresses.size() == N &&
990 "Number of generated lvalues must be exactly N.");
Jonas Hahnfeld4525c822017-10-23 19:01:35 +0000991 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
992 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
993 SharedAddresses.emplace_back(First, Second);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000994}
995
996void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000997 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000998 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
999 QualType PrivateType = PrivateVD->getType();
1000 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref);
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001001 if (!PrivateType->isVariablyModifiedType()) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001002 Sizes.emplace_back(
1003 CGF.getTypeSize(
1004 SharedAddresses[N].first.getType().getNonReferenceType()),
1005 nullptr);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001006 return;
1007 }
1008 llvm::Value *Size;
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001009 llvm::Value *SizeInChars;
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08001010 auto *ElemType =
1011 cast<llvm::PointerType>(SharedAddresses[N].first.getPointer()->getType())
1012 ->getElementType();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001013 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001014 if (AsArraySection) {
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08001015 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(),
1016 SharedAddresses[N].first.getPointer());
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001017 Size = CGF.Builder.CreateNUWAdd(
1018 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001019 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001020 } else {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001021 SizeInChars = CGF.getTypeSize(
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001022 SharedAddresses[N].first.getType().getNonReferenceType());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001023 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001024 }
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001025 Sizes.emplace_back(SizeInChars, Size);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001026 CodeGenFunction::OpaqueValueMapping OpaqueMap(
1027 CGF,
1028 cast<OpaqueValueExpr>(
1029 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),
1030 RValue::get(Size));
1031 CGF.EmitVariablyModifiedType(PrivateType);
1032}
1033
1034void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N,
1035 llvm::Value *Size) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001036 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001037 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1038 QualType PrivateType = PrivateVD->getType();
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001039 if (!PrivateType->isVariablyModifiedType()) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001040 assert(!Size && !Sizes[N].second &&
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001041 "Size should be nullptr for non-variably modified reduction "
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001042 "items.");
1043 return;
1044 }
1045 CodeGenFunction::OpaqueValueMapping OpaqueMap(
1046 CGF,
1047 cast<OpaqueValueExpr>(
1048 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),
1049 RValue::get(Size));
1050 CGF.EmitVariablyModifiedType(PrivateType);
1051}
1052
1053void ReductionCodeGen::emitInitialization(
1054 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal,
1055 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) {
1056 assert(SharedAddresses.size() > N && "No variable was generated");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001057 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001058 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001059 const OMPDeclareReductionDecl *DRD =
1060 getReductionInit(ClausesData[N].ReductionOp);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001061 QualType PrivateType = PrivateVD->getType();
1062 PrivateAddr = CGF.Builder.CreateElementBitCast(
1063 PrivateAddr, CGF.ConvertTypeForMem(PrivateType));
1064 QualType SharedType = SharedAddresses[N].first.getType();
1065 SharedLVal = CGF.MakeAddrLValue(
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08001066 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(),
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001067 CGF.ConvertTypeForMem(SharedType)),
Ivan A. Kosarevf5f20462017-10-12 11:29:46 +00001068 SharedType, SharedAddresses[N].first.getBaseInfo(),
Ivan A. Kosarevb9c59f32017-10-31 11:05:34 +00001069 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType));
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001070 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001071 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001072 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) {
1073 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp,
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08001074 PrivateAddr, SharedLVal.getAddress(),
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001075 SharedLVal.getType());
1076 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
1077 !CGF.isTrivialInitializer(PrivateVD->getInit())) {
1078 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr,
1079 PrivateVD->getType().getQualifiers(),
1080 /*IsInitializer=*/false);
1081 }
1082}
1083
1084bool ReductionCodeGen::needCleanups(unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001085 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001086 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1087 QualType PrivateType = PrivateVD->getType();
1088 QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
1089 return DTorKind != QualType::DK_none;
1090}
1091
1092void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N,
1093 Address PrivateAddr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001094 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001095 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1096 QualType PrivateType = PrivateVD->getType();
1097 QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
1098 if (needCleanups(N)) {
1099 PrivateAddr = CGF.Builder.CreateElementBitCast(
1100 PrivateAddr, CGF.ConvertTypeForMem(PrivateType));
1101 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType);
1102 }
1103}
1104
1105static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
1106 LValue BaseLV) {
1107 BaseTy = BaseTy.getNonReferenceType();
1108 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
1109 !CGF.getContext().hasSameType(BaseTy, ElTy)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001110 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) {
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08001111 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(), PtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001112 } else {
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08001113 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(), BaseTy);
Ivan A. Kosarev9f9d1572017-10-30 11:49:31 +00001114 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001115 }
1116 BaseTy = BaseTy->getPointeeType();
1117 }
1118 return CGF.MakeAddrLValue(
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08001119 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(),
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001120 CGF.ConvertTypeForMem(ElTy)),
Ivan A. Kosarevf5f20462017-10-12 11:29:46 +00001121 BaseLV.getType(), BaseLV.getBaseInfo(),
Ivan A. Kosarevb9c59f32017-10-31 11:05:34 +00001122 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType()));
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001123}
1124
1125static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
1126 llvm::Type *BaseLVType, CharUnits BaseLVAlignment,
1127 llvm::Value *Addr) {
1128 Address Tmp = Address::invalid();
1129 Address TopTmp = Address::invalid();
1130 Address MostTopTmp = Address::invalid();
1131 BaseTy = BaseTy.getNonReferenceType();
1132 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
1133 !CGF.getContext().hasSameType(BaseTy, ElTy)) {
1134 Tmp = CGF.CreateMemTemp(BaseTy);
1135 if (TopTmp.isValid())
1136 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp);
1137 else
1138 MostTopTmp = Tmp;
1139 TopTmp = Tmp;
1140 BaseTy = BaseTy->getPointeeType();
1141 }
1142 llvm::Type *Ty = BaseLVType;
1143 if (Tmp.isValid())
1144 Ty = Tmp.getElementType();
1145 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty);
1146 if (Tmp.isValid()) {
1147 CGF.Builder.CreateStore(Addr, Tmp);
1148 return MostTopTmp;
1149 }
1150 return Address(Addr, BaseLVAlignment);
1151}
1152
Alexey Bataev1c44e152018-03-06 18:59:43 +00001153static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001154 const VarDecl *OrigVD = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001155 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) {
1156 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
1157 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001158 Base = TempOASE->getBase()->IgnoreParenImpCasts();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001159 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());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001163 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
1164 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
1165 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001166 Base = TempASE->getBase()->IgnoreParenImpCasts();
1167 DE = cast<DeclRefExpr>(Base);
1168 OrigVD = cast<VarDecl>(DE->getDecl());
1169 }
Alexey Bataev1c44e152018-03-06 18:59:43 +00001170 return OrigVD;
1171}
1172
1173Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N,
1174 Address PrivateAddr) {
1175 const DeclRefExpr *DE;
1176 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001177 BaseDecls.emplace_back(OrigVD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001178 LValue OriginalBaseLValue = CGF.EmitLValue(DE);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001179 LValue BaseLValue =
1180 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
1181 OriginalBaseLValue);
1182 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff(
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08001183 BaseLValue.getPointer(), SharedAddresses[N].first.getPointer());
Jonas Hahnfeld273d2612017-12-06 19:15:28 +00001184 llvm::Value *PrivatePointer =
1185 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1186 PrivateAddr.getPointer(),
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08001187 SharedAddresses[N].first.getAddress().getType());
Jonas Hahnfeld273d2612017-12-06 19:15:28 +00001188 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001189 return castToBase(CGF, OrigVD->getType(),
1190 SharedAddresses[N].first.getType(),
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08001191 OriginalBaseLValue.getAddress().getType(),
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001192 OriginalBaseLValue.getAlignment(), Ptr);
1193 }
1194 BaseDecls.emplace_back(
1195 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl()));
1196 return PrivateAddr;
1197}
1198
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001199bool ReductionCodeGen::usesReductionInitializer(unsigned N) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001200 const OMPDeclareReductionDecl *DRD =
1201 getReductionInit(ClausesData[N].ReductionOp);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001202 return DRD && DRD->getInitializer();
1203}
1204
Alexey Bataev18095712014-10-10 12:19:54 +00001205LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
Alexey Bataev31300ed2016-02-04 11:27:03 +00001206 return CGF.EmitLoadOfPointerLValue(
1207 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
1208 getThreadIDVariable()->getType()->castAs<PointerType>());
Alexey Bataev18095712014-10-10 12:19:54 +00001209}
1210
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001211void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001212 if (!CGF.HaveInsertPoint())
1213 return;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001214 // 1.2.2 OpenMP Language Terminology
1215 // Structured block - An executable statement with a single entry at the
1216 // top and a single exit at the bottom.
1217 // The point of exit cannot be a branch out of the structured block.
1218 // longjmp() and throw() must not violate the entry/exit criteria.
1219 CGF.EHStack.pushTerminate();
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001220 CodeGen(CGF);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001221 CGF.EHStack.popTerminate();
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001222}
1223
Alexey Bataev62b63b12015-03-10 07:28:44 +00001224LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1225 CodeGenFunction &CGF) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00001226 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()),
1227 getThreadIDVariable()->getType(),
Ivan A. Kosarev5f8c0ca2017-10-10 09:39:32 +00001228 AlignmentSource::Decl);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001229}
1230
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001231static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
1232 QualType FieldTy) {
1233 auto *Field = FieldDecl::Create(
1234 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
1235 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
1236 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
1237 Field->setAccess(AS_public);
1238 DC->addDecl(Field);
1239 return Field;
1240}
1241
Alexey Bataev18fa2322018-05-02 14:20:50 +00001242CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator,
1243 StringRef Separator)
1244 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator),
1245 OffloadEntriesInfoManager(CGM) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001246 ASTContext &C = CGM.getContext();
1247 RecordDecl *RD = C.buildImplicitRecord("ident_t");
1248 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
1249 RD->startDefinition();
1250 // reserved_1
1251 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1252 // flags
1253 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1254 // reserved_2
1255 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1256 // reserved_3
1257 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1258 // psource
1259 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
1260 RD->completeDefinition();
1261 IdentQTy = C.getRecordType(RD);
1262 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001263 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
Samuel Antaoee8fb302016-01-06 13:42:12 +00001264
1265 loadOffloadInfoMetadata();
Alexey Bataev9959db52014-05-06 10:08:46 +00001266}
1267
Alexey Bataevc2cd2d42019-10-10 17:28:10 +00001268bool CGOpenMPRuntime::tryEmitDeclareVariant(const GlobalDecl &NewGD,
1269 const GlobalDecl &OldGD,
1270 llvm::GlobalValue *OrigAddr,
1271 bool IsForDefinition) {
Alexey Bataev2df5f122019-10-01 20:18:32 +00001272 // Emit at least a definition for the aliasee if the the address of the
1273 // original function is requested.
1274 if (IsForDefinition || OrigAddr)
1275 (void)CGM.GetAddrOfGlobal(NewGD);
1276 StringRef NewMangledName = CGM.getMangledName(NewGD);
1277 llvm::GlobalValue *Addr = CGM.GetGlobalValue(NewMangledName);
1278 if (Addr && !Addr->isDeclaration()) {
1279 const auto *D = cast<FunctionDecl>(OldGD.getDecl());
1280 const CGFunctionInfo &FI = CGM.getTypes().arrangeGlobalDeclaration(OldGD);
1281 llvm::Type *DeclTy = CGM.getTypes().GetFunctionType(FI);
1282
1283 // Create a reference to the named value. This ensures that it is emitted
1284 // if a deferred decl.
1285 llvm::GlobalValue::LinkageTypes LT = CGM.getFunctionLinkage(OldGD);
1286
1287 // Create the new alias itself, but don't set a name yet.
1288 auto *GA =
1289 llvm::GlobalAlias::create(DeclTy, 0, LT, "", Addr, &CGM.getModule());
1290
1291 if (OrigAddr) {
1292 assert(OrigAddr->isDeclaration() && "Expected declaration");
1293
1294 GA->takeName(OrigAddr);
1295 OrigAddr->replaceAllUsesWith(
1296 llvm::ConstantExpr::getBitCast(GA, OrigAddr->getType()));
1297 OrigAddr->eraseFromParent();
1298 } else {
1299 GA->setName(CGM.getMangledName(OldGD));
1300 }
1301
1302 // Set attributes which are particular to an alias; this is a
1303 // specialization of the attributes which may be set on a global function.
1304 if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakRefAttr>() ||
1305 D->isWeakImported())
1306 GA->setLinkage(llvm::Function::WeakAnyLinkage);
1307
1308 CGM.SetCommonAttributes(OldGD, GA);
1309 return true;
1310 }
1311 return false;
1312}
1313
Alexey Bataev91797552015-03-18 04:13:55 +00001314void CGOpenMPRuntime::clear() {
1315 InternalVars.clear();
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00001316 // Clean non-target variable declarations possibly used only in debug info.
1317 for (const auto &Data : EmittedNonTargetVariables) {
1318 if (!Data.getValue().pointsToAliveValue())
1319 continue;
1320 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue());
1321 if (!GV)
1322 continue;
1323 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1324 continue;
1325 GV->eraseFromParent();
1326 }
Alexey Bataev2df5f122019-10-01 20:18:32 +00001327 // Emit aliases for the deferred aliasees.
1328 for (const auto &Pair : DeferredVariantFunction) {
1329 StringRef MangledName = CGM.getMangledName(Pair.second.second);
1330 llvm::GlobalValue *Addr = CGM.GetGlobalValue(MangledName);
1331 // If not able to emit alias, just emit original declaration.
Alexey Bataevc2cd2d42019-10-10 17:28:10 +00001332 (void)tryEmitDeclareVariant(Pair.second.first, Pair.second.second, Addr,
1333 /*IsForDefinition=*/false);
Alexey Bataev2df5f122019-10-01 20:18:32 +00001334 }
Alexey Bataev91797552015-03-18 04:13:55 +00001335}
1336
Alexey Bataev18fa2322018-05-02 14:20:50 +00001337std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const {
1338 SmallString<128> Buffer;
1339 llvm::raw_svector_ostream OS(Buffer);
1340 StringRef Sep = FirstSeparator;
1341 for (StringRef Part : Parts) {
1342 OS << Sep << Part;
1343 Sep = Separator;
1344 }
1345 return OS.str();
1346}
1347
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001348static llvm::Function *
1349emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
1350 const Expr *CombinerInitializer, const VarDecl *In,
1351 const VarDecl *Out, bool IsCombiner) {
1352 // void .omp_combiner.(Ty *in, Ty *out);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001353 ASTContext &C = CGM.getContext();
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001354 QualType PtrTy = C.getPointerType(Ty).withRestrict();
1355 FunctionArgList Args;
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001356 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(),
Alexey Bataev56223232017-06-09 13:40:18 +00001357 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001358 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(),
Alexey Bataev56223232017-06-09 13:40:18 +00001359 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001360 Args.push_back(&OmpOutParm);
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001361 Args.push_back(&OmpInParm);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001362 const CGFunctionInfo &FnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00001363 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001364 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00001365 std::string Name = CGM.getOpenMPRuntime().getName(
1366 {IsCombiner ? "omp_combiner" : "omp_initializer", ""});
1367 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1368 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00001369 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataev8c5555c2019-05-21 15:11:58 +00001370 if (CGM.getLangOpts().Optimize) {
1371 Fn->removeFnAttr(llvm::Attribute::NoInline);
1372 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1373 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1374 }
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001375 CodeGenFunction CGF(CGM);
1376 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
1377 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions.
Alexey Bataev7cae94e2018-01-04 19:45:16 +00001378 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(),
1379 Out->getLocation());
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001380 CodeGenFunction::OMPPrivateScope Scope(CGF);
1381 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001382 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() {
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001383 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>())
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08001384 .getAddress();
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001385 });
1386 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001387 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() {
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001388 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>())
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08001389 .getAddress();
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001390 });
1391 (void)Scope.Privatize();
Alexey Bataev070f43a2017-09-06 14:49:58 +00001392 if (!IsCombiner && Out->hasInit() &&
1393 !CGF.isTrivialInitializer(Out->getInit())) {
1394 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out),
1395 Out->getType().getQualifiers(),
1396 /*IsInitializer=*/true);
1397 }
1398 if (CombinerInitializer)
1399 CGF.EmitIgnoredExpr(CombinerInitializer);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001400 Scope.ForceCleanup();
1401 CGF.FinishFunction();
1402 return Fn;
1403}
1404
1405void CGOpenMPRuntime::emitUserDefinedReduction(
1406 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) {
1407 if (UDRMap.count(D) > 0)
1408 return;
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001409 llvm::Function *Combiner = emitCombinerOrInitializer(
Alexey Bataeve6aa4692018-09-13 16:54:05 +00001410 CGM, D->getType(), D->getCombiner(),
1411 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()),
1412 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()),
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001413 /*IsCombiner=*/true);
1414 llvm::Function *Initializer = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001415 if (const Expr *Init = D->getInitializer()) {
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001416 Initializer = emitCombinerOrInitializer(
Alexey Bataev070f43a2017-09-06 14:49:58 +00001417 CGM, D->getType(),
1418 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init
1419 : nullptr,
Alexey Bataeve6aa4692018-09-13 16:54:05 +00001420 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()),
1421 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()),
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001422 /*IsCombiner=*/false);
1423 }
Alexey Bataev43a919f2018-04-13 17:48:43 +00001424 UDRMap.try_emplace(D, Combiner, Initializer);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001425 if (CGF) {
1426 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn);
1427 Decls.second.push_back(D);
1428 }
1429}
1430
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001431std::pair<llvm::Function *, llvm::Function *>
1432CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) {
1433 auto I = UDRMap.find(D);
1434 if (I != UDRMap.end())
1435 return I->second;
1436 emitUserDefinedReduction(/*CGF=*/nullptr, D);
1437 return UDRMap.lookup(D);
1438}
1439
James Y Knight9871db02019-02-05 16:42:33 +00001440static llvm::Function *emitParallelOrTeamsOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001441 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS,
1442 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind,
1443 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00001444 assert(ThreadIDVar->getType()->isPointerType() &&
1445 "thread id variable must be of type kmp_int32 *");
Alexey Bataev18095712014-10-10 12:19:54 +00001446 CodeGenFunction CGF(CGM, true);
Alexey Bataev25e5b442015-09-15 12:52:43 +00001447 bool HasCancel = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001448 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001449 HasCancel = OPD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001450 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001451 HasCancel = OPSD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001452 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001453 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001454 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
Alexey Bataev2139ed62017-11-16 18:20:21 +00001455 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001456 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
Alexey Bataev10a54312017-11-27 16:54:08 +00001457 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001458 else if (const auto *OPFD =
1459 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
Alexey Bataev10a54312017-11-27 16:54:08 +00001460 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001461 else if (const auto *OPFD =
Alexey Bataev10a54312017-11-27 16:54:08 +00001462 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1463 HasCancel = OPFD->hasCancel();
Alexey Bataev25e5b442015-09-15 12:52:43 +00001464 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001465 HasCancel, OutlinedHelperName);
Alexey Bataevd157d472015-06-24 03:35:38 +00001466 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev2377fe92015-09-10 08:12:02 +00001467 return CGF.GenerateOpenMPCapturedStmtFunction(*CS);
Alexey Bataev18095712014-10-10 12:19:54 +00001468}
1469
James Y Knight9871db02019-02-05 16:42:33 +00001470llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001471 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1472 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1473 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1474 return emitParallelOrTeamsOutlinedFunction(
1475 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1476}
1477
James Y Knight9871db02019-02-05 16:42:33 +00001478llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001479 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1480 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1481 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1482 return emitParallelOrTeamsOutlinedFunction(
1483 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1484}
1485
James Y Knight9871db02019-02-05 16:42:33 +00001486llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001487 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
Alexey Bataev48591dd2016-04-20 04:01:36 +00001488 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
1489 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
1490 bool Tied, unsigned &NumberOfParts) {
1491 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF,
1492 PrePostActionTy &) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00001493 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc());
1494 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc());
Alexey Bataev48591dd2016-04-20 04:01:36 +00001495 llvm::Value *TaskArgs[] = {
1496 UpLoc, ThreadID,
1497 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1498 TaskTVar->getType()->castAs<PointerType>())
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08001499 .getPointer()};
Alexey Bataev48591dd2016-04-20 04:01:36 +00001500 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs);
1501 };
1502 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1503 UntiedCodeGen);
1504 CodeGen.setAction(Action);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001505 assert(!ThreadIDVar->getType()->isPointerType() &&
1506 "thread id variable must be of type kmp_int32 for tasks");
Alexey Bataev475a7442018-01-12 19:39:11 +00001507 const OpenMPDirectiveKind Region =
1508 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop
1509 : OMPD_task;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001510 const CapturedStmt *CS = D.getCapturedStmt(Region);
1511 const auto *TD = dyn_cast<OMPTaskDirective>(&D);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001512 CodeGenFunction CGF(CGM, true);
Alexey Bataev7292c292016-04-25 12:22:29 +00001513 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
1514 InnermostKind,
1515 TD ? TD->hasCancel() : false, Action);
Alexey Bataevd157d472015-06-24 03:35:38 +00001516 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
James Y Knight9871db02019-02-05 16:42:33 +00001517 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
Alexey Bataev48591dd2016-04-20 04:01:36 +00001518 if (!Tied)
1519 NumberOfParts = Action.getNumberOfParts();
1520 return Res;
Alexey Bataev62b63b12015-03-10 07:28:44 +00001521}
1522
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001523static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM,
1524 const RecordDecl *RD, const CGRecordLayout &RL,
1525 ArrayRef<llvm::Constant *> Data) {
1526 llvm::StructType *StructTy = RL.getLLVMType();
1527 unsigned PrevIdx = 0;
1528 ConstantInitBuilder CIBuilder(CGM);
1529 auto DI = Data.begin();
1530 for (const FieldDecl *FD : RD->fields()) {
1531 unsigned Idx = RL.getLLVMFieldNo(FD);
1532 // Fill the alignment.
1533 for (unsigned I = PrevIdx; I < Idx; ++I)
1534 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I)));
1535 PrevIdx = Idx + 1;
1536 Fields.add(*DI);
1537 ++DI;
1538 }
1539}
1540
1541template <class... As>
1542static llvm::GlobalVariable *
Mike Ricee1ca7b62018-08-29 15:45:11 +00001543createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant,
1544 ArrayRef<llvm::Constant *> Data, const Twine &Name,
1545 As &&... Args) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001546 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1547 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1548 ConstantInitBuilder CIBuilder(CGM);
1549 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType());
1550 buildStructValue(Fields, CGM, RD, RL, Data);
1551 return Fields.finishAndCreateGlobal(
Mike Ricee1ca7b62018-08-29 15:45:11 +00001552 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant,
1553 std::forward<As>(Args)...);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001554}
1555
1556template <typename T>
Benjamin Kramer651d0bf2018-05-15 21:26:47 +00001557static void
1558createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty,
1559 ArrayRef<llvm::Constant *> Data,
1560 T &Parent) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001561 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1562 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1563 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType());
1564 buildStructValue(Fields, CGM, RD, RL, Data);
1565 Fields.finishAndAddTo(Parent);
1566}
1567
Alexey Bataev50b3c952016-02-19 10:38:26 +00001568Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001569 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy);
Alexey Bataevceeaa482018-11-21 21:04:34 +00001570 unsigned Reserved2Flags = getDefaultLocationReserved2Flags();
1571 FlagsTy FlagsKey(Flags, Reserved2Flags);
1572 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey);
Alexey Bataev9959db52014-05-06 10:08:46 +00001573 if (!Entry) {
1574 if (!DefaultOpenMPPSource) {
1575 // Initialize default location for psource field of ident_t structure of
1576 // all ident_t objects. Format is ";file;function;line;column;;".
1577 // Taken from
James Y Knight5d71fc52019-01-29 16:37:27 +00001578 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp
Alexey Bataev9959db52014-05-06 10:08:46 +00001579 DefaultOpenMPPSource =
John McCall7f416cc2015-09-08 08:05:57 +00001580 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001581 DefaultOpenMPPSource =
1582 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
1583 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001584
Alexey Bataevceeaa482018-11-21 21:04:34 +00001585 llvm::Constant *Data[] = {
1586 llvm::ConstantInt::getNullValue(CGM.Int32Ty),
1587 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
1588 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags),
1589 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource};
Mike Ricee1ca7b62018-08-29 15:45:11 +00001590 llvm::GlobalValue *DefaultOpenMPLocation =
Alexey Bataevceeaa482018-11-21 21:04:34 +00001591 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "",
Mike Ricee1ca7b62018-08-29 15:45:11 +00001592 llvm::GlobalValue::PrivateLinkage);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001593 DefaultOpenMPLocation->setUnnamedAddr(
1594 llvm::GlobalValue::UnnamedAddr::Global);
John McCall6c9f1fdb2016-11-19 08:17:24 +00001595
Alexey Bataevceeaa482018-11-21 21:04:34 +00001596 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation;
Alexey Bataev9959db52014-05-06 10:08:46 +00001597 }
John McCall7f416cc2015-09-08 08:05:57 +00001598 return Address(Entry, Align);
Alexey Bataev9959db52014-05-06 10:08:46 +00001599}
1600
Alexey Bataevfd006c42018-10-05 15:08:53 +00001601void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF,
1602 bool AtCurrentPoint) {
1603 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1604 assert(!Elem.second.ServiceInsertPt && "Insert point is set already.");
1605
1606 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty);
1607 if (AtCurrentPoint) {
1608 Elem.second.ServiceInsertPt = new llvm::BitCastInst(
1609 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock());
1610 } else {
1611 Elem.second.ServiceInsertPt =
1612 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt");
1613 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt);
1614 }
1615}
1616
1617void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) {
1618 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1619 if (Elem.second.ServiceInsertPt) {
1620 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt;
1621 Elem.second.ServiceInsertPt = nullptr;
1622 Ptr->eraseFromParent();
1623 }
1624}
1625
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001626llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
1627 SourceLocation Loc,
Alexey Bataev50b3c952016-02-19 10:38:26 +00001628 unsigned Flags) {
1629 Flags |= OMP_IDENT_KMPC;
Alexey Bataev9959db52014-05-06 10:08:46 +00001630 // If no debug info is generated - return global default location.
Benjamin Kramer8c305922016-02-02 11:06:51 +00001631 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo ||
Alexey Bataev9959db52014-05-06 10:08:46 +00001632 Loc.isInvalid())
John McCall7f416cc2015-09-08 08:05:57 +00001633 return getOrCreateDefaultLocation(Flags).getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001634
1635 assert(CGF.CurFn && "No function in current CodeGenFunction.");
1636
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001637 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy);
John McCall7f416cc2015-09-08 08:05:57 +00001638 Address LocValue = Address::invalid();
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001639 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
1640 if (I != OpenMPLocThreadIDMap.end())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001641 LocValue = Address(I->second.DebugLoc, Align);
John McCall7f416cc2015-09-08 08:05:57 +00001642
Alexander Musmanc6388682014-12-15 07:07:06 +00001643 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
1644 // GetOpenMPThreadID was called before this routine.
John McCall7f416cc2015-09-08 08:05:57 +00001645 if (!LocValue.isValid()) {
Alexey Bataev15007ba2014-05-07 06:18:01 +00001646 // Generate "ident_t .kmpc_loc.addr;"
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001647 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr");
Alexey Bataev18095712014-10-10 12:19:54 +00001648 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
John McCall7f416cc2015-09-08 08:05:57 +00001649 Elem.second.DebugLoc = AI.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001650 LocValue = AI;
1651
Alexey Bataevfd006c42018-10-05 15:08:53 +00001652 if (!Elem.second.ServiceInsertPt)
1653 setLocThreadIdInsertPt(CGF);
Alexey Bataev9959db52014-05-06 10:08:46 +00001654 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001655 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001656 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001657 CGF.getTypeSize(IdentQTy));
Alexey Bataev9959db52014-05-06 10:08:46 +00001658 }
1659
1660 // char **psource = &.kmpc_loc_<flags>.addr.psource;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001661 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy);
1662 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin();
1663 LValue PSource =
1664 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource));
Alexey Bataev9959db52014-05-06 10:08:46 +00001665
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001666 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
Alexey Bataevf002aca2014-05-30 05:48:40 +00001667 if (OMPDebugLoc == nullptr) {
1668 SmallString<128> Buffer2;
1669 llvm::raw_svector_ostream OS2(Buffer2);
1670 // Build debug location
1671 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
1672 OS2 << ";" << PLoc.getFilename() << ";";
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001673 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl))
Alexey Bataevf002aca2014-05-30 05:48:40 +00001674 OS2 << FD->getQualifiedNameAsString();
Alexey Bataevf002aca2014-05-30 05:48:40 +00001675 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
1676 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
1677 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
Alexey Bataev9959db52014-05-06 10:08:46 +00001678 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001679 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001680 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource);
Alexey Bataevf002aca2014-05-30 05:48:40 +00001681
John McCall7f416cc2015-09-08 08:05:57 +00001682 // Our callers always pass this to a runtime function, so for
1683 // convenience, go ahead and return a naked pointer.
1684 return LocValue.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001685}
1686
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001687llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
1688 SourceLocation Loc) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001689 assert(CGF.CurFn && "No function in current CodeGenFunction.");
1690
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001691 llvm::Value *ThreadID = nullptr;
Alexey Bataev18095712014-10-10 12:19:54 +00001692 // Check whether we've already cached a load of the thread id in this
1693 // function.
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001694 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
Alexey Bataev18095712014-10-10 12:19:54 +00001695 if (I != OpenMPLocThreadIDMap.end()) {
1696 ThreadID = I->second.ThreadID;
Alexey Bataev03b340a2014-10-21 03:16:40 +00001697 if (ThreadID != nullptr)
1698 return ThreadID;
1699 }
Alexey Bataevaee18552017-08-16 14:01:00 +00001700 // If exceptions are enabled, do not use parameter to avoid possible crash.
Alexey Bataev780f5552019-10-17 17:12:03 +00001701 if (auto *OMPRegionInfo =
1702 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
1703 if (OMPRegionInfo->getThreadIDVariable()) {
1704 // Check if this an outlined function with thread id passed as argument.
1705 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1706 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent();
1707 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions ||
1708 !CGF.getLangOpts().CXXExceptions ||
1709 CGF.Builder.GetInsertBlock() == TopBlock ||
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08001710 !isa<llvm::Instruction>(LVal.getPointer()) ||
1711 cast<llvm::Instruction>(LVal.getPointer())->getParent() == TopBlock ||
1712 cast<llvm::Instruction>(LVal.getPointer())->getParent() ==
Alexey Bataev780f5552019-10-17 17:12:03 +00001713 CGF.Builder.GetInsertBlock()) {
Alexey Bataev1e491372018-01-23 18:44:14 +00001714 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc);
Alexey Bataevaee18552017-08-16 14:01:00 +00001715 // If value loaded in entry block, cache it and use it everywhere in
1716 // function.
Alexey Bataev780f5552019-10-17 17:12:03 +00001717 if (CGF.Builder.GetInsertBlock() == TopBlock) {
Alexey Bataevaee18552017-08-16 14:01:00 +00001718 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1719 Elem.second.ThreadID = ThreadID;
1720 }
1721 return ThreadID;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001722 }
Alexey Bataevd6c57552014-07-25 07:55:17 +00001723 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001724 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001725
1726 // This is not an outlined function region - need to call __kmpc_int32
1727 // kmpc_global_thread_num(ident_t *loc).
1728 // Generate thread id value and cache this value for use across the
1729 // function.
Alexey Bataevfd006c42018-10-05 15:08:53 +00001730 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1731 if (!Elem.second.ServiceInsertPt)
1732 setLocThreadIdInsertPt(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001733 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001734 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001735 llvm::CallInst *Call = CGF.Builder.CreateCall(
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001736 createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
1737 emitUpdateLocation(CGF, Loc));
1738 Call->setCallingConv(CGF.getRuntimeCC());
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001739 Elem.second.ThreadID = Call;
1740 return Call;
Alexey Bataev9959db52014-05-06 10:08:46 +00001741}
1742
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001743void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001744 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataevfd006c42018-10-05 15:08:53 +00001745 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) {
1746 clearLocThreadIdInsertPt(CGF);
Alexey Bataev03b340a2014-10-21 03:16:40 +00001747 OpenMPLocThreadIDMap.erase(CGF.CurFn);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001748 }
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001749 if (FunctionUDRMap.count(CGF.CurFn) > 0) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001750 for(auto *D : FunctionUDRMap[CGF.CurFn])
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001751 UDRMap.erase(D);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001752 FunctionUDRMap.erase(CGF.CurFn);
1753 }
Michael Krused47b9432019-08-05 18:43:21 +00001754 auto I = FunctionUDMMap.find(CGF.CurFn);
1755 if (I != FunctionUDMMap.end()) {
1756 for(auto *D : I->second)
1757 UDMMap.erase(D);
1758 FunctionUDMMap.erase(I);
1759 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001760}
1761
1762llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001763 return IdentTy->getPointerTo();
Alexey Bataev9959db52014-05-06 10:08:46 +00001764}
1765
1766llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001767 if (!Kmpc_MicroTy) {
1768 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
1769 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
1770 llvm::PointerType::getUnqual(CGM.Int32Ty)};
1771 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
1772 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001773 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
1774}
1775
James Y Knight9871db02019-02-05 16:42:33 +00001776llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
1777 llvm::FunctionCallee RTLFn = nullptr;
Alexey Bataev50b3c952016-02-19 10:38:26 +00001778 switch (static_cast<OpenMPRTLFunction>(Function)) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001779 case OMPRTL__kmpc_fork_call: {
1780 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
1781 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +00001782 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1783 getKmpc_MicroPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001784 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001785 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
Alexey Bataev9959db52014-05-06 10:08:46 +00001786 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
James Y Knight9871db02019-02-05 16:42:33 +00001787 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) {
Johannes Doerfertac991bb2019-01-19 05:36:54 +00001788 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
1789 llvm::LLVMContext &Ctx = F->getContext();
1790 llvm::MDBuilder MDB(Ctx);
1791 // Annotate the callback behavior of the __kmpc_fork_call:
1792 // - The callback callee is argument number 2 (microtask).
1793 // - The first two arguments of the callback callee are unknown (-1).
1794 // - All variadic arguments to the __kmpc_fork_call are passed to the
1795 // callback callee.
1796 F->addMetadata(
1797 llvm::LLVMContext::MD_callback,
1798 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
1799 2, {-1, -1},
1800 /* VarArgsArePassed */ true)}));
1801 }
1802 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001803 break;
1804 }
1805 case OMPRTL__kmpc_global_thread_num: {
1806 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +00001807 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001808 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001809 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
Alexey Bataev9959db52014-05-06 10:08:46 +00001810 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
1811 break;
1812 }
Alexey Bataev97720002014-11-11 04:05:39 +00001813 case OMPRTL__kmpc_threadprivate_cached: {
1814 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
1815 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
1816 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1817 CGM.VoidPtrTy, CGM.SizeTy,
1818 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001819 auto *FnTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001820 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
1821 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
1822 break;
1823 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001824 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001825 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
1826 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001827 llvm::Type *TypeParams[] = {
1828 getIdentTyPointerTy(), CGM.Int32Ty,
1829 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001830 auto *FnTy =
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001831 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1832 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
1833 break;
1834 }
Alexey Bataevfc57d162015-12-15 10:55:09 +00001835 case OMPRTL__kmpc_critical_with_hint: {
1836 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid,
1837 // kmp_critical_name *crit, uintptr_t hint);
1838 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1839 llvm::PointerType::getUnqual(KmpCriticalNameTy),
1840 CGM.IntPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001841 auto *FnTy =
Alexey Bataevfc57d162015-12-15 10:55:09 +00001842 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1843 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint");
1844 break;
1845 }
Alexey Bataev97720002014-11-11 04:05:39 +00001846 case OMPRTL__kmpc_threadprivate_register: {
1847 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
1848 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
1849 // typedef void *(*kmpc_ctor)(void *);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001850 auto *KmpcCtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001851 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1852 /*isVarArg*/ false)->getPointerTo();
1853 // typedef void *(*kmpc_cctor)(void *, void *);
1854 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001855 auto *KmpcCopyCtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001856 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001857 /*isVarArg*/ false)
1858 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00001859 // typedef void (*kmpc_dtor)(void *);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001860 auto *KmpcDtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001861 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
1862 ->getPointerTo();
1863 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
1864 KmpcCopyCtorTy, KmpcDtorTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001865 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
Alexey Bataev97720002014-11-11 04:05:39 +00001866 /*isVarArg*/ false);
1867 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
1868 break;
1869 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001870 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001871 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
1872 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001873 llvm::Type *TypeParams[] = {
1874 getIdentTyPointerTy(), CGM.Int32Ty,
1875 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001876 auto *FnTy =
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001877 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1878 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
1879 break;
1880 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001881 case OMPRTL__kmpc_cancel_barrier: {
1882 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
1883 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001884 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001885 auto *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001886 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1887 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001888 break;
1889 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001890 case OMPRTL__kmpc_barrier: {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001891 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001892 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001893 auto *FnTy =
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001894 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1895 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
1896 break;
1897 }
Alexander Musmanc6388682014-12-15 07:07:06 +00001898 case OMPRTL__kmpc_for_static_fini: {
1899 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
1900 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001901 auto *FnTy =
Alexander Musmanc6388682014-12-15 07:07:06 +00001902 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1903 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
1904 break;
1905 }
Alexey Bataevb2059782014-10-13 08:23:51 +00001906 case OMPRTL__kmpc_push_num_threads: {
1907 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
1908 // kmp_int32 num_threads)
1909 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1910 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001911 auto *FnTy =
Alexey Bataevb2059782014-10-13 08:23:51 +00001912 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1913 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
1914 break;
1915 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001916 case OMPRTL__kmpc_serialized_parallel: {
1917 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
1918 // global_tid);
1919 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001920 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001921 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1922 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
1923 break;
1924 }
1925 case OMPRTL__kmpc_end_serialized_parallel: {
1926 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
1927 // global_tid);
1928 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001929 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001930 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1931 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
1932 break;
1933 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001934 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001935 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001936 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001937 auto *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001938 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001939 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
1940 break;
1941 }
Alexey Bataev8d690652014-12-04 07:23:53 +00001942 case OMPRTL__kmpc_master: {
1943 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
1944 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001945 auto *FnTy =
Alexey Bataev8d690652014-12-04 07:23:53 +00001946 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1947 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
1948 break;
1949 }
1950 case OMPRTL__kmpc_end_master: {
1951 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
1952 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001953 auto *FnTy =
Alexey Bataev8d690652014-12-04 07:23:53 +00001954 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1955 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
1956 break;
1957 }
Alexey Bataev9f797f32015-02-05 05:57:51 +00001958 case OMPRTL__kmpc_omp_taskyield: {
1959 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
1960 // int end_part);
1961 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001962 auto *FnTy =
Alexey Bataev9f797f32015-02-05 05:57:51 +00001963 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1964 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
1965 break;
1966 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001967 case OMPRTL__kmpc_single: {
1968 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
1969 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001970 auto *FnTy =
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001971 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1972 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
1973 break;
1974 }
1975 case OMPRTL__kmpc_end_single: {
1976 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
1977 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001978 auto *FnTy =
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001979 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1980 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
1981 break;
1982 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00001983 case OMPRTL__kmpc_omp_task_alloc: {
1984 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
1985 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
1986 // kmp_routine_entry_t *task_entry);
1987 assert(KmpRoutineEntryPtrTy != nullptr &&
1988 "Type kmp_routine_entry_t must be created.");
1989 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1990 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
1991 // Return void * and then cast to particular kmp_task_t type.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001992 auto *FnTy =
Alexey Bataev62b63b12015-03-10 07:28:44 +00001993 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
1994 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
1995 break;
1996 }
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00001997 case OMPRTL__kmpc_omp_target_task_alloc: {
1998 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid,
1999 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
2000 // kmp_routine_entry_t *task_entry, kmp_int64 device_id);
2001 assert(KmpRoutineEntryPtrTy != nullptr &&
2002 "Type kmp_routine_entry_t must be created.");
2003 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
2004 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy,
2005 CGM.Int64Ty};
2006 // Return void * and then cast to particular kmp_task_t type.
2007 auto *FnTy =
2008 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2009 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc");
2010 break;
2011 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002012 case OMPRTL__kmpc_omp_task: {
2013 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2014 // *new_task);
2015 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2016 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002017 auto *FnTy =
Alexey Bataev62b63b12015-03-10 07:28:44 +00002018 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2019 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
2020 break;
2021 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00002022 case OMPRTL__kmpc_copyprivate: {
2023 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
Alexey Bataev66beaa92015-04-30 03:47:32 +00002024 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
Alexey Bataeva63048e2015-03-23 06:18:07 +00002025 // kmp_int32 didit);
2026 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2027 auto *CpyFnTy =
2028 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
Alexey Bataev66beaa92015-04-30 03:47:32 +00002029 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
Alexey Bataeva63048e2015-03-23 06:18:07 +00002030 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
2031 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002032 auto *FnTy =
Alexey Bataeva63048e2015-03-23 06:18:07 +00002033 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2034 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
2035 break;
2036 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002037 case OMPRTL__kmpc_reduce: {
2038 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
2039 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
2040 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
2041 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2042 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
2043 /*isVarArg=*/false);
2044 llvm::Type *TypeParams[] = {
2045 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
2046 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
2047 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002048 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002049 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2050 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
2051 break;
2052 }
2053 case OMPRTL__kmpc_reduce_nowait: {
2054 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
2055 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
2056 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
2057 // *lck);
2058 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2059 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
2060 /*isVarArg=*/false);
2061 llvm::Type *TypeParams[] = {
2062 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
2063 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
2064 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002065 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002066 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2067 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
2068 break;
2069 }
2070 case OMPRTL__kmpc_end_reduce: {
2071 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
2072 // kmp_critical_name *lck);
2073 llvm::Type *TypeParams[] = {
2074 getIdentTyPointerTy(), CGM.Int32Ty,
2075 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002076 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002077 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2078 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
2079 break;
2080 }
2081 case OMPRTL__kmpc_end_reduce_nowait: {
2082 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
2083 // kmp_critical_name *lck);
2084 llvm::Type *TypeParams[] = {
2085 getIdentTyPointerTy(), CGM.Int32Ty,
2086 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002087 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002088 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2089 RTLFn =
2090 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
2091 break;
2092 }
Alexey Bataev1d677132015-04-22 13:57:31 +00002093 case OMPRTL__kmpc_omp_task_begin_if0: {
2094 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2095 // *new_task);
2096 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2097 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002098 auto *FnTy =
Alexey Bataev1d677132015-04-22 13:57:31 +00002099 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2100 RTLFn =
2101 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
2102 break;
2103 }
2104 case OMPRTL__kmpc_omp_task_complete_if0: {
2105 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2106 // *new_task);
2107 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2108 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002109 auto *FnTy =
Alexey Bataev1d677132015-04-22 13:57:31 +00002110 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2111 RTLFn = CGM.CreateRuntimeFunction(FnTy,
2112 /*Name=*/"__kmpc_omp_task_complete_if0");
2113 break;
2114 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002115 case OMPRTL__kmpc_ordered: {
2116 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
2117 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002118 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002119 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2120 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
2121 break;
2122 }
2123 case OMPRTL__kmpc_end_ordered: {
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002124 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002125 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002126 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002127 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2128 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
2129 break;
2130 }
Alexey Bataev8b8e2022015-04-27 05:22:09 +00002131 case OMPRTL__kmpc_omp_taskwait: {
2132 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
2133 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002134 auto *FnTy =
Alexey Bataev8b8e2022015-04-27 05:22:09 +00002135 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2136 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
2137 break;
2138 }
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002139 case OMPRTL__kmpc_taskgroup: {
2140 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
2141 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002142 auto *FnTy =
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002143 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2144 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
2145 break;
2146 }
2147 case OMPRTL__kmpc_end_taskgroup: {
2148 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
2149 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002150 auto *FnTy =
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002151 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2152 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
2153 break;
2154 }
Alexey Bataev7f210c62015-06-18 13:40:03 +00002155 case OMPRTL__kmpc_push_proc_bind: {
2156 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
2157 // int proc_bind)
2158 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002159 auto *FnTy =
Alexey Bataev7f210c62015-06-18 13:40:03 +00002160 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2161 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
2162 break;
2163 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002164 case OMPRTL__kmpc_omp_task_with_deps: {
2165 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
2166 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
2167 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
2168 llvm::Type *TypeParams[] = {
2169 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
2170 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002171 auto *FnTy =
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002172 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2173 RTLFn =
2174 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
2175 break;
2176 }
2177 case OMPRTL__kmpc_omp_wait_deps: {
2178 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
2179 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
2180 // kmp_depend_info_t *noalias_dep_list);
2181 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2182 CGM.Int32Ty, CGM.VoidPtrTy,
2183 CGM.Int32Ty, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002184 auto *FnTy =
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002185 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2186 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
2187 break;
2188 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00002189 case OMPRTL__kmpc_cancellationpoint: {
2190 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
2191 // global_tid, kmp_int32 cncl_kind)
2192 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002193 auto *FnTy =
Alexey Bataev0f34da12015-07-02 04:17:07 +00002194 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2195 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
2196 break;
2197 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002198 case OMPRTL__kmpc_cancel: {
2199 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
2200 // kmp_int32 cncl_kind)
2201 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002202 auto *FnTy =
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002203 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2204 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
2205 break;
2206 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002207 case OMPRTL__kmpc_push_num_teams: {
2208 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid,
2209 // kmp_int32 num_teams, kmp_int32 num_threads)
2210 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
2211 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002212 auto *FnTy =
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002213 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2214 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams");
2215 break;
2216 }
2217 case OMPRTL__kmpc_fork_teams: {
2218 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
2219 // microtask, ...);
2220 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2221 getKmpc_MicroPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002222 auto *FnTy =
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002223 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
2224 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams");
James Y Knight9871db02019-02-05 16:42:33 +00002225 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) {
Johannes Doerfertac991bb2019-01-19 05:36:54 +00002226 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
2227 llvm::LLVMContext &Ctx = F->getContext();
2228 llvm::MDBuilder MDB(Ctx);
2229 // Annotate the callback behavior of the __kmpc_fork_teams:
2230 // - The callback callee is argument number 2 (microtask).
2231 // - The first two arguments of the callback callee are unknown (-1).
2232 // - All variadic arguments to the __kmpc_fork_teams are passed to the
2233 // callback callee.
2234 F->addMetadata(
2235 llvm::LLVMContext::MD_callback,
2236 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
2237 2, {-1, -1},
2238 /* VarArgsArePassed */ true)}));
2239 }
2240 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002241 break;
2242 }
Alexey Bataev7292c292016-04-25 12:22:29 +00002243 case OMPRTL__kmpc_taskloop: {
2244 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
2245 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
2246 // sched, kmp_uint64 grainsize, void *task_dup);
2247 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
2248 CGM.IntTy,
2249 CGM.VoidPtrTy,
2250 CGM.IntTy,
2251 CGM.Int64Ty->getPointerTo(),
2252 CGM.Int64Ty->getPointerTo(),
2253 CGM.Int64Ty,
2254 CGM.IntTy,
2255 CGM.IntTy,
2256 CGM.Int64Ty,
2257 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002258 auto *FnTy =
Alexey Bataev7292c292016-04-25 12:22:29 +00002259 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2260 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop");
2261 break;
2262 }
Alexey Bataev8b427062016-05-25 12:36:08 +00002263 case OMPRTL__kmpc_doacross_init: {
2264 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32
2265 // num_dims, struct kmp_dim *dims);
2266 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
2267 CGM.Int32Ty,
2268 CGM.Int32Ty,
2269 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002270 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002271 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2272 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init");
2273 break;
2274 }
2275 case OMPRTL__kmpc_doacross_fini: {
2276 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid);
2277 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002278 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002279 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2280 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini");
2281 break;
2282 }
2283 case OMPRTL__kmpc_doacross_post: {
2284 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64
2285 // *vec);
2286 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2287 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002288 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002289 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2290 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post");
2291 break;
2292 }
2293 case OMPRTL__kmpc_doacross_wait: {
2294 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64
2295 // *vec);
2296 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2297 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002298 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002299 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2300 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait");
2301 break;
2302 }
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002303 case OMPRTL__kmpc_task_reduction_init: {
2304 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void
2305 // *data);
2306 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002307 auto *FnTy =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002308 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2309 RTLFn =
2310 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init");
2311 break;
2312 }
2313 case OMPRTL__kmpc_task_reduction_get_th_data: {
2314 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
2315 // *d);
2316 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002317 auto *FnTy =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002318 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2319 RTLFn = CGM.CreateRuntimeFunction(
2320 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data");
2321 break;
2322 }
Alexey Bataev4f680db2019-03-19 16:41:16 +00002323 case OMPRTL__kmpc_alloc: {
Alexey Bataev6cf7b712019-04-08 19:06:42 +00002324 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t
2325 // al); omp_allocator_handle_t type is void *.
2326 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy};
Alexey Bataev4f680db2019-03-19 16:41:16 +00002327 auto *FnTy =
2328 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2329 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc");
2330 break;
2331 }
2332 case OMPRTL__kmpc_free: {
Alexey Bataev6cf7b712019-04-08 19:06:42 +00002333 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t
2334 // al); omp_allocator_handle_t type is void *.
2335 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataev4f680db2019-03-19 16:41:16 +00002336 auto *FnTy =
2337 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2338 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free");
2339 break;
2340 }
Alexey Bataev7bb33532019-01-07 21:30:43 +00002341 case OMPRTL__kmpc_push_target_tripcount: {
2342 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64
2343 // size);
2344 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty};
2345 llvm::FunctionType *FnTy =
2346 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2347 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount");
2348 break;
2349 }
Samuel Antaobed3c462015-10-02 16:14:20 +00002350 case OMPRTL__tgt_target: {
George Rokos63bc9d62017-11-21 18:25:12 +00002351 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002352 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Samuel Antaobed3c462015-10-02 16:14:20 +00002353 // *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002354 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaobed3c462015-10-02 16:14:20 +00002355 CGM.VoidPtrTy,
2356 CGM.Int32Ty,
2357 CGM.VoidPtrPtrTy,
2358 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002359 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002360 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002361 auto *FnTy =
Samuel Antaobed3c462015-10-02 16:14:20 +00002362 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2363 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
2364 break;
2365 }
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002366 case OMPRTL__tgt_target_nowait: {
2367 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002368 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes,
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002369 // int64_t *arg_types);
2370 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2371 CGM.VoidPtrTy,
2372 CGM.Int32Ty,
2373 CGM.VoidPtrPtrTy,
2374 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002375 CGM.Int64Ty->getPointerTo(),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002376 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002377 auto *FnTy =
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002378 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2379 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait");
2380 break;
2381 }
Samuel Antaob68e2db2016-03-03 16:20:23 +00002382 case OMPRTL__tgt_target_teams: {
George Rokos63bc9d62017-11-21 18:25:12 +00002383 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002384 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes,
George Rokos63bc9d62017-11-21 18:25:12 +00002385 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
2386 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaob68e2db2016-03-03 16:20:23 +00002387 CGM.VoidPtrTy,
2388 CGM.Int32Ty,
2389 CGM.VoidPtrPtrTy,
2390 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002391 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002392 CGM.Int64Ty->getPointerTo(),
Samuel Antaob68e2db2016-03-03 16:20:23 +00002393 CGM.Int32Ty,
2394 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002395 auto *FnTy =
Samuel Antaob68e2db2016-03-03 16:20:23 +00002396 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2397 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams");
2398 break;
2399 }
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002400 case OMPRTL__tgt_target_teams_nowait: {
2401 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void
Alexey Bataeva90fc662019-06-25 16:00:43 +00002402 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002403 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
2404 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2405 CGM.VoidPtrTy,
2406 CGM.Int32Ty,
2407 CGM.VoidPtrPtrTy,
2408 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002409 CGM.Int64Ty->getPointerTo(),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002410 CGM.Int64Ty->getPointerTo(),
2411 CGM.Int32Ty,
2412 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002413 auto *FnTy =
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002414 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2415 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait");
2416 break;
2417 }
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00002418 case OMPRTL__tgt_register_requires: {
2419 // Build void __tgt_register_requires(int64_t flags);
2420 llvm::Type *TypeParams[] = {CGM.Int64Ty};
2421 auto *FnTy =
2422 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2423 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires");
2424 break;
2425 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00002426 case OMPRTL__tgt_register_lib: {
2427 // Build void __tgt_register_lib(__tgt_bin_desc *desc);
2428 QualType ParamTy =
2429 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
2430 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002431 auto *FnTy =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002432 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2433 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib");
2434 break;
2435 }
2436 case OMPRTL__tgt_unregister_lib: {
2437 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc);
2438 QualType ParamTy =
2439 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
2440 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002441 auto *FnTy =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002442 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2443 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib");
2444 break;
2445 }
Samuel Antaodf158d52016-04-27 22:58:19 +00002446 case OMPRTL__tgt_target_data_begin: {
George Rokos63bc9d62017-11-21 18:25:12 +00002447 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002448 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002449 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaodf158d52016-04-27 22:58:19 +00002450 CGM.Int32Ty,
2451 CGM.VoidPtrPtrTy,
2452 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002453 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002454 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002455 auto *FnTy =
Samuel Antaodf158d52016-04-27 22:58:19 +00002456 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2457 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin");
2458 break;
2459 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002460 case OMPRTL__tgt_target_data_begin_nowait: {
2461 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002462 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002463 // *arg_types);
2464 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2465 CGM.Int32Ty,
2466 CGM.VoidPtrPtrTy,
2467 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002468 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002469 CGM.Int64Ty->getPointerTo()};
2470 auto *FnTy =
2471 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2472 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait");
2473 break;
2474 }
Samuel Antaodf158d52016-04-27 22:58:19 +00002475 case OMPRTL__tgt_target_data_end: {
George Rokos63bc9d62017-11-21 18:25:12 +00002476 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002477 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002478 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaodf158d52016-04-27 22:58:19 +00002479 CGM.Int32Ty,
2480 CGM.VoidPtrPtrTy,
2481 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002482 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002483 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002484 auto *FnTy =
Samuel Antaodf158d52016-04-27 22:58:19 +00002485 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2486 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end");
2487 break;
2488 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002489 case OMPRTL__tgt_target_data_end_nowait: {
2490 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002491 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002492 // *arg_types);
2493 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2494 CGM.Int32Ty,
2495 CGM.VoidPtrPtrTy,
2496 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002497 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002498 CGM.Int64Ty->getPointerTo()};
2499 auto *FnTy =
2500 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2501 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait");
2502 break;
2503 }
Samuel Antao8d2d7302016-05-26 18:30:22 +00002504 case OMPRTL__tgt_target_data_update: {
George Rokos63bc9d62017-11-21 18:25:12 +00002505 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002506 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002507 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antao8d2d7302016-05-26 18:30:22 +00002508 CGM.Int32Ty,
2509 CGM.VoidPtrPtrTy,
2510 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002511 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002512 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002513 auto *FnTy =
Samuel Antao8d2d7302016-05-26 18:30:22 +00002514 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2515 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update");
2516 break;
2517 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002518 case OMPRTL__tgt_target_data_update_nowait: {
2519 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002520 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002521 // *arg_types);
2522 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2523 CGM.Int32Ty,
2524 CGM.VoidPtrPtrTy,
2525 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002526 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002527 CGM.Int64Ty->getPointerTo()};
2528 auto *FnTy =
2529 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2530 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait");
2531 break;
2532 }
Michael Krused47b9432019-08-05 18:43:21 +00002533 case OMPRTL__tgt_mapper_num_components: {
2534 // Build int64_t __tgt_mapper_num_components(void *rt_mapper_handle);
2535 llvm::Type *TypeParams[] = {CGM.VoidPtrTy};
2536 auto *FnTy =
2537 llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false);
2538 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_mapper_num_components");
2539 break;
2540 }
2541 case OMPRTL__tgt_push_mapper_component: {
2542 // Build void __tgt_push_mapper_component(void *rt_mapper_handle, void
2543 // *base, void *begin, int64_t size, int64_t type);
2544 llvm::Type *TypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.VoidPtrTy,
2545 CGM.Int64Ty, CGM.Int64Ty};
2546 auto *FnTy =
2547 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2548 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_push_mapper_component");
2549 break;
2550 }
Alexey Bataev9959db52014-05-06 10:08:46 +00002551 }
Alexey Bataev50b3c952016-02-19 10:38:26 +00002552 assert(RTLFn && "Unable to find OpenMP runtime function");
Alexey Bataev9959db52014-05-06 10:08:46 +00002553 return RTLFn;
2554}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00002555
James Y Knight9871db02019-02-05 16:42:33 +00002556llvm::FunctionCallee
2557CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman21212e42015-03-13 10:38:23 +00002558 assert((IVSize == 32 || IVSize == 64) &&
2559 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002560 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
2561 : "__kmpc_for_static_init_4u")
2562 : (IVSigned ? "__kmpc_for_static_init_8"
2563 : "__kmpc_for_static_init_8u");
2564 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
2565 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
Alexander Musman21212e42015-03-13 10:38:23 +00002566 llvm::Type *TypeParams[] = {
2567 getIdentTyPointerTy(), // loc
2568 CGM.Int32Ty, // tid
2569 CGM.Int32Ty, // schedtype
2570 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
2571 PtrTy, // p_lower
2572 PtrTy, // p_upper
2573 PtrTy, // p_stride
2574 ITy, // incr
2575 ITy // chunk
2576 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002577 auto *FnTy =
Alexander Musman21212e42015-03-13 10:38:23 +00002578 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2579 return CGM.CreateRuntimeFunction(FnTy, Name);
2580}
2581
James Y Knight9871db02019-02-05 16:42:33 +00002582llvm::FunctionCallee
2583CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002584 assert((IVSize == 32 || IVSize == 64) &&
2585 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002586 StringRef Name =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002587 IVSize == 32
2588 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
2589 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002590 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
Alexander Musman92bdaab2015-03-12 13:37:50 +00002591 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
2592 CGM.Int32Ty, // tid
2593 CGM.Int32Ty, // schedtype
2594 ITy, // lower
2595 ITy, // upper
2596 ITy, // stride
2597 ITy // chunk
2598 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002599 auto *FnTy =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002600 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2601 return CGM.CreateRuntimeFunction(FnTy, Name);
2602}
2603
James Y Knight9871db02019-02-05 16:42:33 +00002604llvm::FunctionCallee
2605CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002606 assert((IVSize == 32 || IVSize == 64) &&
2607 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002608 StringRef Name =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002609 IVSize == 32
2610 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
2611 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
2612 llvm::Type *TypeParams[] = {
2613 getIdentTyPointerTy(), // loc
2614 CGM.Int32Ty, // tid
2615 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002616 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002617 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2618 return CGM.CreateRuntimeFunction(FnTy, Name);
2619}
2620
James Y Knight9871db02019-02-05 16:42:33 +00002621llvm::FunctionCallee
2622CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002623 assert((IVSize == 32 || IVSize == 64) &&
2624 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002625 StringRef Name =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002626 IVSize == 32
2627 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
2628 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002629 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
2630 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002631 llvm::Type *TypeParams[] = {
2632 getIdentTyPointerTy(), // loc
2633 CGM.Int32Ty, // tid
2634 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
2635 PtrTy, // p_lower
2636 PtrTy, // p_upper
2637 PtrTy // p_stride
2638 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002639 auto *FnTy =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002640 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2641 return CGM.CreateRuntimeFunction(FnTy, Name);
2642}
2643
Gheorghe-Teodor Bercea625f59d2019-08-01 21:15:58 +00002644/// Obtain information that uniquely identifies a target entry. This
2645/// consists of the file and device IDs as well as line number associated with
2646/// the relevant entry source location.
2647static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
2648 unsigned &DeviceID, unsigned &FileID,
2649 unsigned &LineNum) {
2650 SourceManager &SM = C.getSourceManager();
2651
2652 // The loc should be always valid and have a file ID (the user cannot use
2653 // #pragma directives in macros)
2654
2655 assert(Loc.isValid() && "Source location is expected to be always valid.");
2656
2657 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
2658 assert(PLoc.isValid() && "Source location is expected to be always valid.");
2659
2660 llvm::sys::fs::UniqueID ID;
2661 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
2662 SM.getDiagnostics().Report(diag::err_cannot_open_file)
2663 << PLoc.getFilename() << EC.message();
2664
2665 DeviceID = ID.getDevice();
2666 FileID = ID.getFile();
2667 LineNum = PLoc.getLine();
2668}
2669
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002670Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) {
Alexey Bataev03f270c2018-03-30 18:31:07 +00002671 if (CGM.getLangOpts().OpenMPSimd)
2672 return Address::invalid();
Alexey Bataev92327c52018-03-26 16:40:55 +00002673 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00002674 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002675 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link ||
2676 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
2677 HasRequiresUnifiedSharedMemory))) {
Alexey Bataev92327c52018-03-26 16:40:55 +00002678 SmallString<64> PtrName;
2679 {
2680 llvm::raw_svector_ostream OS(PtrName);
Gheorghe-Teodor Bercea625f59d2019-08-01 21:15:58 +00002681 OS << CGM.getMangledName(GlobalDecl(VD));
2682 if (!VD->isExternallyVisible()) {
2683 unsigned DeviceID, FileID, Line;
2684 getTargetEntryUniqueInfo(CGM.getContext(),
2685 VD->getCanonicalDecl()->getBeginLoc(),
2686 DeviceID, FileID, Line);
2687 OS << llvm::format("_%x", FileID);
2688 }
2689 OS << "_decl_tgt_ref_ptr";
Alexey Bataev92327c52018-03-26 16:40:55 +00002690 }
2691 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName);
2692 if (!Ptr) {
2693 QualType PtrTy = CGM.getContext().getPointerType(VD->getType());
2694 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy),
2695 PtrName);
Gheorghe-Teodor Bercea625f59d2019-08-01 21:15:58 +00002696
2697 auto *GV = cast<llvm::GlobalVariable>(Ptr);
2698 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
2699
2700 if (!CGM.getLangOpts().OpenMPIsDevice)
Alexey Bataev03f270c2018-03-30 18:31:07 +00002701 GV->setInitializer(CGM.GetAddrOfGlobal(VD));
Alexey Bataev03f270c2018-03-30 18:31:07 +00002702 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr));
Alexey Bataev92327c52018-03-26 16:40:55 +00002703 }
2704 return Address(Ptr, CGM.getContext().getDeclAlign(VD));
2705 }
2706 return Address::invalid();
2707}
2708
Alexey Bataev97720002014-11-11 04:05:39 +00002709llvm::Constant *
2710CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002711 assert(!CGM.getLangOpts().OpenMPUseTLS ||
2712 !CGM.getContext().getTargetInfo().isTLSSupported());
Alexey Bataev97720002014-11-11 04:05:39 +00002713 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev18fa2322018-05-02 14:20:50 +00002714 std::string Suffix = getName({"cache", ""});
2715 return getOrCreateInternalVariable(
2716 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix));
Alexey Bataev97720002014-11-11 04:05:39 +00002717}
2718
John McCall7f416cc2015-09-08 08:05:57 +00002719Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
2720 const VarDecl *VD,
2721 Address VDAddr,
2722 SourceLocation Loc) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002723 if (CGM.getLangOpts().OpenMPUseTLS &&
2724 CGM.getContext().getTargetInfo().isTLSSupported())
2725 return VDAddr;
2726
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002727 llvm::Type *VarTy = VDAddr.getElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002728 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00002729 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
2730 CGM.Int8PtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00002731 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
2732 getOrCreateThreadPrivateCache(VD)};
John McCall7f416cc2015-09-08 08:05:57 +00002733 return Address(CGF.EmitRuntimeCall(
2734 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
2735 VDAddr.getAlignment());
Alexey Bataev97720002014-11-11 04:05:39 +00002736}
2737
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002738void CGOpenMPRuntime::emitThreadPrivateVarInit(
John McCall7f416cc2015-09-08 08:05:57 +00002739 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
Alexey Bataev97720002014-11-11 04:05:39 +00002740 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
2741 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
2742 // library.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002743 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002744 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +00002745 OMPLoc);
2746 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
2747 // to register constructor/destructor for variable.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002748 llvm::Value *Args[] = {
2749 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy),
2750 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +00002751 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002752 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +00002753}
2754
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002755llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
John McCall7f416cc2015-09-08 08:05:57 +00002756 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
Alexey Bataev97720002014-11-11 04:05:39 +00002757 bool PerformInit, CodeGenFunction *CGF) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002758 if (CGM.getLangOpts().OpenMPUseTLS &&
2759 CGM.getContext().getTargetInfo().isTLSSupported())
2760 return nullptr;
2761
Alexey Bataev97720002014-11-11 04:05:39 +00002762 VD = VD->getDefinition(CGM.getContext());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00002763 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) {
Alexey Bataev97720002014-11-11 04:05:39 +00002764 QualType ASTTy = VD->getType();
2765
2766 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002767 const Expr *Init = VD->getAnyInitializer();
Alexey Bataev97720002014-11-11 04:05:39 +00002768 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
2769 // Generate function that re-emits the declaration's initializer into the
2770 // threadprivate copy of the variable VD
2771 CodeGenFunction CtorCGF(CGM);
2772 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002773 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
2774 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
Alexey Bataev56223232017-06-09 13:40:18 +00002775 ImplicitParamDecl::Other);
Alexey Bataev97720002014-11-11 04:05:39 +00002776 Args.push_back(&Dst);
2777
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002778 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
John McCallc56a8b32016-03-11 04:30:31 +00002779 CGM.getContext().VoidPtrTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002780 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002781 std::string Name = getName({"__kmpc_global_ctor_", ""});
2782 llvm::Function *Fn =
2783 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002784 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002785 Args, Loc, Loc);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002786 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002787 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00002788 CGM.getContext().VoidPtrTy, Dst.getLocation());
John McCall7f416cc2015-09-08 08:05:57 +00002789 Address Arg = Address(ArgVal, VDAddr.getAlignment());
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002790 Arg = CtorCGF.Builder.CreateElementBitCast(
2791 Arg, CtorCGF.ConvertTypeForMem(ASTTy));
Alexey Bataev97720002014-11-11 04:05:39 +00002792 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
2793 /*IsInitializer=*/true);
2794 ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002795 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00002796 CGM.getContext().VoidPtrTy, Dst.getLocation());
2797 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
2798 CtorCGF.FinishFunction();
2799 Ctor = Fn;
2800 }
2801 if (VD->getType().isDestructedType() != QualType::DK_none) {
2802 // Generate function that emits destructor call for the threadprivate copy
2803 // of the variable VD
2804 CodeGenFunction DtorCGF(CGM);
2805 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002806 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
2807 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
Alexey Bataev56223232017-06-09 13:40:18 +00002808 ImplicitParamDecl::Other);
Alexey Bataev97720002014-11-11 04:05:39 +00002809 Args.push_back(&Dst);
2810
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002811 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
John McCallc56a8b32016-03-11 04:30:31 +00002812 CGM.getContext().VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002813 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002814 std::string Name = getName({"__kmpc_global_dtor_", ""});
2815 llvm::Function *Fn =
2816 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
Adrian Prantl1858c662016-04-24 22:22:29 +00002817 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
Alexey Bataev97720002014-11-11 04:05:39 +00002818 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002819 Loc, Loc);
Adrian Prantl1858c662016-04-24 22:22:29 +00002820 // Create a scope with an artificial location for the body of this function.
2821 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002822 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar(
Alexey Bataev97720002014-11-11 04:05:39 +00002823 DtorCGF.GetAddrOfLocalVar(&Dst),
John McCall7f416cc2015-09-08 08:05:57 +00002824 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
2825 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
Alexey Bataev97720002014-11-11 04:05:39 +00002826 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
2827 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
2828 DtorCGF.FinishFunction();
2829 Dtor = Fn;
2830 }
2831 // Do not emit init function if it is not required.
2832 if (!Ctor && !Dtor)
2833 return nullptr;
2834
2835 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002836 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
2837 /*isVarArg=*/false)
2838 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002839 // Copying constructor for the threadprivate variable.
2840 // Must be NULL - reserved by runtime, but currently it requires that this
2841 // parameter is always NULL. Otherwise it fires assertion.
2842 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
2843 if (Ctor == nullptr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002844 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
2845 /*isVarArg=*/false)
2846 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002847 Ctor = llvm::Constant::getNullValue(CtorTy);
2848 }
2849 if (Dtor == nullptr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002850 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
2851 /*isVarArg=*/false)
2852 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002853 Dtor = llvm::Constant::getNullValue(DtorTy);
2854 }
2855 if (!CGF) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002856 auto *InitFunctionTy =
Alexey Bataev97720002014-11-11 04:05:39 +00002857 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002858 std::string Name = getName({"__omp_threadprivate_init_", ""});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002859 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction(
Alexey Bataev18fa2322018-05-02 14:20:50 +00002860 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction());
Alexey Bataev97720002014-11-11 04:05:39 +00002861 CodeGenFunction InitCGF(CGM);
2862 FunctionArgList ArgList;
2863 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
2864 CGM.getTypes().arrangeNullaryFunction(), ArgList,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002865 Loc, Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002866 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002867 InitCGF.FinishFunction();
2868 return InitFunction;
2869 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002870 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002871 }
2872 return nullptr;
2873}
2874
Alexey Bataev34f8a702018-03-28 14:28:54 +00002875bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD,
2876 llvm::GlobalVariable *Addr,
2877 bool PerformInit) {
Alexey Bataev36724b72019-10-03 16:46:49 +00002878 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
2879 !CGM.getLangOpts().OpenMPIsDevice)
Alexey Bataev4db9dc62019-09-23 15:53:51 +00002880 return false;
Alexey Bataev34f8a702018-03-28 14:28:54 +00002881 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00002882 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002883 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
2884 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
2885 HasRequiresUnifiedSharedMemory))
Alexey Bataevd01b7492018-08-15 19:45:12 +00002886 return CGM.getLangOpts().OpenMPIsDevice;
Alexey Bataev34f8a702018-03-28 14:28:54 +00002887 VD = VD->getDefinition(CGM.getContext());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00002888 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second)
Alexey Bataev34f8a702018-03-28 14:28:54 +00002889 return CGM.getLangOpts().OpenMPIsDevice;
2890
2891 QualType ASTTy = VD->getType();
2892
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002893 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc();
Alexey Bataev34f8a702018-03-28 14:28:54 +00002894 // Produce the unique prefix to identify the new target regions. We use
2895 // the source location of the variable declaration which we know to not
2896 // conflict with any target region.
2897 unsigned DeviceID;
2898 unsigned FileID;
2899 unsigned Line;
2900 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line);
2901 SmallString<128> Buffer, Out;
2902 {
2903 llvm::raw_svector_ostream OS(Buffer);
2904 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID)
2905 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
2906 }
2907
2908 const Expr *Init = VD->getAnyInitializer();
2909 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
2910 llvm::Constant *Ctor;
2911 llvm::Constant *ID;
2912 if (CGM.getLangOpts().OpenMPIsDevice) {
2913 // Generate function that re-emits the declaration's initializer into
2914 // the threadprivate copy of the variable VD
2915 CodeGenFunction CtorCGF(CGM);
2916
2917 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2918 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2919 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
2920 FTy, Twine(Buffer, "_ctor"), FI, Loc);
2921 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF);
2922 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
2923 FunctionArgList(), Loc, Loc);
2924 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF);
2925 CtorCGF.EmitAnyExprToMem(Init,
2926 Address(Addr, CGM.getContext().getDeclAlign(VD)),
2927 Init->getType().getQualifiers(),
2928 /*IsInitializer=*/true);
2929 CtorCGF.FinishFunction();
2930 Ctor = Fn;
2931 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
Alexey Bataeve253f2f2018-05-09 14:15:18 +00002932 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor));
Alexey Bataev34f8a702018-03-28 14:28:54 +00002933 } else {
2934 Ctor = new llvm::GlobalVariable(
2935 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
2936 llvm::GlobalValue::PrivateLinkage,
2937 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor"));
2938 ID = Ctor;
2939 }
2940
2941 // Register the information for the entry associated with the constructor.
2942 Out.clear();
2943 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
2944 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor,
Alexey Bataev03f270c2018-03-30 18:31:07 +00002945 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor);
Alexey Bataev34f8a702018-03-28 14:28:54 +00002946 }
2947 if (VD->getType().isDestructedType() != QualType::DK_none) {
2948 llvm::Constant *Dtor;
2949 llvm::Constant *ID;
2950 if (CGM.getLangOpts().OpenMPIsDevice) {
2951 // Generate function that emits destructor call for the threadprivate
2952 // copy of the variable VD
2953 CodeGenFunction DtorCGF(CGM);
2954
2955 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2956 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2957 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
2958 FTy, Twine(Buffer, "_dtor"), FI, Loc);
2959 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
2960 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
2961 FunctionArgList(), Loc, Loc);
2962 // Create a scope with an artificial location for the body of this
2963 // function.
2964 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
2965 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)),
2966 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()),
2967 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
2968 DtorCGF.FinishFunction();
2969 Dtor = Fn;
2970 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
Alexey Bataeve253f2f2018-05-09 14:15:18 +00002971 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor));
Alexey Bataev34f8a702018-03-28 14:28:54 +00002972 } else {
2973 Dtor = new llvm::GlobalVariable(
2974 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
2975 llvm::GlobalValue::PrivateLinkage,
2976 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor"));
2977 ID = Dtor;
2978 }
2979 // Register the information for the entry associated with the destructor.
2980 Out.clear();
2981 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
2982 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor,
Alexey Bataev03f270c2018-03-30 18:31:07 +00002983 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor);
Alexey Bataev34f8a702018-03-28 14:28:54 +00002984 }
2985 return CGM.getLangOpts().OpenMPIsDevice;
2986}
2987
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002988Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
2989 QualType VarType,
2990 StringRef Name) {
Alexey Bataev18fa2322018-05-02 14:20:50 +00002991 std::string Suffix = getName({"artificial", ""});
2992 std::string CacheSuffix = getName({"cache", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002993 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002994 llvm::Value *GAddr =
2995 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002996 llvm::Value *Args[] = {
2997 emitUpdateLocation(CGF, SourceLocation()),
2998 getThreadID(CGF, SourceLocation()),
2999 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy),
3000 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00003001 /*isSigned=*/false),
Alexey Bataev18fa2322018-05-02 14:20:50 +00003002 getOrCreateInternalVariable(
3003 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))};
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003004 return Address(
3005 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3006 CGF.EmitRuntimeCall(
3007 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
3008 VarLVType->getPointerTo(/*AddrSpace=*/0)),
3009 CGM.getPointerAlign());
3010}
3011
Alexey Bataev1d943ae2019-11-19 12:12:23 -05003012void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond,
3013 const RegionCodeGenTy &ThenGen,
3014 const RegionCodeGenTy &ElseGen) {
Alexey Bataev1d677132015-04-22 13:57:31 +00003015 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
3016
3017 // If the condition constant folds and can be elided, try to avoid emitting
3018 // the condition and the dead arm of the if/else.
3019 bool CondConstant;
3020 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003021 if (CondConstant)
Alexey Bataev1d677132015-04-22 13:57:31 +00003022 ThenGen(CGF);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003023 else
Alexey Bataev1d677132015-04-22 13:57:31 +00003024 ElseGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00003025 return;
3026 }
3027
3028 // Otherwise, the condition did not fold, or we couldn't elide it. Just
3029 // emit the conditional branch.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003030 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then");
3031 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else");
3032 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end");
Alexey Bataev1d677132015-04-22 13:57:31 +00003033 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
3034
3035 // Emit the 'then' code.
3036 CGF.EmitBlock(ThenBlock);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003037 ThenGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00003038 CGF.EmitBranch(ContBlock);
3039 // Emit the 'else' code if present.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003040 // There is no need to emit line number for unconditional branch.
3041 (void)ApplyDebugLocation::CreateEmpty(CGF);
3042 CGF.EmitBlock(ElseBlock);
3043 ElseGen(CGF);
3044 // There is no need to emit line number for unconditional branch.
3045 (void)ApplyDebugLocation::CreateEmpty(CGF);
3046 CGF.EmitBranch(ContBlock);
Alexey Bataev1d677132015-04-22 13:57:31 +00003047 // Emit the continuation block for code after the if.
3048 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003049}
3050
Alexey Bataev1d677132015-04-22 13:57:31 +00003051void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00003052 llvm::Function *OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00003053 ArrayRef<llvm::Value *> CapturedVars,
Alexey Bataev1d677132015-04-22 13:57:31 +00003054 const Expr *IfCond) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003055 if (!CGF.HaveInsertPoint())
3056 return;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003057 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003058 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF,
3059 PrePostActionTy &) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00003060 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003061 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev2377fe92015-09-10 08:12:02 +00003062 llvm::Value *Args[] = {
3063 RTLoc,
3064 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003065 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())};
Alexey Bataev2377fe92015-09-10 08:12:02 +00003066 llvm::SmallVector<llvm::Value *, 16> RealArgs;
3067 RealArgs.append(std::begin(Args), std::end(Args));
3068 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
3069
James Y Knight9871db02019-02-05 16:42:33 +00003070 llvm::FunctionCallee RTLFn =
3071 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call);
Alexey Bataev2377fe92015-09-10 08:12:02 +00003072 CGF.EmitRuntimeCall(RTLFn, RealArgs);
3073 };
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003074 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF,
3075 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003076 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
3077 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc);
Alexey Bataev1d677132015-04-22 13:57:31 +00003078 // Build calls:
3079 // __kmpc_serialized_parallel(&Loc, GTid);
3080 llvm::Value *Args[] = {RTLoc, ThreadID};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003081 CGF.EmitRuntimeCall(
3082 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +00003083
Alexey Bataev3e0f4f82019-10-17 14:36:43 +00003084 // OutlinedFn(&GTid, &zero_bound, CapturedStruct);
3085 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc);
Alexey Bataevf89cf212019-10-16 16:59:01 +00003086 Address ZeroAddrBound =
3087 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty,
3088 /*Name=*/".bound.zero.addr");
3089 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0));
Alexey Bataev2377fe92015-09-10 08:12:02 +00003090 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
Alexey Bataev8521ff62018-07-25 20:03:01 +00003091 // ThreadId for serialized parallels is 0.
Alexey Bataev3e0f4f82019-10-17 14:36:43 +00003092 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
Alexey Bataevf89cf212019-10-16 16:59:01 +00003093 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer());
Alexey Bataev2377fe92015-09-10 08:12:02 +00003094 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
Alexey Bataev3c595a62017-08-14 15:01:03 +00003095 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +00003096
Alexey Bataev1d677132015-04-22 13:57:31 +00003097 // __kmpc_end_serialized_parallel(&Loc, GTid);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003098 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID};
Alexey Bataev1d677132015-04-22 13:57:31 +00003099 CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003100 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel),
3101 EndArgs);
Alexey Bataev1d677132015-04-22 13:57:31 +00003102 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003103 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -05003104 emitIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003105 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003106 RegionCodeGenTy ThenRCG(ThenGen);
3107 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00003108 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00003109}
3110
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00003111// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +00003112// thread-ID variable (it is passed in a first argument of the outlined function
3113// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
3114// regular serial code region, get thread ID by calling kmp_int32
3115// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
3116// return the address of that temp.
John McCall7f416cc2015-09-08 08:05:57 +00003117Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
3118 SourceLocation Loc) {
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003119 if (auto *OMPRegionInfo =
Alexey Bataevd74d0602014-10-13 06:02:40 +00003120 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003121 if (OMPRegionInfo->getThreadIDVariable())
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08003122 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003123
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003124 llvm::Value *ThreadID = getThreadID(CGF, Loc);
3125 QualType Int32Ty =
Alexey Bataevd74d0602014-10-13 06:02:40 +00003126 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003127 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
Alexey Bataevd74d0602014-10-13 06:02:40 +00003128 CGF.EmitStoreOfScalar(ThreadID,
John McCall7f416cc2015-09-08 08:05:57 +00003129 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
Alexey Bataevd74d0602014-10-13 06:02:40 +00003130
3131 return ThreadIDTemp;
3132}
3133
Alexey Bataev1af5bd52019-03-05 17:47:18 +00003134llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable(
3135 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003136 SmallString<256> Buffer;
3137 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00003138 Out << Name;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003139 StringRef RuntimeName = Out.str();
Alexey Bataev43a919f2018-04-13 17:48:43 +00003140 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first;
David Blaikie13156b62014-11-19 03:06:06 +00003141 if (Elem.second) {
3142 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00003143 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00003144 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00003145 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003146
David Blaikie13156b62014-11-19 03:06:06 +00003147 return Elem.second = new llvm::GlobalVariable(
3148 CGM.getModule(), Ty, /*IsConstant*/ false,
3149 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
Alexey Bataev1af5bd52019-03-05 17:47:18 +00003150 Elem.first(), /*InsertBefore=*/nullptr,
3151 llvm::GlobalValue::NotThreadLocal, AddressSpace);
Alexey Bataev97720002014-11-11 04:05:39 +00003152}
3153
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003154llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev18fa2322018-05-02 14:20:50 +00003155 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str();
3156 std::string Name = getName({Prefix, "var"});
3157 return getOrCreateInternalVariable(KmpCriticalNameTy, Name);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003158}
3159
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003160namespace {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003161/// Common pre(post)-action for different OpenMP constructs.
3162class CommonActionTy final : public PrePostActionTy {
James Y Knight9871db02019-02-05 16:42:33 +00003163 llvm::FunctionCallee EnterCallee;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003164 ArrayRef<llvm::Value *> EnterArgs;
James Y Knight9871db02019-02-05 16:42:33 +00003165 llvm::FunctionCallee ExitCallee;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003166 ArrayRef<llvm::Value *> ExitArgs;
3167 bool Conditional;
3168 llvm::BasicBlock *ContBlock = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003169
3170public:
James Y Knight9871db02019-02-05 16:42:33 +00003171 CommonActionTy(llvm::FunctionCallee EnterCallee,
3172 ArrayRef<llvm::Value *> EnterArgs,
3173 llvm::FunctionCallee ExitCallee,
3174 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003175 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
3176 ExitArgs(ExitArgs), Conditional(Conditional) {}
3177 void Enter(CodeGenFunction &CGF) override {
3178 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs);
3179 if (Conditional) {
3180 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes);
3181 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
3182 ContBlock = CGF.createBasicBlock("omp_if.end");
3183 // Generate the branch (If-stmt)
3184 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
3185 CGF.EmitBlock(ThenBlock);
3186 }
Alexey Bataeva744ff52015-05-05 09:24:37 +00003187 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003188 void Done(CodeGenFunction &CGF) {
3189 // Emit the rest of blocks/branches
3190 CGF.EmitBranch(ContBlock);
3191 CGF.EmitBlock(ContBlock, true);
3192 }
3193 void Exit(CodeGenFunction &CGF) override {
3194 CGF.EmitRuntimeCall(ExitCallee, ExitArgs);
Alexey Bataev3e6124b2015-04-10 07:48:12 +00003195 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003196};
Hans Wennborg7eb54642015-09-10 17:07:54 +00003197} // anonymous namespace
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003198
3199void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
3200 StringRef CriticalName,
3201 const RegionCodeGenTy &CriticalOpGen,
Alexey Bataevfc57d162015-12-15 10:55:09 +00003202 SourceLocation Loc, const Expr *Hint) {
3203 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
Alexey Bataev75ddfab2014-12-01 11:32:38 +00003204 // CriticalOpGen();
3205 // __kmpc_end_critical(ident_t *, gtid, Lock);
3206 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev8ef31412015-12-18 07:58:25 +00003207 if (!CGF.HaveInsertPoint())
3208 return;
Alexey Bataevfc57d162015-12-15 10:55:09 +00003209 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3210 getCriticalRegionLock(CriticalName)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003211 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args),
3212 std::end(Args));
Alexey Bataevfc57d162015-12-15 10:55:09 +00003213 if (Hint) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003214 EnterArgs.push_back(CGF.Builder.CreateIntCast(
3215 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false));
3216 }
3217 CommonActionTy Action(
3218 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint
3219 : OMPRTL__kmpc_critical),
3220 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args);
3221 CriticalOpGen.setAction(Action);
Alexey Bataevfc57d162015-12-15 10:55:09 +00003222 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003223}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003224
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003225void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003226 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003227 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003228 if (!CGF.HaveInsertPoint())
3229 return;
Alexey Bataev8d690652014-12-04 07:23:53 +00003230 // if(__kmpc_master(ident_t *, gtid)) {
3231 // MasterOpGen();
3232 // __kmpc_end_master(ident_t *, gtid);
3233 // }
3234 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00003235 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003236 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args,
3237 createRuntimeFunction(OMPRTL__kmpc_end_master), Args,
3238 /*Conditional=*/true);
3239 MasterOpGen.setAction(Action);
3240 emitInlinedDirective(CGF, OMPD_master, MasterOpGen);
3241 Action.Done(CGF);
Alexey Bataev8d690652014-12-04 07:23:53 +00003242}
3243
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003244void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
3245 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003246 if (!CGF.HaveInsertPoint())
3247 return;
Alexey Bataev9f797f32015-02-05 05:57:51 +00003248 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
3249 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003250 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00003251 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003252 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00003253 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
3254 Region->emitUntiedSwitch(CGF);
Alexey Bataev9f797f32015-02-05 05:57:51 +00003255}
3256
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003257void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
3258 const RegionCodeGenTy &TaskgroupOpGen,
3259 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003260 if (!CGF.HaveInsertPoint())
3261 return;
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003262 // __kmpc_taskgroup(ident_t *, gtid);
3263 // TaskgroupOpGen();
3264 // __kmpc_end_taskgroup(ident_t *, gtid);
3265 // Prepare arguments and build a call to __kmpc_taskgroup
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003266 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
3267 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args,
3268 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
3269 Args);
3270 TaskgroupOpGen.setAction(Action);
3271 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003272}
3273
John McCall7f416cc2015-09-08 08:05:57 +00003274/// Given an array of pointers to variables, project the address of a
3275/// given variable.
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003276static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
3277 unsigned Index, const VarDecl *Var) {
John McCall7f416cc2015-09-08 08:05:57 +00003278 // Pull out the pointer to the variable.
James Y Knight751fe282019-02-09 22:22:28 +00003279 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index);
John McCall7f416cc2015-09-08 08:05:57 +00003280 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
3281
3282 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003283 Addr = CGF.Builder.CreateElementBitCast(
3284 Addr, CGF.ConvertTypeForMem(Var->getType()));
John McCall7f416cc2015-09-08 08:05:57 +00003285 return Addr;
3286}
3287
Alexey Bataeva63048e2015-03-23 06:18:07 +00003288static llvm::Value *emitCopyprivateCopyFunction(
Alexey Bataev420d45b2015-04-14 05:11:24 +00003289 CodeGenModule &CGM, llvm::Type *ArgsType,
3290 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003291 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps,
3292 SourceLocation Loc) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003293 ASTContext &C = CGM.getContext();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003294 // void copy_func(void *LHSArg, void *RHSArg);
3295 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003296 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3297 ImplicitParamDecl::Other);
3298 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3299 ImplicitParamDecl::Other);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003300 Args.push_back(&LHSArg);
3301 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003302 const auto &CGFI =
3303 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00003304 std::string Name =
3305 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"});
3306 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
3307 llvm::GlobalValue::InternalLinkage, Name,
3308 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00003309 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00003310 Fn->setDoesNotRecurse();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003311 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003312 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev420d45b2015-04-14 05:11:24 +00003313 // Dest = (void*[n])(LHSArg);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003314 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00003315 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3316 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
3317 ArgsType), CGF.getPointerAlign());
3318 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3319 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
3320 ArgsType), CGF.getPointerAlign());
Alexey Bataeva63048e2015-03-23 06:18:07 +00003321 // *(Type0*)Dst[0] = *(Type0*)Src[0];
3322 // *(Type1*)Dst[1] = *(Type1*)Src[1];
3323 // ...
3324 // *(Typen*)Dst[n] = *(Typen*)Src[n];
Alexey Bataeva63048e2015-03-23 06:18:07 +00003325 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003326 const auto *DestVar =
3327 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +00003328 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
3329
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003330 const auto *SrcVar =
3331 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +00003332 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
3333
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003334 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003335 QualType Type = VD->getType();
John McCall7f416cc2015-09-08 08:05:57 +00003336 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003337 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00003338 CGF.FinishFunction();
3339 return Fn;
3340}
3341
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003342void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003343 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00003344 SourceLocation Loc,
3345 ArrayRef<const Expr *> CopyprivateVars,
3346 ArrayRef<const Expr *> SrcExprs,
3347 ArrayRef<const Expr *> DstExprs,
3348 ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003349 if (!CGF.HaveInsertPoint())
3350 return;
Alexey Bataeva63048e2015-03-23 06:18:07 +00003351 assert(CopyprivateVars.size() == SrcExprs.size() &&
3352 CopyprivateVars.size() == DstExprs.size() &&
3353 CopyprivateVars.size() == AssignmentOps.size());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003354 ASTContext &C = CGM.getContext();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003355 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003356 // if(__kmpc_single(ident_t *, gtid)) {
3357 // SingleOpGen();
3358 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003359 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003360 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00003361 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3362 // <copy_func>, did_it);
3363
John McCall7f416cc2015-09-08 08:05:57 +00003364 Address DidIt = Address::invalid();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003365 if (!CopyprivateVars.empty()) {
3366 // int32 did_it = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003367 QualType KmpInt32Ty =
3368 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003369 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
John McCall7f416cc2015-09-08 08:05:57 +00003370 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003371 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003372 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00003373 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003374 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args,
3375 createRuntimeFunction(OMPRTL__kmpc_end_single), Args,
3376 /*Conditional=*/true);
3377 SingleOpGen.setAction(Action);
3378 emitInlinedDirective(CGF, OMPD_single, SingleOpGen);
3379 if (DidIt.isValid()) {
3380 // did_it = 1;
3381 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
3382 }
3383 Action.Done(CGF);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003384 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3385 // <copy_func>, did_it);
John McCall7f416cc2015-09-08 08:05:57 +00003386 if (DidIt.isValid()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00003387 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
Richard Smith772e2662019-10-04 01:25:59 +00003388 QualType CopyprivateArrayTy = C.getConstantArrayType(
3389 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
3390 /*IndexTypeQuals=*/0);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003391 // Create a list of all private variables for copyprivate.
John McCall7f416cc2015-09-08 08:05:57 +00003392 Address CopyprivateList =
Alexey Bataeva63048e2015-03-23 06:18:07 +00003393 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
3394 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +00003395 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I);
John McCall7f416cc2015-09-08 08:05:57 +00003396 CGF.Builder.CreateStore(
Alexey Bataeva63048e2015-03-23 06:18:07 +00003397 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08003398 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy),
John McCall7f416cc2015-09-08 08:05:57 +00003399 Elem);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003400 }
3401 // Build function that copies private values from single region to all other
3402 // threads in the corresponding parallel region.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003403 llvm::Value *CpyFn = emitCopyprivateCopyFunction(
Alexey Bataeva63048e2015-03-23 06:18:07 +00003404 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003405 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003406 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00003407 Address CL =
3408 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
3409 CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003410 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003411 llvm::Value *Args[] = {
3412 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
3413 getThreadID(CGF, Loc), // i32 <gtid>
Alexey Bataev66beaa92015-04-30 03:47:32 +00003414 BufSize, // size_t <buf_size>
John McCall7f416cc2015-09-08 08:05:57 +00003415 CL.getPointer(), // void *<copyprivate list>
Alexey Bataeva63048e2015-03-23 06:18:07 +00003416 CpyFn, // void (*) (void *, void *) <copy_func>
3417 DidItVal // i32 did_it
3418 };
3419 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
3420 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003421}
3422
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003423void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
3424 const RegionCodeGenTy &OrderedOpGen,
Alexey Bataev5f600d62015-09-29 03:48:57 +00003425 SourceLocation Loc, bool IsThreads) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003426 if (!CGF.HaveInsertPoint())
3427 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003428 // __kmpc_ordered(ident_t *, gtid);
3429 // OrderedOpGen();
3430 // __kmpc_end_ordered(ident_t *, gtid);
3431 // Prepare arguments and build a call to __kmpc_ordered
Alexey Bataev5f600d62015-09-29 03:48:57 +00003432 if (IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003433 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003434 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args,
3435 createRuntimeFunction(OMPRTL__kmpc_end_ordered),
3436 Args);
3437 OrderedOpGen.setAction(Action);
3438 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
3439 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003440 }
Alexey Bataev5f600d62015-09-29 03:48:57 +00003441 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003442}
3443
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003444unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) {
Alexey Bataev50b3c952016-02-19 10:38:26 +00003445 unsigned Flags;
3446 if (Kind == OMPD_for)
3447 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
3448 else if (Kind == OMPD_sections)
3449 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
3450 else if (Kind == OMPD_single)
3451 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
3452 else if (Kind == OMPD_barrier)
3453 Flags = OMP_IDENT_BARRIER_EXPL;
3454 else
3455 Flags = OMP_IDENT_BARRIER_IMPL;
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003456 return Flags;
3457}
3458
Alexey Bataevf6a53d62019-03-18 18:40:00 +00003459void CGOpenMPRuntime::getDefaultScheduleAndChunk(
3460 CodeGenFunction &CGF, const OMPLoopDirective &S,
3461 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const {
3462 // Check if the loop directive is actually a doacross loop directive. In this
3463 // case choose static, 1 schedule.
3464 if (llvm::any_of(
3465 S.getClausesOfKind<OMPOrderedClause>(),
3466 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) {
3467 ScheduleKind = OMPC_SCHEDULE_static;
3468 // Chunk size is 1 in this case.
3469 llvm::APInt ChunkSize(32, 1);
3470 ChunkExpr = IntegerLiteral::Create(
3471 CGF.getContext(), ChunkSize,
3472 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
3473 SourceLocation());
3474 }
3475}
3476
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003477void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
3478 OpenMPDirectiveKind Kind, bool EmitChecks,
3479 bool ForceSimpleCall) {
3480 if (!CGF.HaveInsertPoint())
3481 return;
3482 // Build call __kmpc_cancel_barrier(loc, thread_id);
3483 // Build call __kmpc_barrier(loc, thread_id);
3484 unsigned Flags = getDefaultFlagsForBarriers(Kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003485 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
3486 // thread_id);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003487 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
3488 getThreadID(CGF, Loc)};
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003489 if (auto *OMPRegionInfo =
3490 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00003491 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003492 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003493 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev25e5b442015-09-15 12:52:43 +00003494 if (EmitChecks) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003495 // if (__kmpc_cancel_barrier()) {
3496 // exit from construct;
3497 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003498 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
3499 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
3500 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003501 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
3502 CGF.EmitBlock(ExitBB);
3503 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003504 CodeGenFunction::JumpDest CancelDestination =
Alexey Bataev25e5b442015-09-15 12:52:43 +00003505 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003506 CGF.EmitBranchThroughCleanup(CancelDestination);
3507 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
3508 }
3509 return;
3510 }
3511 }
3512 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003513}
3514
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003515/// Map the OpenMP loop schedule to the runtime enumeration.
Alexander Musmanc6388682014-12-15 07:07:06 +00003516static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003517 bool Chunked, bool Ordered) {
Alexander Musmanc6388682014-12-15 07:07:06 +00003518 switch (ScheduleKind) {
3519 case OMPC_SCHEDULE_static:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003520 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
3521 : (Ordered ? OMP_ord_static : OMP_sch_static);
Alexander Musmanc6388682014-12-15 07:07:06 +00003522 case OMPC_SCHEDULE_dynamic:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003523 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00003524 case OMPC_SCHEDULE_guided:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003525 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00003526 case OMPC_SCHEDULE_runtime:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003527 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
3528 case OMPC_SCHEDULE_auto:
3529 return Ordered ? OMP_ord_auto : OMP_sch_auto;
Alexander Musmanc6388682014-12-15 07:07:06 +00003530 case OMPC_SCHEDULE_unknown:
3531 assert(!Chunked && "chunk was specified but schedule kind not known");
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003532 return Ordered ? OMP_ord_static : OMP_sch_static;
Alexander Musmanc6388682014-12-15 07:07:06 +00003533 }
3534 llvm_unreachable("Unexpected runtime schedule");
3535}
3536
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003537/// Map the OpenMP distribute schedule to the runtime enumeration.
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003538static OpenMPSchedType
3539getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
3540 // only static is allowed for dist_schedule
3541 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
3542}
3543
Alexander Musmanc6388682014-12-15 07:07:06 +00003544bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
3545 bool Chunked) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003546 OpenMPSchedType Schedule =
3547 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
Alexander Musmanc6388682014-12-15 07:07:06 +00003548 return Schedule == OMP_sch_static;
3549}
3550
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003551bool CGOpenMPRuntime::isStaticNonchunked(
3552 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003553 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003554 return Schedule == OMP_dist_sch_static;
3555}
3556
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00003557bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind,
3558 bool Chunked) const {
3559 OpenMPSchedType Schedule =
3560 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
3561 return Schedule == OMP_sch_static_chunked;
3562}
3563
3564bool CGOpenMPRuntime::isStaticChunked(
3565 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
3566 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
3567 return Schedule == OMP_dist_sch_static_chunked;
3568}
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003569
Alexander Musmandf7a8e22015-01-22 08:49:35 +00003570bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003571 OpenMPSchedType Schedule =
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003572 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00003573 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
3574 return Schedule != OMP_sch_static;
3575}
3576
Alexey Bataev07a3b592019-08-23 19:52:05 +00003577static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003578 OpenMPScheduleClauseModifier M1,
3579 OpenMPScheduleClauseModifier M2) {
Alexey Bataev6cff6242016-05-30 13:05:14 +00003580 int Modifier = 0;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003581 switch (M1) {
3582 case OMPC_SCHEDULE_MODIFIER_monotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003583 Modifier = OMP_sch_modifier_monotonic;
3584 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003585 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003586 Modifier = OMP_sch_modifier_nonmonotonic;
3587 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003588 case OMPC_SCHEDULE_MODIFIER_simd:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003589 if (Schedule == OMP_sch_static_chunked)
3590 Schedule = OMP_sch_static_balanced_chunked;
3591 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003592 case OMPC_SCHEDULE_MODIFIER_last:
3593 case OMPC_SCHEDULE_MODIFIER_unknown:
3594 break;
3595 }
3596 switch (M2) {
3597 case OMPC_SCHEDULE_MODIFIER_monotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003598 Modifier = OMP_sch_modifier_monotonic;
3599 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003600 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003601 Modifier = OMP_sch_modifier_nonmonotonic;
3602 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003603 case OMPC_SCHEDULE_MODIFIER_simd:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003604 if (Schedule == OMP_sch_static_chunked)
3605 Schedule = OMP_sch_static_balanced_chunked;
3606 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003607 case OMPC_SCHEDULE_MODIFIER_last:
3608 case OMPC_SCHEDULE_MODIFIER_unknown:
3609 break;
3610 }
Alexey Bataev07a3b592019-08-23 19:52:05 +00003611 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription.
3612 // If the static schedule kind is specified or if the ordered clause is
3613 // specified, and if the nonmonotonic modifier is not specified, the effect is
3614 // as if the monotonic modifier is specified. Otherwise, unless the monotonic
3615 // modifier is specified, the effect is as if the nonmonotonic modifier is
3616 // specified.
3617 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) {
3618 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
3619 Schedule == OMP_sch_static_balanced_chunked ||
Alexey Bataevc3eded02019-11-18 11:13:08 -05003620 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
3621 Schedule == OMP_dist_sch_static_chunked ||
3622 Schedule == OMP_dist_sch_static))
Alexey Bataev07a3b592019-08-23 19:52:05 +00003623 Modifier = OMP_sch_modifier_nonmonotonic;
3624 }
Alexey Bataev6cff6242016-05-30 13:05:14 +00003625 return Schedule | Modifier;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003626}
3627
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003628void CGOpenMPRuntime::emitForDispatchInit(
3629 CodeGenFunction &CGF, SourceLocation Loc,
3630 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
3631 bool Ordered, const DispatchRTInput &DispatchValues) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003632 if (!CGF.HaveInsertPoint())
3633 return;
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003634 OpenMPSchedType Schedule = getRuntimeSchedule(
3635 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered);
John McCall7f416cc2015-09-08 08:05:57 +00003636 assert(Ordered ||
3637 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
Alexey Bataev6cff6242016-05-30 13:05:14 +00003638 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
3639 Schedule != OMP_sch_static_balanced_chunked));
John McCall7f416cc2015-09-08 08:05:57 +00003640 // Call __kmpc_dispatch_init(
3641 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
3642 // kmp_int[32|64] lower, kmp_int[32|64] upper,
3643 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00003644
John McCall7f416cc2015-09-08 08:05:57 +00003645 // If the Chunk was not specified in the clause - use default value 1.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003646 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk
3647 : CGF.Builder.getIntN(IVSize, 1);
John McCall7f416cc2015-09-08 08:05:57 +00003648 llvm::Value *Args[] = {
Alexey Bataev07a3b592019-08-23 19:52:05 +00003649 emitUpdateLocation(CGF, Loc),
3650 getThreadID(CGF, Loc),
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003651 CGF.Builder.getInt32(addMonoNonMonoModifier(
Alexey Bataev07a3b592019-08-23 19:52:05 +00003652 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type
3653 DispatchValues.LB, // Lower
3654 DispatchValues.UB, // Upper
3655 CGF.Builder.getIntN(IVSize, 1), // Stride
3656 Chunk // Chunk
John McCall7f416cc2015-09-08 08:05:57 +00003657 };
3658 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
3659}
3660
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003661static void emitForStaticInitCall(
3662 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
James Y Knight9871db02019-02-05 16:42:33 +00003663 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003664 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003665 const CGOpenMPRuntime::StaticRTInput &Values) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003666 if (!CGF.HaveInsertPoint())
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003667 return;
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003668
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003669 assert(!Values.Ordered);
3670 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
3671 Schedule == OMP_sch_static_balanced_chunked ||
3672 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
3673 Schedule == OMP_dist_sch_static ||
3674 Schedule == OMP_dist_sch_static_chunked);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003675
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003676 // Call __kmpc_for_static_init(
3677 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
3678 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
3679 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
3680 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
3681 llvm::Value *Chunk = Values.Chunk;
3682 if (Chunk == nullptr) {
3683 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
3684 Schedule == OMP_dist_sch_static) &&
3685 "expected static non-chunked schedule");
3686 // If the Chunk was not specified in the clause - use default value 1.
3687 Chunk = CGF.Builder.getIntN(Values.IVSize, 1);
3688 } else {
3689 assert((Schedule == OMP_sch_static_chunked ||
3690 Schedule == OMP_sch_static_balanced_chunked ||
3691 Schedule == OMP_ord_static_chunked ||
3692 Schedule == OMP_dist_sch_static_chunked) &&
3693 "expected static chunked schedule");
3694 }
3695 llvm::Value *Args[] = {
3696 UpdateLocation,
3697 ThreadId,
Alexey Bataev07a3b592019-08-23 19:52:05 +00003698 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003699 M2)), // Schedule type
3700 Values.IL.getPointer(), // &isLastIter
3701 Values.LB.getPointer(), // &LB
3702 Values.UB.getPointer(), // &UB
3703 Values.ST.getPointer(), // &Stride
3704 CGF.Builder.getIntN(Values.IVSize, 1), // Incr
3705 Chunk // Chunk
3706 };
3707 CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003708}
3709
John McCall7f416cc2015-09-08 08:05:57 +00003710void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
3711 SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003712 OpenMPDirectiveKind DKind,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003713 const OpenMPScheduleTy &ScheduleKind,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003714 const StaticRTInput &Values) {
3715 OpenMPSchedType ScheduleNum = getRuntimeSchedule(
3716 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered);
3717 assert(isOpenMPWorksharingDirective(DKind) &&
3718 "Expected loop-based or sections-based directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003719 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003720 isOpenMPLoopDirective(DKind)
3721 ? OMP_IDENT_WORK_LOOP
3722 : OMP_IDENT_WORK_SECTIONS);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003723 llvm::Value *ThreadId = getThreadID(CGF, Loc);
James Y Knight9871db02019-02-05 16:42:33 +00003724 llvm::FunctionCallee StaticInitFunction =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003725 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003726 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003727 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003728}
John McCall7f416cc2015-09-08 08:05:57 +00003729
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003730void CGOpenMPRuntime::emitDistributeStaticInit(
3731 CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003732 OpenMPDistScheduleClauseKind SchedKind,
3733 const CGOpenMPRuntime::StaticRTInput &Values) {
3734 OpenMPSchedType ScheduleNum =
3735 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003736 llvm::Value *UpdatedLocation =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003737 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003738 llvm::Value *ThreadId = getThreadID(CGF, Loc);
James Y Knight9871db02019-02-05 16:42:33 +00003739 llvm::FunctionCallee StaticInitFunction =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003740 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003741 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
3742 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003743 OMPC_SCHEDULE_MODIFIER_unknown, Values);
Alexander Musmanc6388682014-12-15 07:07:06 +00003744}
3745
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003746void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
Alexey Bataevf43f7142017-09-06 16:17:35 +00003747 SourceLocation Loc,
3748 OpenMPDirectiveKind DKind) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003749 if (!CGF.HaveInsertPoint())
3750 return;
Alexander Musmanc6388682014-12-15 07:07:06 +00003751 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataevf43f7142017-09-06 16:17:35 +00003752 llvm::Value *Args[] = {
3753 emitUpdateLocation(CGF, Loc,
3754 isOpenMPDistributeDirective(DKind)
3755 ? OMP_IDENT_WORK_DISTRIBUTE
3756 : isOpenMPLoopDirective(DKind)
3757 ? OMP_IDENT_WORK_LOOP
3758 : OMP_IDENT_WORK_SECTIONS),
3759 getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003760 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
3761 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00003762}
3763
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003764void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
3765 SourceLocation Loc,
3766 unsigned IVSize,
3767 bool IVSigned) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003768 if (!CGF.HaveInsertPoint())
3769 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003770 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00003771 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003772 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
3773}
3774
Alexander Musman92bdaab2015-03-12 13:37:50 +00003775llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
3776 SourceLocation Loc, unsigned IVSize,
John McCall7f416cc2015-09-08 08:05:57 +00003777 bool IVSigned, Address IL,
3778 Address LB, Address UB,
3779 Address ST) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00003780 // Call __kmpc_dispatch_next(
3781 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
3782 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
3783 // kmp_int[32|64] *p_stride);
3784 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00003785 emitUpdateLocation(CGF, Loc),
3786 getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00003787 IL.getPointer(), // &isLastIter
3788 LB.getPointer(), // &Lower
3789 UB.getPointer(), // &Upper
3790 ST.getPointer() // &Stride
Alexander Musman92bdaab2015-03-12 13:37:50 +00003791 };
3792 llvm::Value *Call =
3793 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
3794 return CGF.EmitScalarConversion(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003795 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00003796 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00003797}
3798
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003799void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
3800 llvm::Value *NumThreads,
3801 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003802 if (!CGF.HaveInsertPoint())
3803 return;
Alexey Bataevb2059782014-10-13 08:23:51 +00003804 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
3805 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003806 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00003807 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003808 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
3809 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00003810}
3811
Alexey Bataev7f210c62015-06-18 13:40:03 +00003812void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
3813 OpenMPProcBindClauseKind ProcBind,
3814 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003815 if (!CGF.HaveInsertPoint())
3816 return;
Alexey Bataev7f210c62015-06-18 13:40:03 +00003817 // Constants for proc bind value accepted by the runtime.
3818 enum ProcBindTy {
3819 ProcBindFalse = 0,
3820 ProcBindTrue,
3821 ProcBindMaster,
3822 ProcBindClose,
3823 ProcBindSpread,
3824 ProcBindIntel,
3825 ProcBindDefault
3826 } RuntimeProcBind;
3827 switch (ProcBind) {
3828 case OMPC_PROC_BIND_master:
3829 RuntimeProcBind = ProcBindMaster;
3830 break;
3831 case OMPC_PROC_BIND_close:
3832 RuntimeProcBind = ProcBindClose;
3833 break;
3834 case OMPC_PROC_BIND_spread:
3835 RuntimeProcBind = ProcBindSpread;
3836 break;
3837 case OMPC_PROC_BIND_unknown:
3838 llvm_unreachable("Unsupported proc_bind value.");
3839 }
3840 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
3841 llvm::Value *Args[] = {
3842 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3843 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
3844 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
3845}
3846
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003847void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
3848 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003849 if (!CGF.HaveInsertPoint())
3850 return;
Alexey Bataevd76df6d2015-02-24 12:55:09 +00003851 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003852 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
3853 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00003854}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003855
Alexey Bataev62b63b12015-03-10 07:28:44 +00003856namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003857/// Indexes of fields for type kmp_task_t.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003858enum KmpTaskTFields {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003859 /// List of shared variables.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003860 KmpTaskTShareds,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003861 /// Task routine.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003862 KmpTaskTRoutine,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003863 /// Partition id for the untied tasks.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003864 KmpTaskTPartId,
Alexey Bataevad537bb2016-05-30 09:06:50 +00003865 /// Function with call of destructors for private variables.
3866 Data1,
3867 /// Task priority.
3868 Data2,
Alexey Bataev7292c292016-04-25 12:22:29 +00003869 /// (Taskloops only) Lower bound.
3870 KmpTaskTLowerBound,
3871 /// (Taskloops only) Upper bound.
3872 KmpTaskTUpperBound,
3873 /// (Taskloops only) Stride.
3874 KmpTaskTStride,
3875 /// (Taskloops only) Is last iteration flag.
3876 KmpTaskTLastIter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003877 /// (Taskloops only) Reduction data.
3878 KmpTaskTReductions,
Alexey Bataev62b63b12015-03-10 07:28:44 +00003879};
Hans Wennborg7eb54642015-09-10 17:07:54 +00003880} // anonymous namespace
Alexey Bataev62b63b12015-03-10 07:28:44 +00003881
Samuel Antaoee8fb302016-01-06 13:42:12 +00003882bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003883 return OffloadEntriesTargetRegion.empty() &&
3884 OffloadEntriesDeviceGlobalVar.empty();
Samuel Antaoee8fb302016-01-06 13:42:12 +00003885}
3886
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003887/// Initialize target region entry.
Samuel Antaoee8fb302016-01-06 13:42:12 +00003888void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3889 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3890 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00003891 unsigned Order) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003892 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
3893 "only required for the device "
3894 "code generation.");
Samuel Antao2de62b02016-02-13 23:35:10 +00003895 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
Samuel Antaof83efdb2017-01-05 16:02:49 +00003896 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003897 OMPTargetRegionEntryTargetRegion);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003898 ++OffloadingEntriesNum;
3899}
3900
3901void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3902 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3903 StringRef ParentName, unsigned LineNum,
Samuel Antaof83efdb2017-01-05 16:02:49 +00003904 llvm::Constant *Addr, llvm::Constant *ID,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003905 OMPTargetRegionEntryKind Flags) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003906 // If we are emitting code for a target, the entry is already initialized,
3907 // only has to be registered.
3908 if (CGM.getLangOpts().OpenMPIsDevice) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00003909 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) {
3910 unsigned DiagID = CGM.getDiags().getCustomDiagID(
3911 DiagnosticsEngine::Error,
3912 "Unable to find target region on line '%0' in the device code.");
3913 CGM.getDiags().Report(DiagID) << LineNum;
3914 return;
3915 }
Samuel Antao2de62b02016-02-13 23:35:10 +00003916 auto &Entry =
3917 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
Samuel Antaoee8fb302016-01-06 13:42:12 +00003918 assert(Entry.isValid() && "Entry not initialized!");
3919 Entry.setAddress(Addr);
3920 Entry.setID(ID);
Samuel Antaof83efdb2017-01-05 16:02:49 +00003921 Entry.setFlags(Flags);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003922 } else {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003923 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags);
Samuel Antao2de62b02016-02-13 23:35:10 +00003924 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00003925 ++OffloadingEntriesNum;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003926 }
3927}
3928
3929bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00003930 unsigned DeviceID, unsigned FileID, StringRef ParentName,
3931 unsigned LineNum) const {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003932 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
3933 if (PerDevice == OffloadEntriesTargetRegion.end())
3934 return false;
3935 auto PerFile = PerDevice->second.find(FileID);
3936 if (PerFile == PerDevice->second.end())
3937 return false;
3938 auto PerParentName = PerFile->second.find(ParentName);
3939 if (PerParentName == PerFile->second.end())
3940 return false;
3941 auto PerLine = PerParentName->second.find(LineNum);
3942 if (PerLine == PerParentName->second.end())
3943 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003944 // Fail if this entry is already registered.
Samuel Antao2de62b02016-02-13 23:35:10 +00003945 if (PerLine->second.getAddress() || PerLine->second.getID())
Samuel Antaoee8fb302016-01-06 13:42:12 +00003946 return false;
3947 return true;
3948}
3949
3950void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
3951 const OffloadTargetRegionEntryInfoActTy &Action) {
3952 // Scan all target region entries and perform the provided action.
Alexey Bataev03f270c2018-03-30 18:31:07 +00003953 for (const auto &D : OffloadEntriesTargetRegion)
3954 for (const auto &F : D.second)
3955 for (const auto &P : F.second)
3956 for (const auto &L : P.second)
Samuel Antao2de62b02016-02-13 23:35:10 +00003957 Action(D.first, F.first, P.first(), L.first, L.second);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003958}
3959
Alexey Bataev03f270c2018-03-30 18:31:07 +00003960void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3961 initializeDeviceGlobalVarEntryInfo(StringRef Name,
3962 OMPTargetGlobalVarEntryKind Flags,
3963 unsigned Order) {
3964 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
3965 "only required for the device "
3966 "code generation.");
3967 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
3968 ++OffloadingEntriesNum;
3969}
Samuel Antaoee8fb302016-01-06 13:42:12 +00003970
Alexey Bataev03f270c2018-03-30 18:31:07 +00003971void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3972 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr,
3973 CharUnits VarSize,
3974 OMPTargetGlobalVarEntryKind Flags,
3975 llvm::GlobalValue::LinkageTypes Linkage) {
3976 if (CGM.getLangOpts().OpenMPIsDevice) {
3977 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3978 assert(Entry.isValid() && Entry.getFlags() == Flags &&
3979 "Entry not initialized!");
3980 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
3981 "Resetting with the new address.");
Alexey Bataev8259cc32019-03-12 20:05:17 +00003982 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) {
3983 if (Entry.getVarSize().isZero()) {
3984 Entry.setVarSize(VarSize);
3985 Entry.setLinkage(Linkage);
3986 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003987 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00003988 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003989 Entry.setVarSize(VarSize);
3990 Entry.setLinkage(Linkage);
Alexey Bataev8259cc32019-03-12 20:05:17 +00003991 Entry.setAddress(Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00003992 } else {
Alexey Bataev8259cc32019-03-12 20:05:17 +00003993 if (hasDeviceGlobalVarEntryInfo(VarName)) {
3994 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3995 assert(Entry.isValid() && Entry.getFlags() == Flags &&
3996 "Entry not initialized!");
3997 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
3998 "Resetting with the new address.");
3999 if (Entry.getVarSize().isZero()) {
4000 Entry.setVarSize(VarSize);
4001 Entry.setLinkage(Linkage);
4002 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004003 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00004004 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004005 OffloadEntriesDeviceGlobalVar.try_emplace(
4006 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage);
4007 ++OffloadingEntriesNum;
4008 }
4009}
4010
4011void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
4012 actOnDeviceGlobalVarEntriesInfo(
4013 const OffloadDeviceGlobalVarEntryInfoActTy &Action) {
4014 // Scan all target region entries and perform the provided action.
4015 for (const auto &E : OffloadEntriesDeviceGlobalVar)
4016 Action(E.getKey(), E.getValue());
Samuel Antaoee8fb302016-01-06 13:42:12 +00004017}
4018
Alexey Bataev03f270c2018-03-30 18:31:07 +00004019void CGOpenMPRuntime::createOffloadEntry(
4020 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags,
4021 llvm::GlobalValue::LinkageTypes Linkage) {
Samuel Antao2de62b02016-02-13 23:35:10 +00004022 StringRef Name = Addr->getName();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004023 llvm::Module &M = CGM.getModule();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004024 llvm::LLVMContext &C = M.getContext();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004025
4026 // Create constant string with the name.
4027 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
4028
Alexey Bataev18fa2322018-05-02 14:20:50 +00004029 std::string StringName = getName({"omp_offloading", "entry_name"});
4030 auto *Str = new llvm::GlobalVariable(
4031 M, StrPtrInit->getType(), /*isConstant=*/true,
4032 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00004033 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004034
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004035 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy),
4036 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy),
4037 llvm::ConstantInt::get(CGM.SizeTy, Size),
4038 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
4039 llvm::ConstantInt::get(CGM.Int32Ty, 0)};
Alexey Bataev18fa2322018-05-02 14:20:50 +00004040 std::string EntryName = getName({"omp_offloading", "entry", ""});
Mike Ricee1ca7b62018-08-29 15:45:11 +00004041 llvm::GlobalVariable *Entry = createGlobalStruct(
4042 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data,
4043 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004044
4045 // The entry has to be created in the section the linker expects it to be.
Sergey Dmitriev4b343fd2019-09-27 20:00:51 +00004046 Entry->setSection("omp_offloading_entries");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004047}
4048
4049void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
4050 // Emit the offloading entries and metadata so that the device codegen side
Samuel Antao4c8035b2016-12-12 18:00:20 +00004051 // can easily figure out what to emit. The produced metadata looks like
4052 // this:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004053 //
4054 // !omp_offload.info = !{!1, ...}
4055 //
4056 // Right now we only generate metadata for function that contain target
4057 // regions.
4058
Sergey Dmitriev5836c352019-10-15 18:42:47 +00004059 // If we are in simd mode or there are no entries, we don't need to do
4060 // anything.
4061 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty())
Samuel Antaoee8fb302016-01-06 13:42:12 +00004062 return;
4063
4064 llvm::Module &M = CGM.getModule();
4065 llvm::LLVMContext &C = M.getContext();
Alexey Bataevba643691d2019-10-03 16:20:34 +00004066 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *,
4067 SourceLocation, StringRef>,
4068 16>
Samuel Antaoee8fb302016-01-06 13:42:12 +00004069 OrderedEntries(OffloadEntriesInfoManager.size());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004070 llvm::SmallVector<StringRef, 16> ParentFunctions(
4071 OffloadEntriesInfoManager.size());
Samuel Antaoee8fb302016-01-06 13:42:12 +00004072
Simon Pilgrim2c518802017-03-30 14:13:19 +00004073 // Auxiliary methods to create metadata values and strings.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004074 auto &&GetMDInt = [this](unsigned V) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004075 return llvm::ConstantAsMetadata::get(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004076 llvm::ConstantInt::get(CGM.Int32Ty, V));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004077 };
4078
Alexey Bataev03f270c2018-03-30 18:31:07 +00004079 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); };
4080
4081 // Create the offloading info metadata node.
4082 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004083
4084 // Create function that emits metadata for each target region entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00004085 auto &&TargetRegionMetadataEmitter =
Alexey Bataevba643691d2019-10-03 16:20:34 +00004086 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt,
4087 &GetMDString](
Alexey Bataev03f270c2018-03-30 18:31:07 +00004088 unsigned DeviceID, unsigned FileID, StringRef ParentName,
4089 unsigned Line,
4090 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
4091 // Generate metadata for target regions. Each entry of this metadata
4092 // contains:
4093 // - Entry 0 -> Kind of this type of metadata (0).
4094 // - Entry 1 -> Device ID of the file where the entry was identified.
4095 // - Entry 2 -> File ID of the file where the entry was identified.
4096 // - Entry 3 -> Mangled name of the function where the entry was
4097 // identified.
4098 // - Entry 4 -> Line in the file where the entry was identified.
4099 // - Entry 5 -> Order the entry was created.
4100 // The first element of the metadata node is the kind.
4101 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID),
4102 GetMDInt(FileID), GetMDString(ParentName),
4103 GetMDInt(Line), GetMDInt(E.getOrder())};
Samuel Antaoee8fb302016-01-06 13:42:12 +00004104
Alexey Bataevba643691d2019-10-03 16:20:34 +00004105 SourceLocation Loc;
4106 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(),
4107 E = CGM.getContext().getSourceManager().fileinfo_end();
4108 I != E; ++I) {
4109 if (I->getFirst()->getUniqueID().getDevice() == DeviceID &&
4110 I->getFirst()->getUniqueID().getFile() == FileID) {
4111 Loc = CGM.getContext().getSourceManager().translateFileLineCol(
4112 I->getFirst(), Line, 1);
4113 break;
4114 }
4115 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004116 // Save this entry in the right position of the ordered entries array.
Alexey Bataevba643691d2019-10-03 16:20:34 +00004117 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName);
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004118 ParentFunctions[E.getOrder()] = ParentName;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004119
Alexey Bataev03f270c2018-03-30 18:31:07 +00004120 // Add metadata to the named metadata node.
4121 MD->addOperand(llvm::MDNode::get(C, Ops));
4122 };
Samuel Antaoee8fb302016-01-06 13:42:12 +00004123
4124 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
4125 TargetRegionMetadataEmitter);
4126
Alexey Bataev03f270c2018-03-30 18:31:07 +00004127 // Create function that emits metadata for each device global variable entry;
4128 auto &&DeviceGlobalVarMetadataEmitter =
4129 [&C, &OrderedEntries, &GetMDInt, &GetMDString,
4130 MD](StringRef MangledName,
4131 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar
4132 &E) {
4133 // Generate metadata for global variables. Each entry of this metadata
4134 // contains:
4135 // - Entry 0 -> Kind of this type of metadata (1).
4136 // - Entry 1 -> Mangled name of the variable.
4137 // - Entry 2 -> Declare target kind.
4138 // - Entry 3 -> Order the entry was created.
4139 // The first element of the metadata node is the kind.
4140 llvm::Metadata *Ops[] = {
4141 GetMDInt(E.getKind()), GetMDString(MangledName),
4142 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
4143
4144 // Save this entry in the right position of the ordered entries array.
Alexey Bataevba643691d2019-10-03 16:20:34 +00004145 OrderedEntries[E.getOrder()] =
4146 std::make_tuple(&E, SourceLocation(), MangledName);
Alexey Bataev03f270c2018-03-30 18:31:07 +00004147
4148 // Add metadata to the named metadata node.
4149 MD->addOperand(llvm::MDNode::get(C, Ops));
4150 };
4151
4152 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo(
4153 DeviceGlobalVarMetadataEmitter);
4154
Alexey Bataevba643691d2019-10-03 16:20:34 +00004155 for (const auto &E : OrderedEntries) {
4156 assert(std::get<0>(E) && "All ordered entries must exist!");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004157 if (const auto *CE =
Samuel Antaoee8fb302016-01-06 13:42:12 +00004158 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
Alexey Bataevba643691d2019-10-03 16:20:34 +00004159 std::get<0>(E))) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004160 if (!CE->getID() || !CE->getAddress()) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004161 // Do not blame the entry if the parent funtion is not emitted.
4162 StringRef FnName = ParentFunctions[CE->getOrder()];
4163 if (!CGM.GetGlobalValue(FnName))
4164 continue;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004165 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4166 DiagnosticsEngine::Error,
Alexey Bataevba643691d2019-10-03 16:20:34 +00004167 "Offloading entry for target region in %0 is incorrect: either the "
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004168 "address or the ID is invalid.");
Alexey Bataevba643691d2019-10-03 16:20:34 +00004169 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004170 continue;
4171 }
Alexey Bataev34f8a702018-03-28 14:28:54 +00004172 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004173 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage);
Alexey Bataevba643691d2019-10-03 16:20:34 +00004174 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy::
4175 OffloadEntryInfoDeviceGlobalVar>(
4176 std::get<0>(E))) {
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004177 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags =
4178 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4179 CE->getFlags());
4180 switch (Flags) {
4181 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00004182 if (CGM.getLangOpts().OpenMPIsDevice &&
4183 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())
4184 continue;
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004185 if (!CE->getAddress()) {
4186 unsigned DiagID = CGM.getDiags().getCustomDiagID(
Alexey Bataevba643691d2019-10-03 16:20:34 +00004187 DiagnosticsEngine::Error, "Offloading entry for declare target "
4188 "variable %0 is incorrect: the "
4189 "address is invalid.");
4190 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E);
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004191 continue;
4192 }
Alexey Bataevb4dd6d22018-08-29 20:41:37 +00004193 // The vaiable has no definition - no need to add the entry.
4194 if (CE->getVarSize().isZero())
4195 continue;
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004196 break;
4197 }
4198 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink:
4199 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) ||
4200 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) &&
4201 "Declaret target link address is set.");
4202 if (CGM.getLangOpts().OpenMPIsDevice)
4203 continue;
4204 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 }
4212 break;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004213 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004214 createOffloadEntry(CE->getAddress(), CE->getAddress(),
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004215 CE->getVarSize().getQuantity(), Flags,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004216 CE->getLinkage());
4217 } else {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004218 llvm_unreachable("Unsupported entry kind.");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004219 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004220 }
4221}
4222
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004223/// Loads all the offload entries information from the host IR
Samuel Antaoee8fb302016-01-06 13:42:12 +00004224/// metadata.
4225void CGOpenMPRuntime::loadOffloadInfoMetadata() {
4226 // If we are in target mode, load the metadata from the host IR. This code has
4227 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
4228
4229 if (!CGM.getLangOpts().OpenMPIsDevice)
4230 return;
4231
4232 if (CGM.getLangOpts().OMPHostIRFile.empty())
4233 return;
4234
4235 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004236 if (auto EC = Buf.getError()) {
4237 CGM.getDiags().Report(diag::err_cannot_open_file)
4238 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004239 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004240 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004241
4242 llvm::LLVMContext C;
Peter Collingbourned9445c42016-11-13 07:00:17 +00004243 auto ME = expectedToErrorOrAndEmitErrors(
4244 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004245
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004246 if (auto EC = ME.getError()) {
4247 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4248 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'");
4249 CGM.getDiags().Report(DiagID)
4250 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004251 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004252 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004253
4254 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
4255 if (!MD)
4256 return;
4257
George Burgess IV00f70bd2018-03-01 05:43:23 +00004258 for (llvm::MDNode *MN : MD->operands()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004259 auto &&GetMDInt = [MN](unsigned Idx) {
4260 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004261 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
4262 };
4263
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004264 auto &&GetMDString = [MN](unsigned Idx) {
4265 auto *V = cast<llvm::MDString>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004266 return V->getString();
4267 };
4268
Alexey Bataev03f270c2018-03-30 18:31:07 +00004269 switch (GetMDInt(0)) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004270 default:
4271 llvm_unreachable("Unexpected metadata!");
4272 break;
4273 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
Alexey Bataev34f8a702018-03-28 14:28:54 +00004274 OffloadingEntryInfoTargetRegion:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004275 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
Alexey Bataev03f270c2018-03-30 18:31:07 +00004276 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2),
4277 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4),
4278 /*Order=*/GetMDInt(5));
4279 break;
4280 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
4281 OffloadingEntryInfoDeviceGlobalVar:
4282 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo(
4283 /*MangledName=*/GetMDString(1),
4284 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4285 /*Flags=*/GetMDInt(2)),
4286 /*Order=*/GetMDInt(3));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004287 break;
4288 }
4289 }
4290}
4291
Alexey Bataev62b63b12015-03-10 07:28:44 +00004292void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
4293 if (!KmpRoutineEntryPtrTy) {
4294 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004295 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004296 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
4297 FunctionProtoType::ExtProtoInfo EPI;
4298 KmpRoutineEntryPtrQTy = C.getPointerType(
4299 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
4300 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
4301 }
4302}
4303
Samuel Antaoee8fb302016-01-06 13:42:12 +00004304QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004305 // Make sure the type of the entry is already created. This is the type we
4306 // have to create:
4307 // struct __tgt_offload_entry{
4308 // void *addr; // Pointer to the offload entry info.
4309 // // (function or global)
4310 // char *name; // Name of the function or global.
4311 // size_t size; // Size of the entry info (0 if it a function).
Samuel Antaof83efdb2017-01-05 16:02:49 +00004312 // int32_t flags; // Flags associated with the entry, e.g. 'link'.
4313 // int32_t reserved; // Reserved, to use by the runtime library.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004314 // };
4315 if (TgtOffloadEntryQTy.isNull()) {
4316 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004317 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004318 RD->startDefinition();
4319 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4320 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
4321 addFieldToRecordDecl(C, RD, C.getSizeType());
Samuel Antaof83efdb2017-01-05 16:02:49 +00004322 addFieldToRecordDecl(
4323 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4324 addFieldToRecordDecl(
4325 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004326 RD->completeDefinition();
Jonas Hahnfeld5e4df282018-01-18 15:38:03 +00004327 RD->addAttr(PackedAttr::CreateImplicit(C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004328 TgtOffloadEntryQTy = C.getRecordType(RD);
4329 }
4330 return TgtOffloadEntryQTy;
4331}
4332
4333QualType CGOpenMPRuntime::getTgtDeviceImageQTy() {
4334 // These are the types we need to build:
4335 // struct __tgt_device_image{
4336 // void *ImageStart; // Pointer to the target code start.
4337 // void *ImageEnd; // Pointer to the target code end.
4338 // // We also add the host entries to the device image, as it may be useful
4339 // // for the target runtime to have access to that information.
4340 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all
4341 // // the entries.
4342 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
4343 // // entries (non inclusive).
4344 // };
4345 if (TgtDeviceImageQTy.isNull()) {
4346 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004347 RecordDecl *RD = C.buildImplicitRecord("__tgt_device_image");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004348 RD->startDefinition();
4349 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4350 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4351 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4352 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4353 RD->completeDefinition();
4354 TgtDeviceImageQTy = C.getRecordType(RD);
4355 }
4356 return TgtDeviceImageQTy;
4357}
4358
4359QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() {
4360 // struct __tgt_bin_desc{
4361 // int32_t NumDevices; // Number of devices supported.
4362 // __tgt_device_image *DeviceImages; // Arrays of device images
4363 // // (one per device).
4364 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the
4365 // // entries.
4366 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
4367 // // entries (non inclusive).
4368 // };
4369 if (TgtBinaryDescriptorQTy.isNull()) {
4370 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004371 RecordDecl *RD = C.buildImplicitRecord("__tgt_bin_desc");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004372 RD->startDefinition();
4373 addFieldToRecordDecl(
4374 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4375 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy()));
4376 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4377 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4378 RD->completeDefinition();
4379 TgtBinaryDescriptorQTy = C.getRecordType(RD);
4380 }
4381 return TgtBinaryDescriptorQTy;
4382}
4383
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004384namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00004385struct PrivateHelpersTy {
4386 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
4387 const VarDecl *PrivateElemInit)
4388 : Original(Original), PrivateCopy(PrivateCopy),
4389 PrivateElemInit(PrivateElemInit) {}
4390 const VarDecl *Original;
4391 const VarDecl *PrivateCopy;
4392 const VarDecl *PrivateElemInit;
4393};
4394typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Hans Wennborg7eb54642015-09-10 17:07:54 +00004395} // anonymous namespace
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004396
Alexey Bataev9e034042015-05-05 04:05:12 +00004397static RecordDecl *
Craig Topper8674c5c2015-09-29 04:30:07 +00004398createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004399 if (!Privates.empty()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004400 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004401 // Build struct .kmp_privates_t. {
4402 // /* private vars */
4403 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004404 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t");
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004405 RD->startDefinition();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004406 for (const auto &Pair : Privates) {
4407 const VarDecl *VD = Pair.second.Original;
4408 QualType Type = VD->getType().getNonReferenceType();
4409 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type);
Alexey Bataevc71a4092015-09-11 10:29:41 +00004410 if (VD->hasAttrs()) {
4411 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
4412 E(VD->getAttrs().end());
4413 I != E; ++I)
4414 FD->addAttr(*I);
4415 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004416 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004417 RD->completeDefinition();
4418 return RD;
4419 }
4420 return nullptr;
4421}
4422
Alexey Bataev9e034042015-05-05 04:05:12 +00004423static RecordDecl *
Alexey Bataev7292c292016-04-25 12:22:29 +00004424createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind,
4425 QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004426 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004427 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004428 // Build struct kmp_task_t {
4429 // void * shareds;
4430 // kmp_routine_entry_t routine;
4431 // kmp_int32 part_id;
Alexey Bataevad537bb2016-05-30 09:06:50 +00004432 // kmp_cmplrdata_t data1;
4433 // kmp_cmplrdata_t data2;
Alexey Bataev7292c292016-04-25 12:22:29 +00004434 // For taskloops additional fields:
4435 // kmp_uint64 lb;
4436 // kmp_uint64 ub;
4437 // kmp_int64 st;
4438 // kmp_int32 liter;
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004439 // void * reductions;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004440 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004441 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004442 UD->startDefinition();
4443 addFieldToRecordDecl(C, UD, KmpInt32Ty);
4444 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy);
4445 UD->completeDefinition();
4446 QualType KmpCmplrdataTy = C.getRecordType(UD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004447 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t");
Alexey Bataev62b63b12015-03-10 07:28:44 +00004448 RD->startDefinition();
4449 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4450 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
4451 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004452 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
4453 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004454 if (isOpenMPTaskLoopDirective(Kind)) {
4455 QualType KmpUInt64Ty =
4456 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
4457 QualType KmpInt64Ty =
4458 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
4459 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4460 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4461 addFieldToRecordDecl(C, RD, KmpInt64Ty);
4462 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004463 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004464 }
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004465 RD->completeDefinition();
4466 return RD;
4467}
4468
4469static RecordDecl *
4470createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004471 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004472 ASTContext &C = CGM.getContext();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004473 // Build struct kmp_task_t_with_privates {
4474 // kmp_task_t task_data;
4475 // .kmp_privates_t. privates;
4476 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004477 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004478 RD->startDefinition();
4479 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004480 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates))
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004481 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004482 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004483 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004484}
4485
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004486/// Emit a proxy function which accepts kmp_task_t as the second
Alexey Bataev62b63b12015-03-10 07:28:44 +00004487/// argument.
4488/// \code
4489/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00004490/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt,
Alexey Bataev7292c292016-04-25 12:22:29 +00004491/// For taskloops:
4492/// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004493/// tt->reductions, tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004494/// return 0;
4495/// }
4496/// \endcode
James Y Knight9871db02019-02-05 16:42:33 +00004497static llvm::Function *
Alexey Bataev62b63b12015-03-10 07:28:44 +00004498emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev7292c292016-04-25 12:22:29 +00004499 OpenMPDirectiveKind Kind, QualType KmpInt32Ty,
4500 QualType KmpTaskTWithPrivatesPtrQTy,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004501 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
James Y Knight9871db02019-02-05 16:42:33 +00004502 QualType SharedsPtrTy, llvm::Function *TaskFunction,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004503 llvm::Value *TaskPrivatesMap) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004504 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004505 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004506 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4507 ImplicitParamDecl::Other);
4508 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4509 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4510 ImplicitParamDecl::Other);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004511 Args.push_back(&GtidArg);
4512 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004513 const auto &TaskEntryFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004514 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004515 llvm::FunctionType *TaskEntryTy =
4516 CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004517 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""});
4518 auto *TaskEntry = llvm::Function::Create(
4519 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004520 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004521 TaskEntry->setDoesNotRecurse();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004522 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004523 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args,
4524 Loc, Loc);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004525
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004526 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
Alexey Bataev7292c292016-04-25 12:22:29 +00004527 // tt,
4528 // For taskloops:
4529 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
4530 // tt->task_data.shareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004531 llvm::Value *GtidParam = CGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00004532 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
Alexey Bataev31300ed2016-02-04 11:27:03 +00004533 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4534 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4535 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004536 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004537 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004538 LValue Base =
4539 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004540 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004541 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004542 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08004543 llvm::Value *PartidParam = PartIdLVal.getPointer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004544
4545 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004546 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
4547 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev1e491372018-01-23 18:44:14 +00004548 CGF.EmitLoadOfScalar(SharedsLVal, Loc),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004549 CGF.ConvertTypeForMem(SharedsPtrTy));
4550
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004551 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4552 llvm::Value *PrivatesParam;
4553 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004554 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004555 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08004556 PrivatesLVal.getPointer(), CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004557 } else {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004558 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004559 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004560
Alexey Bataev7292c292016-04-25 12:22:29 +00004561 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam,
4562 TaskPrivatesMap,
4563 CGF.Builder
4564 .CreatePointerBitCastOrAddrSpaceCast(
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08004565 TDBase.getAddress(), CGF.VoidPtrTy)
Alexey Bataev7292c292016-04-25 12:22:29 +00004566 .getPointer()};
4567 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs),
4568 std::end(CommonArgs));
4569 if (isOpenMPTaskLoopDirective(Kind)) {
4570 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004571 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI);
4572 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004573 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004574 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI);
4575 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004576 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004577 LValue StLVal = CGF.EmitLValueForField(Base, *StFI);
4578 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004579 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004580 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4581 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004582 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004583 LValue RLVal = CGF.EmitLValueForField(Base, *RFI);
4584 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004585 CallArgs.push_back(LBParam);
4586 CallArgs.push_back(UBParam);
4587 CallArgs.push_back(StParam);
4588 CallArgs.push_back(LIParam);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004589 CallArgs.push_back(RParam);
Alexey Bataev7292c292016-04-25 12:22:29 +00004590 }
4591 CallArgs.push_back(SharedsParam);
4592
Alexey Bataev3c595a62017-08-14 15:01:03 +00004593 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction,
4594 CallArgs);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004595 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)),
4596 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004597 CGF.FinishFunction();
4598 return TaskEntry;
4599}
4600
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004601static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
4602 SourceLocation Loc,
4603 QualType KmpInt32Ty,
4604 QualType KmpTaskTWithPrivatesPtrQTy,
4605 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004606 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004607 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004608 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4609 ImplicitParamDecl::Other);
4610 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4611 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4612 ImplicitParamDecl::Other);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004613 Args.push_back(&GtidArg);
4614 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004615 const auto &DestructorFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004616 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004617 llvm::FunctionType *DestructorFnTy =
4618 CGM.getTypes().GetFunctionType(DestructorFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004619 std::string Name =
4620 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""});
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004621 auto *DestructorFn =
4622 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00004623 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004624 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004625 DestructorFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004626 DestructorFn->setDoesNotRecurse();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004627 CodeGenFunction CGF(CGM);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004628 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004629 Args, Loc, Loc);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004630
Alexey Bataev31300ed2016-02-04 11:27:03 +00004631 LValue Base = CGF.EmitLoadOfPointerLValue(
4632 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4633 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004634 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004635 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
4636 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004637 Base = CGF.EmitLValueForField(Base, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004638 for (const auto *Field :
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004639 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004640 if (QualType::DestructionKind DtorKind =
4641 Field->getType().isDestructedType()) {
4642 LValue FieldLValue = CGF.EmitLValueForField(Base, Field);
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08004643 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004644 }
4645 }
4646 CGF.FinishFunction();
4647 return DestructorFn;
4648}
4649
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004650/// Emit a privates mapping function for correct handling of private and
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004651/// firstprivate variables.
4652/// \code
4653/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
4654/// **noalias priv1,..., <tyn> **noalias privn) {
4655/// *priv1 = &.privates.priv1;
4656/// ...;
4657/// *privn = &.privates.privn;
4658/// }
4659/// \endcode
4660static llvm::Value *
4661emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Craig Topper8674c5c2015-09-29 04:30:07 +00004662 ArrayRef<const Expr *> PrivateVars,
4663 ArrayRef<const Expr *> FirstprivateVars,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004664 ArrayRef<const Expr *> LastprivateVars,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004665 QualType PrivatesQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004666 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004667 ASTContext &C = CGM.getContext();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004668 FunctionArgList Args;
4669 ImplicitParamDecl TaskPrivatesArg(
4670 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
Alexey Bataev56223232017-06-09 13:40:18 +00004671 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
4672 ImplicitParamDecl::Other);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004673 Args.push_back(&TaskPrivatesArg);
4674 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
4675 unsigned Counter = 1;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004676 for (const Expr *E : PrivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004677 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004678 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4679 C.getPointerType(C.getPointerType(E->getType()))
4680 .withConst()
4681 .withRestrict(),
4682 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004683 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004684 PrivateVarsPos[VD] = Counter;
4685 ++Counter;
4686 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004687 for (const Expr *E : FirstprivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004688 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004689 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4690 C.getPointerType(C.getPointerType(E->getType()))
4691 .withConst()
4692 .withRestrict(),
4693 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004694 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004695 PrivateVarsPos[VD] = Counter;
4696 ++Counter;
4697 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004698 for (const Expr *E : LastprivateVars) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004699 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004700 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4701 C.getPointerType(C.getPointerType(E->getType()))
4702 .withConst()
4703 .withRestrict(),
4704 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004705 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataevf93095a2016-05-05 08:46:22 +00004706 PrivateVarsPos[VD] = Counter;
4707 ++Counter;
4708 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004709 const auto &TaskPrivatesMapFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004710 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004711 llvm::FunctionType *TaskPrivatesMapTy =
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004712 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004713 std::string Name =
4714 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""});
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004715 auto *TaskPrivatesMap = llvm::Function::Create(
Alexey Bataev18fa2322018-05-02 14:20:50 +00004716 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
4717 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004718 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004719 TaskPrivatesMapFnInfo);
Alexey Bataev8c5555c2019-05-21 15:11:58 +00004720 if (CGM.getLangOpts().Optimize) {
4721 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
4722 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
4723 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
4724 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004725 CodeGenFunction CGF(CGM);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004726 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004727 TaskPrivatesMapFnInfo, Args, Loc, Loc);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004728
4729 // *privi = &.privates.privi;
Alexey Bataev31300ed2016-02-04 11:27:03 +00004730 LValue Base = CGF.EmitLoadOfPointerLValue(
4731 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
4732 TaskPrivatesArg.getType()->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004733 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004734 Counter = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004735 for (const FieldDecl *Field : PrivatesQTyRD->fields()) {
4736 LValue FieldLVal = CGF.EmitLValueForField(Base, Field);
4737 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
4738 LValue RefLVal =
4739 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
4740 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue(
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08004741 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>());
4742 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004743 ++Counter;
4744 }
4745 CGF.FinishFunction();
4746 return TaskPrivatesMap;
4747}
4748
Alexey Bataevf93095a2016-05-05 08:46:22 +00004749/// Emit initialization for private variables in task-based directives.
Alexey Bataev8a831592016-05-10 10:36:51 +00004750static void emitPrivatesInit(CodeGenFunction &CGF,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004751 const OMPExecutableDirective &D,
4752 Address KmpTaskSharedsPtr, LValue TDBase,
4753 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4754 QualType SharedsTy, QualType SharedsPtrTy,
4755 const OMPTaskDataTy &Data,
4756 ArrayRef<PrivateDataTy> Privates, bool ForDup) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004757 ASTContext &C = CGF.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004758 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
4759 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004760 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind())
4761 ? OMPD_taskloop
4762 : OMPD_task;
4763 const CapturedStmt &CS = *D.getCapturedStmt(Kind);
4764 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004765 LValue SrcBase;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004766 bool IsTargetTask =
4767 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) ||
4768 isOpenMPTargetExecutionDirective(D.getDirectiveKind());
4769 // For target-based directives skip 3 firstprivate arrays BasePointersArray,
4770 // PointersArray and SizesArray. The original variables for these arrays are
4771 // not captured and we get their addresses explicitly.
4772 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) ||
Alexey Bataev8451efa2018-01-15 19:06:12 +00004773 (IsTargetTask && KmpTaskSharedsPtr.isValid())) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004774 SrcBase = CGF.MakeAddrLValue(
4775 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4776 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
4777 SharedsTy);
4778 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004779 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004780 for (const PrivateDataTy &Pair : Privates) {
4781 const VarDecl *VD = Pair.second.PrivateCopy;
4782 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004783 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) &&
4784 !CGF.isTrivialInitializer(Init)))) {
Alexey Bataev8a831592016-05-10 10:36:51 +00004785 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004786 if (const VarDecl *Elem = Pair.second.PrivateElemInit) {
4787 const VarDecl *OriginalVD = Pair.second.Original;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004788 // Check if the variable is the target-based BasePointersArray,
4789 // PointersArray or SizesArray.
4790 LValue SharedRefLValue;
Alexey Bataevab41ea62019-03-13 20:46:28 +00004791 QualType Type = PrivateLValue.getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004792 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004793 if (IsTargetTask && !SharedField) {
4794 assert(isa<ImplicitParamDecl>(OriginalVD) &&
4795 isa<CapturedDecl>(OriginalVD->getDeclContext()) &&
4796 cast<CapturedDecl>(OriginalVD->getDeclContext())
4797 ->getNumParams() == 0 &&
4798 isa<TranslationUnitDecl>(
4799 cast<CapturedDecl>(OriginalVD->getDeclContext())
4800 ->getDeclContext()) &&
4801 "Expected artificial target data variable.");
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004802 SharedRefLValue =
4803 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type);
4804 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004805 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField);
4806 SharedRefLValue = CGF.MakeAddrLValue(
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08004807 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004808 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl),
4809 SharedRefLValue.getTBAAInfo());
4810 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004811 if (Type->isArrayType()) {
4812 // Initialize firstprivate array.
4813 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) {
4814 // Perform simple memcpy.
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00004815 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004816 } else {
4817 // Initialize firstprivate array using element-by-element
Simon Pilgrim2c518802017-03-30 14:13:19 +00004818 // initialization.
Alexey Bataevf93095a2016-05-05 08:46:22 +00004819 CGF.EmitOMPAggregateAssign(
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08004820 PrivateLValue.getAddress(), SharedRefLValue.getAddress(), Type,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004821 [&CGF, Elem, Init, &CapturesInfo](Address DestElement,
4822 Address SrcElement) {
4823 // Clean up any temporaries needed by the initialization.
4824 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4825 InitScope.addPrivate(
4826 Elem, [SrcElement]() -> Address { return SrcElement; });
4827 (void)InitScope.Privatize();
4828 // Emit initialization for single element.
4829 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
4830 CGF, &CapturesInfo);
4831 CGF.EmitAnyExprToMem(Init, DestElement,
4832 Init->getType().getQualifiers(),
4833 /*IsInitializer=*/false);
4834 });
4835 }
4836 } else {
4837 CodeGenFunction::OMPPrivateScope InitScope(CGF);
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08004838 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
4839 return SharedRefLValue.getAddress();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004840 });
4841 (void)InitScope.Privatize();
4842 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
4843 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
4844 /*capturedByInit=*/false);
4845 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004846 } else {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004847 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004848 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004849 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004850 ++FI;
4851 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004852}
4853
4854/// Check if duplication function is required for taskloops.
4855static bool checkInitIsRequired(CodeGenFunction &CGF,
4856 ArrayRef<PrivateDataTy> Privates) {
4857 bool InitRequired = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004858 for (const PrivateDataTy &Pair : Privates) {
4859 const VarDecl *VD = Pair.second.PrivateCopy;
4860 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004861 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) &&
4862 !CGF.isTrivialInitializer(Init));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004863 if (InitRequired)
4864 break;
Alexey Bataevf93095a2016-05-05 08:46:22 +00004865 }
4866 return InitRequired;
4867}
4868
4869
4870/// Emit task_dup function (for initialization of
4871/// private/firstprivate/lastprivate vars and last_iter flag)
4872/// \code
4873/// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int
4874/// lastpriv) {
4875/// // setup lastprivate flag
4876/// task_dst->last = lastpriv;
4877/// // could be constructor calls here...
4878/// }
4879/// \endcode
4880static llvm::Value *
4881emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
4882 const OMPExecutableDirective &D,
4883 QualType KmpTaskTWithPrivatesPtrQTy,
4884 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4885 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy,
4886 QualType SharedsPtrTy, const OMPTaskDataTy &Data,
4887 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004888 ASTContext &C = CGM.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004889 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004890 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4891 KmpTaskTWithPrivatesPtrQTy,
4892 ImplicitParamDecl::Other);
4893 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4894 KmpTaskTWithPrivatesPtrQTy,
4895 ImplicitParamDecl::Other);
4896 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy,
4897 ImplicitParamDecl::Other);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004898 Args.push_back(&DstArg);
4899 Args.push_back(&SrcArg);
4900 Args.push_back(&LastprivArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004901 const auto &TaskDupFnInfo =
Alexey Bataevf93095a2016-05-05 08:46:22 +00004902 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004903 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004904 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""});
4905 auto *TaskDup = llvm::Function::Create(
4906 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004907 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004908 TaskDup->setDoesNotRecurse();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004909 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004910 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc,
4911 Loc);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004912
4913 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4914 CGF.GetAddrOfLocalVar(&DstArg),
4915 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4916 // task_dst->liter = lastpriv;
4917 if (WithLastIter) {
4918 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
4919 LValue Base = CGF.EmitLValueForField(
4920 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4921 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4922 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar(
4923 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc);
4924 CGF.EmitStoreOfScalar(Lastpriv, LILVal);
4925 }
4926
4927 // Emit initial values for private copies (if any).
4928 assert(!Privates.empty());
4929 Address KmpTaskSharedsPtr = Address::invalid();
4930 if (!Data.FirstprivateVars.empty()) {
4931 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4932 CGF.GetAddrOfLocalVar(&SrcArg),
4933 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4934 LValue Base = CGF.EmitLValueForField(
4935 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4936 KmpTaskSharedsPtr = Address(
4937 CGF.EmitLoadOfScalar(CGF.EmitLValueForField(
4938 Base, *std::next(KmpTaskTQTyRD->field_begin(),
4939 KmpTaskTShareds)),
4940 Loc),
4941 CGF.getNaturalTypeAlignment(SharedsTy));
4942 }
Alexey Bataev8a831592016-05-10 10:36:51 +00004943 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
4944 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004945 CGF.FinishFunction();
4946 return TaskDup;
4947}
4948
Alexey Bataev8a831592016-05-10 10:36:51 +00004949/// Checks if destructor function is required to be generated.
4950/// \return true if cleanups are required, false otherwise.
4951static bool
4952checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) {
4953 bool NeedsCleanup = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004954 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4955 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl());
4956 for (const FieldDecl *FD : PrivateRD->fields()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00004957 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType();
4958 if (NeedsCleanup)
4959 break;
4960 }
4961 return NeedsCleanup;
4962}
4963
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004964CGOpenMPRuntime::TaskResultTy
4965CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
4966 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00004967 llvm::Function *TaskFunction, QualType SharedsTy,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004968 Address Shareds, const OMPTaskDataTy &Data) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004969 ASTContext &C = CGM.getContext();
Alexey Bataev7292c292016-04-25 12:22:29 +00004970 llvm::SmallVector<PrivateDataTy, 4> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004971 // Aggregate privates and sort them by the alignment.
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004972 auto I = Data.PrivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004973 for (const Expr *E : Data.PrivateVars) {
4974 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00004975 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00004976 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00004977 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00004978 /*PrivateElemInit=*/nullptr));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004979 ++I;
4980 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004981 I = Data.FirstprivateCopies.begin();
4982 auto IElemInitRef = Data.FirstprivateInits.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004983 for (const Expr *E : Data.FirstprivateVars) {
4984 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00004985 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00004986 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00004987 PrivateHelpersTy(
4988 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00004989 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())));
Richard Trieucc3949d2016-02-18 22:34:54 +00004990 ++I;
4991 ++IElemInitRef;
Alexey Bataev9e034042015-05-05 04:05:12 +00004992 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004993 I = Data.LastprivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004994 for (const Expr *E : Data.LastprivateVars) {
4995 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00004996 Privates.emplace_back(
Alexey Bataevf93095a2016-05-05 08:46:22 +00004997 C.getDeclAlign(VD),
4998 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00004999 /*PrivateElemInit=*/nullptr));
Alexey Bataevf93095a2016-05-05 08:46:22 +00005000 ++I;
5001 }
Fangrui Song899d1392019-04-24 14:43:05 +00005002 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) {
5003 return L.first > R.first;
5004 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005005 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005006 // Build type kmp_routine_entry_t (if not built yet).
5007 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005008 // Build type kmp_task_t (if not built yet).
Alexey Bataeve213f3e2017-10-11 15:29:40 +00005009 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) {
5010 if (SavedKmpTaskloopTQTy.isNull()) {
5011 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5012 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5013 }
5014 KmpTaskTQTy = SavedKmpTaskloopTQTy;
Alexey Bataev3a03a7f2017-10-11 15:56:38 +00005015 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00005016 assert((D.getDirectiveKind() == OMPD_task ||
5017 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) ||
5018 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) &&
5019 "Expected taskloop, task or target directive");
Alexey Bataeve213f3e2017-10-11 15:29:40 +00005020 if (SavedKmpTaskTQTy.isNull()) {
5021 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5022 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5023 }
5024 KmpTaskTQTy = SavedKmpTaskTQTy;
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005025 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005026 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005027 // Build particular struct kmp_task_t for the given task.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005028 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005029 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005030 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005031 QualType KmpTaskTWithPrivatesPtrQTy =
5032 C.getPointerType(KmpTaskTWithPrivatesQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005033 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
5034 llvm::Type *KmpTaskTWithPrivatesPtrTy =
5035 KmpTaskTWithPrivatesTy->getPointerTo();
5036 llvm::Value *KmpTaskTWithPrivatesTySize =
5037 CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005038 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
5039
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005040 // Emit initial values for private copies (if any).
5041 llvm::Value *TaskPrivatesMap = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005042 llvm::Type *TaskPrivatesMapTy =
James Y Knight9871db02019-02-05 16:42:33 +00005043 std::next(TaskFunction->arg_begin(), 3)->getType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005044 if (!Privates.empty()) {
5045 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataevf93095a2016-05-05 08:46:22 +00005046 TaskPrivatesMap = emitTaskPrivateMappingFunction(
5047 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars,
5048 FI->getType(), Privates);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005049 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5050 TaskPrivatesMap, TaskPrivatesMapTy);
5051 } else {
5052 TaskPrivatesMap = llvm::ConstantPointerNull::get(
5053 cast<llvm::PointerType>(TaskPrivatesMapTy));
5054 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005055 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
5056 // kmp_task_t *tt);
James Y Knight9871db02019-02-05 16:42:33 +00005057 llvm::Function *TaskEntry = emitProxyTaskFunction(
Alexey Bataev7292c292016-04-25 12:22:29 +00005058 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5059 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction,
5060 TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005061
5062 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
5063 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
5064 // kmp_routine_entry_t *task_entry);
5065 // Task flags. Format is taken from
James Y Knight5d71fc52019-01-29 16:37:27 +00005066 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h,
Alexey Bataev62b63b12015-03-10 07:28:44 +00005067 // description of kmp_tasking_flags struct.
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005068 enum {
5069 TiedFlag = 0x1,
5070 FinalFlag = 0x2,
5071 DestructorsFlag = 0x8,
5072 PriorityFlag = 0x20
5073 };
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005074 unsigned Flags = Data.Tied ? TiedFlag : 0;
Alexey Bataev8a831592016-05-10 10:36:51 +00005075 bool NeedsCleanup = false;
5076 if (!Privates.empty()) {
5077 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD);
5078 if (NeedsCleanup)
5079 Flags = Flags | DestructorsFlag;
5080 }
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005081 if (Data.Priority.getInt())
5082 Flags = Flags | PriorityFlag;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005083 llvm::Value *TaskFlags =
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005084 Data.Final.getPointer()
5085 ? CGF.Builder.CreateSelect(Data.Final.getPointer(),
Alexey Bataev62b63b12015-03-10 07:28:44 +00005086 CGF.Builder.getInt32(FinalFlag),
5087 CGF.Builder.getInt32(/*C=*/0))
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005088 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005089 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005090 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00005091 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc),
5092 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
5093 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5094 TaskEntry, KmpRoutineEntryPtrTy)};
5095 llvm::Value *NewTask;
5096 if (D.hasClausesOfKind<OMPNowaitClause>()) {
5097 // Check if we have any device clause associated with the directive.
5098 const Expr *Device = nullptr;
5099 if (auto *C = D.getSingleClause<OMPDeviceClause>())
5100 Device = C->getDevice();
5101 // Emit device ID if any otherwise use default value.
5102 llvm::Value *DeviceID;
5103 if (Device)
5104 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
5105 CGF.Int64Ty, /*isSigned=*/true);
5106 else
5107 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
5108 AllocArgs.push_back(DeviceID);
5109 NewTask = CGF.EmitRuntimeCall(
5110 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs);
5111 } else {
5112 NewTask = CGF.EmitRuntimeCall(
Alexey Bataev62b63b12015-03-10 07:28:44 +00005113 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00005114 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005115 llvm::Value *NewTaskNewTaskTTy =
5116 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5117 NewTask, KmpTaskTWithPrivatesPtrTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005118 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
5119 KmpTaskTWithPrivatesQTy);
5120 LValue TDBase =
5121 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005122 // Fill the data in the resulting kmp_task_t record.
5123 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00005124 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005125 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00005126 KmpTaskSharedsPtr =
5127 Address(CGF.EmitLoadOfScalar(
5128 CGF.EmitLValueForField(
5129 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
5130 KmpTaskTShareds)),
5131 Loc),
5132 CGF.getNaturalTypeAlignment(SharedsTy));
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00005133 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy);
5134 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy);
Richard Smithe78fac52018-04-05 20:52:58 +00005135 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005136 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005137 // Emit initial values for private copies (if any).
Alexey Bataevf93095a2016-05-05 08:46:22 +00005138 TaskResultTy Result;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005139 if (!Privates.empty()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00005140 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD,
5141 SharedsTy, SharedsPtrTy, Data, Privates,
5142 /*ForDup=*/false);
Alexey Bataevf93095a2016-05-05 08:46:22 +00005143 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
5144 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) {
5145 Result.TaskDupFn = emitTaskDupFunction(
5146 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
5147 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates,
5148 /*WithLastIter=*/!Data.LastprivateVars.empty());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005149 }
5150 }
Alexey Bataevad537bb2016-05-30 09:06:50 +00005151 // Fields of union "kmp_cmplrdata_t" for destructors and priority.
5152 enum { Priority = 0, Destructors = 1 };
Alexey Bataev62b63b12015-03-10 07:28:44 +00005153 // Provide pointer to function with destructors for privates.
Alexey Bataevad537bb2016-05-30 09:06:50 +00005154 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005155 const RecordDecl *KmpCmplrdataUD =
5156 (*FI)->getType()->getAsUnionType()->getDecl();
Alexey Bataevad537bb2016-05-30 09:06:50 +00005157 if (NeedsCleanup) {
5158 llvm::Value *DestructorFn = emitDestructorsFunction(
5159 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5160 KmpTaskTWithPrivatesQTy);
5161 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI);
5162 LValue DestructorsLV = CGF.EmitLValueForField(
5163 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
5164 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5165 DestructorFn, KmpRoutineEntryPtrTy),
5166 DestructorsLV);
5167 }
5168 // Set priority.
5169 if (Data.Priority.getInt()) {
5170 LValue Data2LV = CGF.EmitLValueForField(
5171 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
5172 LValue PriorityLV = CGF.EmitLValueForField(
5173 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
5174 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV);
5175 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005176 Result.NewTask = NewTask;
5177 Result.TaskEntry = TaskEntry;
5178 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
5179 Result.TDBase = TDBase;
5180 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
5181 return Result;
Alexey Bataev7292c292016-04-25 12:22:29 +00005182}
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005183
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005184void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
5185 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005186 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005187 QualType SharedsTy, Address Shareds,
5188 const Expr *IfCond,
5189 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005190 if (!CGF.HaveInsertPoint())
5191 return;
5192
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005193 TaskResultTy Result =
5194 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
5195 llvm::Value *NewTask = Result.NewTask;
James Y Knight9871db02019-02-05 16:42:33 +00005196 llvm::Function *TaskEntry = Result.TaskEntry;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005197 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy;
5198 LValue TDBase = Result.TDBase;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005199 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD;
5200 ASTContext &C = CGM.getContext();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005201 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00005202 Address DependenciesArray = Address::invalid();
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005203 unsigned NumDependencies = Data.Dependences.size();
John McCall7f416cc2015-09-08 08:05:57 +00005204 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005205 // Dependence kind for RTL.
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005206 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 };
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005207 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
5208 RecordDecl *KmpDependInfoRD;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005209 QualType FlagsTy =
5210 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005211 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
5212 if (KmpDependInfoTy.isNull()) {
5213 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
5214 KmpDependInfoRD->startDefinition();
5215 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
5216 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
5217 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
5218 KmpDependInfoRD->completeDefinition();
5219 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005220 } else {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005221 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005222 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005223 // Define type kmp_depend_info[<Dependences.size()>];
5224 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00005225 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Richard Smith772e2662019-10-04 01:25:59 +00005226 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005227 // kmp_depend_info[<Dependences.size()>] deps;
Alexey Bataev48591dd2016-04-20 04:01:36 +00005228 DependenciesArray =
5229 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005230 for (unsigned I = 0; I < NumDependencies; ++I) {
5231 const Expr *E = Data.Dependences[I].second;
5232 LValue Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005233 llvm::Value *Size;
5234 QualType Ty = E->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005235 if (const auto *ASE =
5236 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005237 LValue UpAddrLVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005238 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false);
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08005239 llvm::Value *UpAddr =
5240 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005241 llvm::Value *LowIntPtr =
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08005242 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005243 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
5244 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005245 } else {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005246 Size = CGF.getTypeSize(Ty);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005247 }
5248 LValue Base = CGF.MakeAddrLValue(
James Y Knight751fe282019-02-09 22:22:28 +00005249 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005250 KmpDependInfoTy);
5251 // deps[i].base_addr = &<Dependences[i].second>;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005252 LValue BaseAddrLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005253 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00005254 CGF.EmitStoreOfScalar(
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08005255 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy),
John McCall7f416cc2015-09-08 08:05:57 +00005256 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005257 // deps[i].len = sizeof(<Dependences[i].second>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005258 LValue LenLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005259 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
5260 CGF.EmitStoreOfScalar(Size, LenLVal);
5261 // deps[i].flags = <Dependences[i].first>;
5262 RTLDependenceKindTy DepKind;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005263 switch (Data.Dependences[I].first) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005264 case OMPC_DEPEND_in:
5265 DepKind = DepIn;
5266 break;
Alexey Bataev92e82f92015-11-23 13:33:42 +00005267 // Out and InOut dependencies must use the same code.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005268 case OMPC_DEPEND_out:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005269 case OMPC_DEPEND_inout:
5270 DepKind = DepInOut;
5271 break;
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005272 case OMPC_DEPEND_mutexinoutset:
5273 DepKind = DepMutexInOutSet;
5274 break;
Alexey Bataeveb482352015-12-18 05:05:56 +00005275 case OMPC_DEPEND_source:
Alexey Bataeva636c7f2015-12-23 10:27:45 +00005276 case OMPC_DEPEND_sink:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005277 case OMPC_DEPEND_unknown:
5278 llvm_unreachable("Unknown task dependence type");
5279 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005280 LValue FlagsLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005281 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
5282 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
5283 FlagsLVal);
5284 }
John McCall7f416cc2015-09-08 08:05:57 +00005285 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knightf5f1b0e2019-02-08 15:34:12 +00005286 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005287 }
5288
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005289 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev62b63b12015-03-10 07:28:44 +00005290 // libcall.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005291 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
5292 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
5293 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
5294 // list is not empty
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005295 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5296 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00005297 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
5298 llvm::Value *DepTaskArgs[7];
5299 if (NumDependencies) {
5300 DepTaskArgs[0] = UpLoc;
5301 DepTaskArgs[1] = ThreadID;
5302 DepTaskArgs[2] = NewTask;
5303 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
5304 DepTaskArgs[4] = DependenciesArray.getPointer();
5305 DepTaskArgs[5] = CGF.Builder.getInt32(0);
5306 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5307 }
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005308 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies,
5309 &TaskArgs,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005310 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005311 if (!Data.Tied) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005312 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005313 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
Alexey Bataev48591dd2016-04-20 04:01:36 +00005314 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
5315 }
John McCall7f416cc2015-09-08 08:05:57 +00005316 if (NumDependencies) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005317 CGF.EmitRuntimeCall(
Alexey Bataev48591dd2016-04-20 04:01:36 +00005318 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs);
John McCall7f416cc2015-09-08 08:05:57 +00005319 } else {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005320 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
John McCall7f416cc2015-09-08 08:05:57 +00005321 TaskArgs);
5322 }
Alexey Bataev48591dd2016-04-20 04:01:36 +00005323 // Check if parent region is untied and build return for untied task;
5324 if (auto *Region =
5325 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
5326 Region->emitUntiedSwitch(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00005327 };
John McCall7f416cc2015-09-08 08:05:57 +00005328
5329 llvm::Value *DepWaitTaskArgs[6];
5330 if (NumDependencies) {
5331 DepWaitTaskArgs[0] = UpLoc;
5332 DepWaitTaskArgs[1] = ThreadID;
5333 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
5334 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
5335 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
5336 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5337 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005338 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
Alexey Bataev3c595a62017-08-14 15:01:03 +00005339 NumDependencies, &DepWaitTaskArgs,
5340 Loc](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005341 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005342 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
5343 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
5344 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
5345 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
5346 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00005347 if (NumDependencies)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005348 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005349 DepWaitTaskArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005350 // Call proxy_task_entry(gtid, new_task);
Alexey Bataev3c595a62017-08-14 15:01:03 +00005351 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
5352 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005353 Action.Enter(CGF);
5354 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
Alexey Bataev3c595a62017-08-14 15:01:03 +00005355 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
Alexey Bataev2c7eee52017-08-04 19:10:54 +00005356 OutlinedFnArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005357 };
5358
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005359 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
5360 // kmp_task_t *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005361 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
5362 // kmp_task_t *new_task);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005363 RegionCodeGenTy RCG(CodeGen);
5364 CommonActionTy Action(
5365 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs,
5366 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs);
5367 RCG.setAction(Action);
5368 RCG(CGF);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005369 };
John McCall7f416cc2015-09-08 08:05:57 +00005370
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005371 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -05005372 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005373 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005374 RegionCodeGenTy ThenRCG(ThenCodeGen);
5375 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00005376 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005377}
5378
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005379void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
5380 const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005381 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005382 QualType SharedsTy, Address Shareds,
5383 const Expr *IfCond,
5384 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005385 if (!CGF.HaveInsertPoint())
5386 return;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005387 TaskResultTy Result =
5388 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005389 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev7292c292016-04-25 12:22:29 +00005390 // libcall.
5391 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
5392 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
5393 // sched, kmp_uint64 grainsize, void *task_dup);
5394 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5395 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
5396 llvm::Value *IfVal;
5397 if (IfCond) {
5398 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy,
5399 /*isSigned=*/true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005400 } else {
Alexey Bataev7292c292016-04-25 12:22:29 +00005401 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005402 }
Alexey Bataev7292c292016-04-25 12:22:29 +00005403
5404 LValue LBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005405 Result.TDBase,
5406 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005407 const auto *LBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005408 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl());
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08005409 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(),
Alexey Bataev7292c292016-04-25 12:22:29 +00005410 /*IsInitializer=*/true);
5411 LValue UBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005412 Result.TDBase,
5413 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005414 const auto *UBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005415 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl());
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08005416 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(),
Alexey Bataev7292c292016-04-25 12:22:29 +00005417 /*IsInitializer=*/true);
5418 LValue StLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005419 Result.TDBase,
5420 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005421 const auto *StVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005422 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl());
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08005423 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(),
Alexey Bataev7292c292016-04-25 12:22:29 +00005424 /*IsInitializer=*/true);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005425 // Store reductions address.
5426 LValue RedLVal = CGF.EmitLValueForField(
5427 Result.TDBase,
5428 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005429 if (Data.Reductions) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005430 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005431 } else {
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08005432 CGF.EmitNullInitialization(RedLVal.getAddress(),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005433 CGF.getContext().VoidPtrTy);
5434 }
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005435 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
Alexey Bataev7292c292016-04-25 12:22:29 +00005436 llvm::Value *TaskArgs[] = {
Alexey Bataev33446032017-07-12 18:09:32 +00005437 UpLoc,
5438 ThreadID,
5439 Result.NewTask,
5440 IfVal,
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08005441 LBLVal.getPointer(),
5442 UBLVal.getPointer(),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00005443 CGF.EmitLoadOfScalar(StLVal, Loc),
Alexey Bataevac6e4de2018-10-24 19:06:37 +00005444 llvm::ConstantInt::getSigned(
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08005445 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005446 llvm::ConstantInt::getSigned(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005447 CGF.IntTy, Data.Schedule.getPointer()
5448 ? Data.Schedule.getInt() ? NumTasks : Grainsize
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005449 : NoSchedule),
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005450 Data.Schedule.getPointer()
5451 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty,
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005452 /*isSigned=*/false)
5453 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0),
Alexey Bataev33446032017-07-12 18:09:32 +00005454 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5455 Result.TaskDupFn, CGF.VoidPtrTy)
5456 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)};
Alexey Bataev7292c292016-04-25 12:22:29 +00005457 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs);
5458}
5459
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005460/// Emit reduction operation for each element of array (required for
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005461/// array sections) LHS op = RHS.
5462/// \param Type Type of array.
5463/// \param LHSVar Variable on the left side of the reduction operation
5464/// (references element of array in original variable).
5465/// \param RHSVar Variable on the right side of the reduction operation
5466/// (references element of array in original variable).
5467/// \param RedOpGen Generator of reduction operation with use of LHSVar and
5468/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00005469static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005470 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
5471 const VarDecl *RHSVar,
5472 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
5473 const Expr *, const Expr *)> &RedOpGen,
5474 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
5475 const Expr *UpExpr = nullptr) {
5476 // Perform element-by-element initialization.
5477 QualType ElementTy;
5478 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
5479 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
5480
5481 // Drill down to the base element type on both arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005482 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
5483 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005484
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005485 llvm::Value *RHSBegin = RHSAddr.getPointer();
5486 llvm::Value *LHSBegin = LHSAddr.getPointer();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005487 // Cast from pointer to array type to pointer to single element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005488 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005489 // The basic structure here is a while-do loop.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005490 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
5491 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
5492 llvm::Value *IsEmpty =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005493 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
5494 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
5495
5496 // Enter the loop body, making that address the current address.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005497 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005498 CGF.EmitBlock(BodyBB);
5499
5500 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
5501
5502 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
5503 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
5504 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
5505 Address RHSElementCurrent =
5506 Address(RHSElementPHI,
5507 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5508
5509 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
5510 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
5511 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
5512 Address LHSElementCurrent =
5513 Address(LHSElementPHI,
5514 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5515
5516 // Emit copy.
5517 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005518 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; });
5519 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005520 Scope.Privatize();
5521 RedOpGen(CGF, XExpr, EExpr, UpExpr);
5522 Scope.ForceCleanup();
5523
5524 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005525 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005526 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005527 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005528 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
5529 // Check whether we've reached the end.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005530 llvm::Value *Done =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005531 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
5532 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
5533 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
5534 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
5535
5536 // Done.
5537 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
5538}
5539
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005540/// Emit reduction combiner. If the combiner is a simple expression emit it as
5541/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
5542/// UDR combiner function.
5543static void emitReductionCombiner(CodeGenFunction &CGF,
5544 const Expr *ReductionOp) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005545 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
5546 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
5547 if (const auto *DRE =
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005548 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005549 if (const auto *DRD =
5550 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005551 std::pair<llvm::Function *, llvm::Function *> Reduction =
5552 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
5553 RValue Func = RValue::get(Reduction.first);
5554 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
5555 CGF.EmitIgnoredExpr(ReductionOp);
5556 return;
5557 }
5558 CGF.EmitIgnoredExpr(ReductionOp);
5559}
5560
James Y Knight9871db02019-02-05 16:42:33 +00005561llvm::Function *CGOpenMPRuntime::emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005562 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates,
5563 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
5564 ArrayRef<const Expr *> ReductionOps) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005565 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005566
5567 // void reduction_func(void *LHSArg, void *RHSArg);
5568 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005569 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5570 ImplicitParamDecl::Other);
5571 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5572 ImplicitParamDecl::Other);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005573 Args.push_back(&LHSArg);
5574 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005575 const auto &CGFI =
5576 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00005577 std::string Name = getName({"omp", "reduction", "reduction_func"});
5578 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
5579 llvm::GlobalValue::InternalLinkage, Name,
5580 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00005581 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00005582 Fn->setDoesNotRecurse();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005583 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005584 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005585
5586 // Dst = (void*[n])(LHSArg);
5587 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00005588 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5589 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
5590 ArgsType), CGF.getPointerAlign());
5591 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5592 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
5593 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005594
5595 // ...
5596 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
5597 // ...
5598 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005599 auto IPriv = Privates.begin();
5600 unsigned Idx = 0;
5601 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005602 const auto *RHSVar =
5603 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
5604 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005605 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005606 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005607 const auto *LHSVar =
5608 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
5609 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005610 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005611 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005612 QualType PrivTy = (*IPriv)->getType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00005613 if (PrivTy->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005614 // Get array size and emit VLA type.
5615 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005616 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005617 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005618 const VariableArrayType *VLA =
5619 CGF.getContext().getAsVariableArrayType(PrivTy);
5620 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005621 CodeGenFunction::OpaqueValueMapping OpaqueMap(
Alexey Bataev1189bd02016-01-26 12:20:39 +00005622 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005623 CGF.EmitVariablyModifiedType(PrivTy);
5624 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005625 }
5626 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005627 IPriv = Privates.begin();
5628 auto ILHS = LHSExprs.begin();
5629 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005630 for (const Expr *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005631 if ((*IPriv)->getType()->isArrayType()) {
5632 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005633 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5634 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005635 EmitOMPAggregateReduction(
5636 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5637 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5638 emitReductionCombiner(CGF, E);
5639 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005640 } else {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005641 // Emit reduction for array subscript or single variable.
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005642 emitReductionCombiner(CGF, E);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005643 }
Richard Trieucc3949d2016-02-18 22:34:54 +00005644 ++IPriv;
5645 ++ILHS;
5646 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005647 }
5648 Scope.ForceCleanup();
5649 CGF.FinishFunction();
5650 return Fn;
5651}
5652
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005653void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF,
5654 const Expr *ReductionOp,
5655 const Expr *PrivateRef,
5656 const DeclRefExpr *LHS,
5657 const DeclRefExpr *RHS) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005658 if (PrivateRef->getType()->isArrayType()) {
5659 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005660 const auto *LHSVar = cast<VarDecl>(LHS->getDecl());
5661 const auto *RHSVar = cast<VarDecl>(RHS->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005662 EmitOMPAggregateReduction(
5663 CGF, PrivateRef->getType(), LHSVar, RHSVar,
5664 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5665 emitReductionCombiner(CGF, ReductionOp);
5666 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005667 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005668 // Emit reduction for array subscript or single variable.
5669 emitReductionCombiner(CGF, ReductionOp);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005670 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005671}
5672
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005673void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005674 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005675 ArrayRef<const Expr *> LHSExprs,
5676 ArrayRef<const Expr *> RHSExprs,
5677 ArrayRef<const Expr *> ReductionOps,
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005678 ReductionOptionsTy Options) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00005679 if (!CGF.HaveInsertPoint())
5680 return;
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005681
5682 bool WithNowait = Options.WithNowait;
5683 bool SimpleReduction = Options.SimpleReduction;
5684
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005685 // Next code should be emitted for reduction:
5686 //
5687 // static kmp_critical_name lock = { 0 };
5688 //
5689 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
5690 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
5691 // ...
5692 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
5693 // *(Type<n>-1*)rhs[<n>-1]);
5694 // }
5695 //
5696 // ...
5697 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
5698 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5699 // RedList, reduce_func, &<lock>)) {
5700 // case 1:
5701 // ...
5702 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5703 // ...
5704 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5705 // break;
5706 // case 2:
5707 // ...
5708 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5709 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00005710 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005711 // break;
5712 // default:;
5713 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005714 //
5715 // if SimpleReduction is true, only the next code is generated:
5716 // ...
5717 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5718 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005719
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005720 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005721
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005722 if (SimpleReduction) {
5723 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005724 auto IPriv = Privates.begin();
5725 auto ILHS = LHSExprs.begin();
5726 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005727 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005728 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5729 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005730 ++IPriv;
5731 ++ILHS;
5732 ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005733 }
5734 return;
5735 }
5736
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005737 // 1. Build a list of reduction variables.
5738 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005739 auto Size = RHSExprs.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005740 for (const Expr *E : Privates) {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005741 if (E->getType()->isVariablyModifiedType())
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005742 // Reserve place for array size.
5743 ++Size;
5744 }
5745 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005746 QualType ReductionArrayTy =
Richard Smith772e2662019-10-04 01:25:59 +00005747 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005748 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00005749 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005750 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005751 auto IPriv = Privates.begin();
5752 unsigned Idx = 0;
5753 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
James Y Knight751fe282019-02-09 22:22:28 +00005754 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
John McCall7f416cc2015-09-08 08:05:57 +00005755 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005756 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08005757 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
John McCall7f416cc2015-09-08 08:05:57 +00005758 Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005759 if ((*IPriv)->getType()->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005760 // Store array size.
5761 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005762 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005763 llvm::Value *Size = CGF.Builder.CreateIntCast(
5764 CGF.getVLASize(
5765 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
Sander de Smalen891af03a2018-02-03 13:55:59 +00005766 .NumElts,
Alexey Bataev1189bd02016-01-26 12:20:39 +00005767 CGF.SizeTy, /*isSigned=*/false);
5768 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
5769 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005770 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005771 }
5772
5773 // 2. Emit reduce_func().
James Y Knight9871db02019-02-05 16:42:33 +00005774 llvm::Function *ReductionFn = emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005775 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
5776 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005777
5778 // 3. Create static kmp_critical_name lock = { 0 };
Alexey Bataev18fa2322018-05-02 14:20:50 +00005779 std::string Name = getName({"reduction"});
5780 llvm::Value *Lock = getCriticalRegionLock(Name);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005781
5782 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5783 // RedList, reduce_func, &<lock>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005784 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
5785 llvm::Value *ThreadId = getThreadID(CGF, Loc);
5786 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
5787 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Samuel Antao4c8035b2016-12-12 18:00:20 +00005788 ReductionList.getPointer(), CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005789 llvm::Value *Args[] = {
5790 IdentTLoc, // ident_t *<loc>
5791 ThreadId, // i32 <gtid>
5792 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
5793 ReductionArrayTySize, // size_type sizeof(RedList)
5794 RL, // void *RedList
5795 ReductionFn, // void (*) (void *, void *) <reduce_func>
5796 Lock // kmp_critical_name *&<lock>
5797 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005798 llvm::Value *Res = CGF.EmitRuntimeCall(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005799 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
5800 : OMPRTL__kmpc_reduce),
5801 Args);
5802
5803 // 5. Build switch(res)
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005804 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
5805 llvm::SwitchInst *SwInst =
5806 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005807
5808 // 6. Build case 1:
5809 // ...
5810 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5811 // ...
5812 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5813 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005814 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005815 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
5816 CGF.EmitBlock(Case1BB);
5817
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005818 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5819 llvm::Value *EndArgs[] = {
5820 IdentTLoc, // ident_t *<loc>
5821 ThreadId, // i32 <gtid>
5822 Lock // kmp_critical_name *&<lock>
5823 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005824 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5825 CodeGenFunction &CGF, PrePostActionTy &Action) {
5826 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005827 auto IPriv = Privates.begin();
5828 auto ILHS = LHSExprs.begin();
5829 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005830 for (const Expr *E : ReductionOps) {
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005831 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5832 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005833 ++IPriv;
5834 ++ILHS;
5835 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005836 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005837 };
5838 RegionCodeGenTy RCG(CodeGen);
5839 CommonActionTy Action(
5840 nullptr, llvm::None,
5841 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
5842 : OMPRTL__kmpc_end_reduce),
5843 EndArgs);
5844 RCG.setAction(Action);
5845 RCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005846
5847 CGF.EmitBranch(DefaultBB);
5848
5849 // 7. Build case 2:
5850 // ...
5851 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5852 // ...
5853 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005854 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005855 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
5856 CGF.EmitBlock(Case2BB);
5857
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005858 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
5859 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005860 auto ILHS = LHSExprs.begin();
5861 auto IRHS = RHSExprs.begin();
5862 auto IPriv = Privates.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005863 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005864 const Expr *XExpr = nullptr;
5865 const Expr *EExpr = nullptr;
5866 const Expr *UpExpr = nullptr;
5867 BinaryOperatorKind BO = BO_Comma;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005868 if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005869 if (BO->getOpcode() == BO_Assign) {
5870 XExpr = BO->getLHS();
5871 UpExpr = BO->getRHS();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005872 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005873 }
5874 // Try to emit update expression as a simple atomic.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005875 const Expr *RHSExpr = UpExpr;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005876 if (RHSExpr) {
5877 // Analyze RHS part of the whole expression.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005878 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005879 RHSExpr->IgnoreParenImpCasts())) {
5880 // If this is a conditional operator, analyze its condition for
5881 // min/max reduction operator.
5882 RHSExpr = ACO->getCond();
Alexey Bataev69a47792015-05-07 03:54:03 +00005883 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005884 if (const auto *BORHS =
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005885 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
5886 EExpr = BORHS->getRHS();
5887 BO = BORHS->getOpcode();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005888 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005889 }
5890 if (XExpr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005891 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005892 auto &&AtomicRedGen = [BO, VD,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005893 Loc](CodeGenFunction &CGF, const Expr *XExpr,
5894 const Expr *EExpr, const Expr *UpExpr) {
5895 LValue X = CGF.EmitLValue(XExpr);
5896 RValue E;
5897 if (EExpr)
5898 E = CGF.EmitAnyExpr(EExpr);
5899 CGF.EmitOMPAtomicSimpleUpdateExpr(
JF Bastien92f4ef12016-04-06 17:26:42 +00005900 X, E, BO, /*IsXLHSInRHSPart=*/true,
5901 llvm::AtomicOrdering::Monotonic, Loc,
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005902 [&CGF, UpExpr, VD, Loc](RValue XRValue) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005903 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5904 PrivateScope.addPrivate(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005905 VD, [&CGF, VD, XRValue, Loc]() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005906 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5907 CGF.emitOMPSimpleStore(
5908 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
5909 VD->getType().getNonReferenceType(), Loc);
5910 return LHSTemp;
5911 });
5912 (void)PrivateScope.Privatize();
5913 return CGF.EmitAnyExpr(UpExpr);
5914 });
5915 };
5916 if ((*IPriv)->getType()->isArrayType()) {
5917 // Emit atomic reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005918 const auto *RHSVar =
5919 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005920 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
5921 AtomicRedGen, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005922 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005923 // Emit atomic reduction for array subscript or single variable.
5924 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005925 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005926 } else {
5927 // Emit as a critical region.
5928 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
Alexey Bataev18fa2322018-05-02 14:20:50 +00005929 const Expr *, const Expr *) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005930 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev18fa2322018-05-02 14:20:50 +00005931 std::string Name = RT.getName({"atomic_reduction"});
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005932 RT.emitCriticalRegion(
Alexey Bataev18fa2322018-05-02 14:20:50 +00005933 CGF, Name,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005934 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
5935 Action.Enter(CGF);
5936 emitReductionCombiner(CGF, E);
5937 },
5938 Loc);
5939 };
5940 if ((*IPriv)->getType()->isArrayType()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005941 const auto *LHSVar =
5942 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5943 const auto *RHSVar =
5944 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005945 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5946 CritRedGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005947 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005948 CritRedGen(CGF, nullptr, nullptr, nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005949 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005950 }
Richard Trieucc3949d2016-02-18 22:34:54 +00005951 ++ILHS;
5952 ++IRHS;
5953 ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005954 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005955 };
5956 RegionCodeGenTy AtomicRCG(AtomicCodeGen);
5957 if (!WithNowait) {
5958 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
5959 llvm::Value *EndArgs[] = {
5960 IdentTLoc, // ident_t *<loc>
5961 ThreadId, // i32 <gtid>
5962 Lock // kmp_critical_name *&<lock>
5963 };
5964 CommonActionTy Action(nullptr, llvm::None,
5965 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
5966 EndArgs);
5967 AtomicRCG.setAction(Action);
5968 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005969 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005970 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005971 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005972
5973 CGF.EmitBranch(DefaultBB);
5974 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
5975}
5976
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005977/// Generates unique name for artificial threadprivate variables.
Alexey Bataev1c44e152018-03-06 18:59:43 +00005978/// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>"
5979static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix,
5980 const Expr *Ref) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005981 SmallString<256> Buffer;
5982 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev1c44e152018-03-06 18:59:43 +00005983 const clang::DeclRefExpr *DE;
5984 const VarDecl *D = ::getBaseDecl(Ref, DE);
5985 if (!D)
5986 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl());
5987 D = D->getCanonicalDecl();
Alexey Bataev18fa2322018-05-02 14:20:50 +00005988 std::string Name = CGM.getOpenMPRuntime().getName(
5989 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)});
5990 Out << Prefix << Name << "_"
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005991 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005992 return Out.str();
5993}
5994
5995/// Emits reduction initializer function:
5996/// \code
5997/// void @.red_init(void* %arg) {
5998/// %0 = bitcast void* %arg to <type>*
5999/// store <type> <init>, <type>* %0
6000/// ret void
6001/// }
6002/// \endcode
6003static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM,
6004 SourceLocation Loc,
6005 ReductionCodeGen &RCG, unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006006 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006007 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006008 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6009 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006010 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006011 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006012 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006013 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006014 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006015 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006016 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006017 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006018 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006019 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006020 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006021 Address PrivateAddr = CGF.EmitLoadOfPointer(
6022 CGF.GetAddrOfLocalVar(&Param),
6023 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6024 llvm::Value *Size = nullptr;
6025 // If the size of the reduction item is non-constant, load it from global
6026 // threadprivate variable.
6027 if (RCG.getSizes(N).second) {
6028 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6029 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006030 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006031 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6032 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006033 }
6034 RCG.emitAggregateType(CGF, N, Size);
6035 LValue SharedLVal;
6036 // If initializer uses initializer from declare reduction construct, emit a
6037 // pointer to the address of the original reduction item (reuired by reduction
6038 // initializer)
6039 if (RCG.usesReductionInitializer(N)) {
6040 Address SharedAddr =
6041 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6042 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006043 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataev21dab122018-03-09 15:20:30 +00006044 SharedAddr = CGF.EmitLoadOfPointer(
6045 SharedAddr,
6046 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006047 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy);
6048 } else {
6049 SharedLVal = CGF.MakeNaturalAlignAddrLValue(
6050 llvm::ConstantPointerNull::get(CGM.VoidPtrTy),
6051 CGM.getContext().VoidPtrTy);
6052 }
6053 // Emit the initializer:
6054 // %0 = bitcast void* %arg to <type>*
6055 // store <type> <init>, <type>* %0
6056 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal,
6057 [](CodeGenFunction &) { return false; });
6058 CGF.FinishFunction();
6059 return Fn;
6060}
6061
6062/// Emits reduction combiner function:
6063/// \code
6064/// void @.red_comb(void* %arg0, void* %arg1) {
6065/// %lhs = bitcast void* %arg0 to <type>*
6066/// %rhs = bitcast void* %arg1 to <type>*
6067/// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs)
6068/// store <type> %2, <type>* %lhs
6069/// ret void
6070/// }
6071/// \endcode
6072static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM,
6073 SourceLocation Loc,
6074 ReductionCodeGen &RCG, unsigned N,
6075 const Expr *ReductionOp,
6076 const Expr *LHS, const Expr *RHS,
6077 const Expr *PrivateRef) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006078 ASTContext &C = CGM.getContext();
6079 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl());
6080 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006081 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006082 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
6083 C.VoidPtrTy, ImplicitParamDecl::Other);
6084 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6085 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006086 Args.emplace_back(&ParamInOut);
6087 Args.emplace_back(&ParamIn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006088 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006089 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006090 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006091 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006092 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006093 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006094 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006095 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006096 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006097 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006098 llvm::Value *Size = nullptr;
6099 // If the size of the reduction item is non-constant, load it from global
6100 // threadprivate variable.
6101 if (RCG.getSizes(N).second) {
6102 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6103 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006104 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006105 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6106 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006107 }
6108 RCG.emitAggregateType(CGF, N, Size);
6109 // Remap lhs and rhs variables to the addresses of the function arguments.
6110 // %lhs = bitcast void* %arg0 to <type>*
6111 // %rhs = bitcast void* %arg1 to <type>*
6112 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006113 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006114 // Pull out the pointer to the variable.
6115 Address PtrAddr = CGF.EmitLoadOfPointer(
6116 CGF.GetAddrOfLocalVar(&ParamInOut),
6117 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6118 return CGF.Builder.CreateElementBitCast(
6119 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType()));
6120 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006121 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006122 // Pull out the pointer to the variable.
6123 Address PtrAddr = CGF.EmitLoadOfPointer(
6124 CGF.GetAddrOfLocalVar(&ParamIn),
6125 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6126 return CGF.Builder.CreateElementBitCast(
6127 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType()));
6128 });
6129 PrivateScope.Privatize();
6130 // Emit the combiner body:
6131 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs)
6132 // store <type> %2, <type>* %lhs
6133 CGM.getOpenMPRuntime().emitSingleReductionCombiner(
6134 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS),
6135 cast<DeclRefExpr>(RHS));
6136 CGF.FinishFunction();
6137 return Fn;
6138}
6139
6140/// Emits reduction finalizer function:
6141/// \code
6142/// void @.red_fini(void* %arg) {
6143/// %0 = bitcast void* %arg to <type>*
6144/// <destroy>(<type>* %0)
6145/// ret void
6146/// }
6147/// \endcode
6148static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM,
6149 SourceLocation Loc,
6150 ReductionCodeGen &RCG, unsigned N) {
6151 if (!RCG.needCleanups(N))
6152 return nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006153 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006154 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006155 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6156 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006157 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006158 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006159 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006160 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006161 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006162 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006163 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006164 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006165 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006166 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006167 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006168 Address PrivateAddr = CGF.EmitLoadOfPointer(
6169 CGF.GetAddrOfLocalVar(&Param),
6170 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6171 llvm::Value *Size = nullptr;
6172 // If the size of the reduction item is non-constant, load it from global
6173 // threadprivate variable.
6174 if (RCG.getSizes(N).second) {
6175 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6176 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006177 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006178 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6179 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006180 }
6181 RCG.emitAggregateType(CGF, N, Size);
6182 // Emit the finalizer body:
6183 // <destroy>(<type>* %0)
6184 RCG.emitCleanups(CGF, N, PrivateAddr);
6185 CGF.FinishFunction();
6186 return Fn;
6187}
6188
6189llvm::Value *CGOpenMPRuntime::emitTaskReductionInit(
6190 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
6191 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
6192 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty())
6193 return nullptr;
6194
6195 // Build typedef struct:
6196 // kmp_task_red_input {
6197 // void *reduce_shar; // shared reduction item
6198 // size_t reduce_size; // size of data item
6199 // void *reduce_init; // data initialization routine
6200 // void *reduce_fini; // data finalization routine
6201 // void *reduce_comb; // data combiner routine
6202 // kmp_task_red_flags_t flags; // flags for additional info from compiler
6203 // } kmp_task_red_input_t;
6204 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006205 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t");
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006206 RD->startDefinition();
6207 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6208 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType());
6209 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6210 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6211 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6212 const FieldDecl *FlagsFD = addFieldToRecordDecl(
6213 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false));
6214 RD->completeDefinition();
6215 QualType RDType = C.getRecordType(RD);
6216 unsigned Size = Data.ReductionVars.size();
6217 llvm::APInt ArraySize(/*numBits=*/64, Size);
6218 QualType ArrayRDType = C.getConstantArrayType(
Richard Smith772e2662019-10-04 01:25:59 +00006219 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006220 // kmp_task_red_input_t .rd_input.[Size];
6221 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input.");
6222 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies,
6223 Data.ReductionOps);
6224 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) {
6225 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt];
6226 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0),
6227 llvm::ConstantInt::get(CGM.SizeTy, Cnt)};
6228 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP(
6229 TaskRedInput.getPointer(), Idxs,
6230 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc,
6231 ".rd_input.gep.");
6232 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType);
6233 // ElemLVal.reduce_shar = &Shareds[Cnt];
6234 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD);
6235 RCG.emitSharedLValue(CGF, Cnt);
6236 llvm::Value *CastedShared =
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08006237 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006238 CGF.EmitStoreOfScalar(CastedShared, SharedLVal);
6239 RCG.emitAggregateType(CGF, Cnt);
6240 llvm::Value *SizeValInChars;
6241 llvm::Value *SizeVal;
6242 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt);
6243 // We use delayed creation/initialization for VLAs, array sections and
6244 // custom reduction initializations. It is required because runtime does not
6245 // provide the way to pass the sizes of VLAs/array sections to
6246 // initializer/combiner/finalizer functions and does not pass the pointer to
6247 // original reduction item to the initializer. Instead threadprivate global
6248 // variables are used to store these values and use them in the functions.
6249 bool DelayedCreation = !!SizeVal;
6250 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy,
6251 /*isSigned=*/false);
6252 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD);
6253 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal);
6254 // ElemLVal.reduce_init = init;
6255 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD);
6256 llvm::Value *InitAddr =
6257 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt));
6258 CGF.EmitStoreOfScalar(InitAddr, InitLVal);
6259 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt);
6260 // ElemLVal.reduce_fini = fini;
6261 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD);
6262 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt);
6263 llvm::Value *FiniAddr = Fini
6264 ? CGF.EmitCastToVoidPtr(Fini)
6265 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy);
6266 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal);
6267 // ElemLVal.reduce_comb = comb;
6268 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD);
6269 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction(
6270 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt],
6271 RHSExprs[Cnt], Data.ReductionCopies[Cnt]));
6272 CGF.EmitStoreOfScalar(CombAddr, CombLVal);
6273 // ElemLVal.flags = 0;
6274 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD);
6275 if (DelayedCreation) {
6276 CGF.EmitStoreOfScalar(
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006277 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006278 FlagsLVal);
6279 } else
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08006280 CGF.EmitNullInitialization(FlagsLVal.getAddress(), FlagsLVal.getType());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006281 }
6282 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void
6283 // *data);
6284 llvm::Value *Args[] = {
6285 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6286 /*isSigned=*/true),
6287 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true),
6288 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(),
6289 CGM.VoidPtrTy)};
6290 return CGF.EmitRuntimeCall(
6291 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args);
6292}
6293
6294void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
6295 SourceLocation Loc,
6296 ReductionCodeGen &RCG,
6297 unsigned N) {
6298 auto Sizes = RCG.getSizes(N);
6299 // Emit threadprivate global variable if the type is non-constant
6300 // (Sizes.second = nullptr).
6301 if (Sizes.second) {
6302 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy,
6303 /*isSigned=*/false);
6304 Address SizeAddr = getAddrOfArtificialThreadPrivate(
6305 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006306 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006307 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false);
6308 }
6309 // Store address of the original reduction item if custom initializer is used.
6310 if (RCG.usesReductionInitializer(N)) {
6311 Address SharedAddr = getAddrOfArtificialThreadPrivate(
6312 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006313 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006314 CGF.Builder.CreateStore(
6315 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08006316 RCG.getSharedLValue(N).getPointer(), CGM.VoidPtrTy),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006317 SharedAddr, /*IsVolatile=*/false);
6318 }
6319}
6320
6321Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF,
6322 SourceLocation Loc,
6323 llvm::Value *ReductionsPtr,
6324 LValue SharedLVal) {
6325 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
6326 // *d);
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08006327 llvm::Value *Args[] = {
6328 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6329 /*isSigned=*/true),
6330 ReductionsPtr,
6331 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(SharedLVal.getPointer(),
6332 CGM.VoidPtrTy)};
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006333 return Address(
6334 CGF.EmitRuntimeCall(
6335 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args),
6336 SharedLVal.getAlignment());
6337}
6338
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006339void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
6340 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006341 if (!CGF.HaveInsertPoint())
6342 return;
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006343 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
6344 // global_tid);
6345 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
6346 // Ignore return result until untied tasks are supported.
6347 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00006348 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
6349 Region->emitUntiedSwitch(CGF);
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006350}
6351
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006352void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006353 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00006354 const RegionCodeGenTy &CodeGen,
6355 bool HasCancel) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006356 if (!CGF.HaveInsertPoint())
6357 return;
Alexey Bataev25e5b442015-09-15 12:52:43 +00006358 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006359 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00006360}
6361
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006362namespace {
6363enum RTCancelKind {
6364 CancelNoreq = 0,
6365 CancelParallel = 1,
6366 CancelLoop = 2,
6367 CancelSections = 3,
6368 CancelTaskgroup = 4
6369};
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00006370} // anonymous namespace
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006371
6372static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
6373 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00006374 if (CancelRegion == OMPD_parallel)
6375 CancelKind = CancelParallel;
6376 else if (CancelRegion == OMPD_for)
6377 CancelKind = CancelLoop;
6378 else if (CancelRegion == OMPD_sections)
6379 CancelKind = CancelSections;
6380 else {
6381 assert(CancelRegion == OMPD_taskgroup);
6382 CancelKind = CancelTaskgroup;
6383 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006384 return CancelKind;
6385}
6386
6387void CGOpenMPRuntime::emitCancellationPointCall(
6388 CodeGenFunction &CGF, SourceLocation Loc,
6389 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006390 if (!CGF.HaveInsertPoint())
6391 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006392 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
6393 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006394 if (auto *OMPRegionInfo =
6395 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Jonas Hahnfeldb07931f2017-02-17 18:32:58 +00006396 // For 'cancellation point taskgroup', the task region info may not have a
6397 // cancel. This may instead happen in another adjacent task.
6398 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006399 llvm::Value *Args[] = {
6400 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
6401 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006402 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006403 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006404 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
6405 // if (__kmpc_cancellationpoint()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006406 // exit from construct;
6407 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006408 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6409 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6410 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006411 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6412 CGF.EmitBlock(ExitBB);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006413 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006414 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev25e5b442015-09-15 12:52:43 +00006415 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006416 CGF.EmitBranchThroughCleanup(CancelDest);
6417 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6418 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006419 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006420}
6421
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006422void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00006423 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006424 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006425 if (!CGF.HaveInsertPoint())
6426 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006427 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
6428 // kmp_int32 cncl_kind);
6429 if (auto *OMPRegionInfo =
6430 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006431 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF,
6432 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006433 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev87933c72015-09-18 08:07:34 +00006434 llvm::Value *Args[] = {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006435 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
Alexey Bataev87933c72015-09-18 08:07:34 +00006436 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
6437 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006438 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006439 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
Alexey Bataev87933c72015-09-18 08:07:34 +00006440 // if (__kmpc_cancel()) {
Alexey Bataev87933c72015-09-18 08:07:34 +00006441 // exit from construct;
6442 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006443 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6444 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6445 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev87933c72015-09-18 08:07:34 +00006446 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6447 CGF.EmitBlock(ExitBB);
Alexey Bataev87933c72015-09-18 08:07:34 +00006448 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006449 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev87933c72015-09-18 08:07:34 +00006450 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6451 CGF.EmitBranchThroughCleanup(CancelDest);
6452 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6453 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006454 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -05006455 emitIfClause(CGF, IfCond, ThenGen,
6456 [](CodeGenFunction &, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006457 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006458 RegionCodeGenTy ThenRCG(ThenGen);
6459 ThenRCG(CGF);
6460 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006461 }
6462}
Samuel Antaobed3c462015-10-02 16:14:20 +00006463
Samuel Antaoee8fb302016-01-06 13:42:12 +00006464void CGOpenMPRuntime::emitTargetOutlinedFunction(
6465 const OMPExecutableDirective &D, StringRef ParentName,
6466 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006467 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00006468 assert(!ParentName.empty() && "Invalid target region parent name!");
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00006469 HasEmittedTargetRegion = true;
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006470 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
6471 IsOffloadEntry, CodeGen);
6472}
6473
6474void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
6475 const OMPExecutableDirective &D, StringRef ParentName,
6476 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6477 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antao2de62b02016-02-13 23:35:10 +00006478 // Create a unique name for the entry function using the source location
6479 // information of the current target region. The name will be something like:
Samuel Antaoee8fb302016-01-06 13:42:12 +00006480 //
Samuel Antao2de62b02016-02-13 23:35:10 +00006481 // __omp_offloading_DD_FFFF_PP_lBB
Samuel Antaoee8fb302016-01-06 13:42:12 +00006482 //
6483 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
Samuel Antao2de62b02016-02-13 23:35:10 +00006484 // mangled name of the function that encloses the target region and BB is the
6485 // line number of the target region.
Samuel Antaoee8fb302016-01-06 13:42:12 +00006486
6487 unsigned DeviceID;
6488 unsigned FileID;
6489 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00006490 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00006491 Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006492 SmallString<64> EntryFnName;
6493 {
6494 llvm::raw_svector_ostream OS(EntryFnName);
Samuel Antao2de62b02016-02-13 23:35:10 +00006495 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
6496 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00006497 }
6498
Alexey Bataev475a7442018-01-12 19:39:11 +00006499 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006500
Samuel Antaobed3c462015-10-02 16:14:20 +00006501 CodeGenFunction CGF(CGM, true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006502 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
Samuel Antaobed3c462015-10-02 16:14:20 +00006503 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006504
Samuel Antao6d004262016-06-16 18:39:34 +00006505 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006506
6507 // If this target outline function is not an offload entry, we don't need to
6508 // register it.
6509 if (!IsOffloadEntry)
6510 return;
6511
6512 // The target region ID is used by the runtime library to identify the current
6513 // target region, so it only has to be unique and not necessarily point to
6514 // anything. It could be the pointer to the outlined function that implements
6515 // the target region, but we aren't using that so that the compiler doesn't
6516 // need to keep that, and could therefore inline the host function if proven
6517 // worthwhile during optimization. In the other hand, if emitting code for the
6518 // device, the ID has to be the function address so that it can retrieved from
6519 // the offloading entry and launched by the runtime library. We also mark the
6520 // outlined function to have external linkage in case we are emitting code for
6521 // the device, because these functions will be entry points to the device.
6522
6523 if (CGM.getLangOpts().OpenMPIsDevice) {
6524 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
Alexey Bataev9a700172018-05-08 14:16:57 +00006525 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Rafael Espindolacbca4872018-01-11 22:15:12 +00006526 OutlinedFn->setDSOLocal(false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006527 } else {
Alexey Bataevc15ea702018-05-09 18:02:37 +00006528 std::string Name = getName({EntryFnName, "region_id"});
Samuel Antaoee8fb302016-01-06 13:42:12 +00006529 OutlinedFnID = new llvm::GlobalVariable(
6530 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
Alexey Bataev9a700172018-05-08 14:16:57 +00006531 llvm::GlobalValue::WeakAnyLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006532 llvm::Constant::getNullValue(CGM.Int8Ty), Name);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006533 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00006534
6535 // Register the information for the entry associated with this target region.
6536 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
Samuel Antaof83efdb2017-01-05 16:02:49 +00006537 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID,
Alexey Bataev03f270c2018-03-30 18:31:07 +00006538 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion);
Samuel Antaobed3c462015-10-02 16:14:20 +00006539}
6540
Alexey Bataev5c427362019-04-10 19:11:33 +00006541/// Checks if the expression is constant or does not have non-trivial function
6542/// calls.
6543static bool isTrivial(ASTContext &Ctx, const Expr * E) {
6544 // We can skip constant expressions.
6545 // We can skip expressions with trivial calls or simple expressions.
6546 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) ||
6547 !E->hasNonTrivialCall(Ctx)) &&
6548 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true);
6549}
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006550
Alexey Bataev5c427362019-04-10 19:11:33 +00006551const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx,
6552 const Stmt *Body) {
6553 const Stmt *Child = Body->IgnoreContainers();
6554 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) {
6555 Child = nullptr;
6556 for (const Stmt *S : C->body()) {
6557 if (const auto *E = dyn_cast<Expr>(S)) {
6558 if (isTrivial(Ctx, E))
6559 continue;
6560 }
6561 // Some of the statements can be ignored.
6562 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) ||
6563 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S))
6564 continue;
6565 // Analyze declarations.
6566 if (const auto *DS = dyn_cast<DeclStmt>(S)) {
6567 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) {
6568 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6569 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6570 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6571 isa<UsingDirectiveDecl>(D) ||
6572 isa<OMPDeclareReductionDecl>(D) ||
6573 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6574 return true;
6575 const auto *VD = dyn_cast<VarDecl>(D);
6576 if (!VD)
6577 return false;
6578 return VD->isConstexpr() ||
6579 ((VD->getType().isTrivialType(Ctx) ||
6580 VD->getType()->isReferenceType()) &&
6581 (!VD->hasInit() || isTrivial(Ctx, VD->getInit())));
6582 }))
6583 continue;
6584 }
6585 // Found multiple children - cannot get the one child only.
6586 if (Child)
6587 return nullptr;
6588 Child = S;
6589 }
6590 if (Child)
6591 Child = Child->IgnoreContainers();
6592 }
6593 return Child;
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006594}
6595
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006596/// Emit the number of teams for a target directive. Inspect the num_teams
6597/// clause associated with a teams construct combined or closely nested
6598/// with the target directive.
6599///
6600/// Emit a team of size one for directives such as 'target parallel' that
6601/// have no associated teams construct.
6602///
6603/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006604static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006605emitNumTeamsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006606 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006607 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6608 "Clauses associated with the teams directive expected to be emitted "
6609 "only for the host!");
6610 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6611 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6612 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006613 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006614 switch (DirectiveKind) {
6615 case OMPD_target: {
6616 const auto *CS = D.getInnermostCapturedStmt();
6617 const auto *Body =
6618 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
6619 const Stmt *ChildStmt =
6620 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body);
6621 if (const auto *NestedDir =
6622 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6623 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) {
6624 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) {
6625 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6626 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6627 const Expr *NumTeams =
6628 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6629 llvm::Value *NumTeamsVal =
6630 CGF.EmitScalarExpr(NumTeams,
6631 /*IgnoreResultAssign*/ true);
6632 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006633 /*isSigned=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00006634 }
6635 return Bld.getInt32(0);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006636 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006637 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) ||
6638 isOpenMPSimdDirective(NestedDir->getDirectiveKind()))
6639 return Bld.getInt32(1);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006640 return Bld.getInt32(0);
6641 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006642 return nullptr;
Samuel Antaob68e2db2016-03-03 16:20:23 +00006643 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006644 case OMPD_target_teams:
6645 case OMPD_target_teams_distribute:
6646 case OMPD_target_teams_distribute_simd:
6647 case OMPD_target_teams_distribute_parallel_for:
6648 case OMPD_target_teams_distribute_parallel_for_simd: {
6649 if (D.hasClausesOfKind<OMPNumTeamsClause>()) {
6650 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF);
6651 const Expr *NumTeams =
6652 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6653 llvm::Value *NumTeamsVal =
6654 CGF.EmitScalarExpr(NumTeams,
6655 /*IgnoreResultAssign*/ true);
6656 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006657 /*isSigned=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00006658 }
6659 return Bld.getInt32(0);
6660 }
6661 case OMPD_target_parallel:
6662 case OMPD_target_parallel_for:
6663 case OMPD_target_parallel_for_simd:
6664 case OMPD_target_simd:
6665 return Bld.getInt32(1);
6666 case OMPD_parallel:
6667 case OMPD_for:
6668 case OMPD_parallel_for:
6669 case OMPD_parallel_sections:
6670 case OMPD_for_simd:
6671 case OMPD_parallel_for_simd:
6672 case OMPD_cancel:
6673 case OMPD_cancellation_point:
6674 case OMPD_ordered:
6675 case OMPD_threadprivate:
6676 case OMPD_allocate:
6677 case OMPD_task:
6678 case OMPD_simd:
6679 case OMPD_sections:
6680 case OMPD_section:
6681 case OMPD_single:
6682 case OMPD_master:
6683 case OMPD_critical:
6684 case OMPD_taskyield:
6685 case OMPD_barrier:
6686 case OMPD_taskwait:
6687 case OMPD_taskgroup:
6688 case OMPD_atomic:
6689 case OMPD_flush:
6690 case OMPD_teams:
6691 case OMPD_target_data:
6692 case OMPD_target_exit_data:
6693 case OMPD_target_enter_data:
6694 case OMPD_distribute:
6695 case OMPD_distribute_simd:
6696 case OMPD_distribute_parallel_for:
6697 case OMPD_distribute_parallel_for_simd:
6698 case OMPD_teams_distribute:
6699 case OMPD_teams_distribute_simd:
6700 case OMPD_teams_distribute_parallel_for:
6701 case OMPD_teams_distribute_parallel_for_simd:
6702 case OMPD_target_update:
6703 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00006704 case OMPD_declare_variant:
Alexey Bataev5c427362019-04-10 19:11:33 +00006705 case OMPD_declare_target:
6706 case OMPD_end_declare_target:
6707 case OMPD_declare_reduction:
6708 case OMPD_declare_mapper:
6709 case OMPD_taskloop:
6710 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00006711 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00006712 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00006713 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04006714 case OMPD_parallel_master_taskloop_simd:
Alexey Bataev5c427362019-04-10 19:11:33 +00006715 case OMPD_requires:
6716 case OMPD_unknown:
6717 break;
6718 }
6719 llvm_unreachable("Unexpected directive kind.");
6720}
Samuel Antaob68e2db2016-03-03 16:20:23 +00006721
Alexey Bataev5c427362019-04-10 19:11:33 +00006722static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS,
6723 llvm::Value *DefaultThreadLimitVal) {
6724 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6725 CGF.getContext(), CS->getCapturedStmt());
6726 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6727 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) {
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006728 llvm::Value *NumThreads = nullptr;
6729 llvm::Value *CondVal = nullptr;
6730 // Handle if clause. If if clause present, the number of threads is
6731 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6732 if (Dir->hasClausesOfKind<OMPIfClause>()) {
6733 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6734 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6735 const OMPIfClause *IfClause = nullptr;
6736 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) {
6737 if (C->getNameModifier() == OMPD_unknown ||
6738 C->getNameModifier() == OMPD_parallel) {
6739 IfClause = C;
6740 break;
6741 }
6742 }
6743 if (IfClause) {
6744 const Expr *Cond = IfClause->getCondition();
6745 bool Result;
6746 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6747 if (!Result)
6748 return CGF.Builder.getInt32(1);
6749 } else {
6750 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange());
6751 if (const auto *PreInit =
6752 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) {
6753 for (const auto *I : PreInit->decls()) {
6754 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6755 CGF.EmitVarDecl(cast<VarDecl>(*I));
6756 } else {
6757 CodeGenFunction::AutoVarEmission Emission =
6758 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6759 CGF.EmitAutoVarCleanups(Emission);
6760 }
6761 }
6762 }
6763 CondVal = CGF.EvaluateExprAsBool(Cond);
6764 }
6765 }
6766 }
6767 // Check the value of num_threads clause iff if clause was not specified
6768 // or is not evaluated to false.
Alexey Bataev5c427362019-04-10 19:11:33 +00006769 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) {
6770 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6771 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6772 const auto *NumThreadsClause =
6773 Dir->getSingleClause<OMPNumThreadsClause>();
6774 CodeGenFunction::LexicalScope Scope(
6775 CGF, NumThreadsClause->getNumThreads()->getSourceRange());
6776 if (const auto *PreInit =
6777 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6778 for (const auto *I : PreInit->decls()) {
6779 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6780 CGF.EmitVarDecl(cast<VarDecl>(*I));
6781 } else {
6782 CodeGenFunction::AutoVarEmission Emission =
6783 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6784 CGF.EmitAutoVarCleanups(Emission);
6785 }
6786 }
6787 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006788 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads());
Alexey Bataev5c427362019-04-10 19:11:33 +00006789 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006790 /*isSigned=*/false);
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006791 if (DefaultThreadLimitVal)
6792 NumThreads = CGF.Builder.CreateSelect(
6793 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads),
6794 DefaultThreadLimitVal, NumThreads);
6795 } else {
6796 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal
6797 : CGF.Builder.getInt32(0);
Alexey Bataev5c427362019-04-10 19:11:33 +00006798 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006799 // Process condition of the if clause.
6800 if (CondVal) {
6801 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads,
6802 CGF.Builder.getInt32(1));
6803 }
6804 return NumThreads;
Alexey Bataev5c427362019-04-10 19:11:33 +00006805 }
6806 if (isOpenMPSimdDirective(Dir->getDirectiveKind()))
6807 return CGF.Builder.getInt32(1);
6808 return DefaultThreadLimitVal;
6809 }
6810 return DefaultThreadLimitVal ? DefaultThreadLimitVal
6811 : CGF.Builder.getInt32(0);
Samuel Antaob68e2db2016-03-03 16:20:23 +00006812}
6813
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006814/// Emit the number of threads for a target directive. Inspect the
6815/// thread_limit clause associated with a teams construct combined or closely
6816/// nested with the target directive.
6817///
6818/// Emit the num_threads clause for directives such as 'target parallel' that
6819/// have no associated teams construct.
6820///
6821/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006822static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006823emitNumThreadsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006824 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006825 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6826 "Clauses associated with the teams directive expected to be emitted "
6827 "only for the host!");
6828 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6829 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6830 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006831 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006832 llvm::Value *ThreadLimitVal = nullptr;
6833 llvm::Value *NumThreadsVal = nullptr;
6834 switch (DirectiveKind) {
6835 case OMPD_target: {
6836 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6837 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6838 return NumThreads;
6839 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6840 CGF.getContext(), CS->getCapturedStmt());
6841 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6842 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) {
6843 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6844 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6845 const auto *ThreadLimitClause =
6846 Dir->getSingleClause<OMPThreadLimitClause>();
6847 CodeGenFunction::LexicalScope Scope(
6848 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange());
6849 if (const auto *PreInit =
6850 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6851 for (const auto *I : PreInit->decls()) {
6852 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6853 CGF.EmitVarDecl(cast<VarDecl>(*I));
6854 } else {
6855 CodeGenFunction::AutoVarEmission Emission =
6856 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6857 CGF.EmitAutoVarCleanups(Emission);
6858 }
6859 }
6860 }
6861 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6862 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6863 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006864 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006865 }
6866 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) &&
6867 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) {
6868 CS = Dir->getInnermostCapturedStmt();
6869 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6870 CGF.getContext(), CS->getCapturedStmt());
6871 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6872 }
6873 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) &&
6874 !isOpenMPSimdDirective(Dir->getDirectiveKind())) {
6875 CS = Dir->getInnermostCapturedStmt();
6876 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6877 return NumThreads;
6878 }
6879 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind()))
6880 return Bld.getInt32(1);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006881 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006882 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6883 }
6884 case OMPD_target_teams: {
6885 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6886 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6887 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6888 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6889 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6890 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006891 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006892 }
6893 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6894 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6895 return NumThreads;
6896 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6897 CGF.getContext(), CS->getCapturedStmt());
6898 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6899 if (Dir->getDirectiveKind() == OMPD_distribute) {
6900 CS = Dir->getInnermostCapturedStmt();
6901 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6902 return NumThreads;
6903 }
6904 }
6905 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6906 }
6907 case OMPD_target_teams_distribute:
6908 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6909 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6910 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6911 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6912 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6913 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006914 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006915 }
6916 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal);
6917 case OMPD_target_parallel:
6918 case OMPD_target_parallel_for:
6919 case OMPD_target_parallel_for_simd:
6920 case OMPD_target_teams_distribute_parallel_for:
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006921 case OMPD_target_teams_distribute_parallel_for_simd: {
6922 llvm::Value *CondVal = nullptr;
6923 // Handle if clause. If if clause present, the number of threads is
6924 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6925 if (D.hasClausesOfKind<OMPIfClause>()) {
6926 const OMPIfClause *IfClause = nullptr;
6927 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) {
6928 if (C->getNameModifier() == OMPD_unknown ||
6929 C->getNameModifier() == OMPD_parallel) {
6930 IfClause = C;
6931 break;
6932 }
6933 }
6934 if (IfClause) {
6935 const Expr *Cond = IfClause->getCondition();
6936 bool Result;
6937 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6938 if (!Result)
6939 return Bld.getInt32(1);
6940 } else {
6941 CodeGenFunction::RunCleanupsScope Scope(CGF);
6942 CondVal = CGF.EvaluateExprAsBool(Cond);
6943 }
6944 }
6945 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006946 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6947 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6948 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6949 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6950 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6951 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006952 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006953 }
6954 if (D.hasClausesOfKind<OMPNumThreadsClause>()) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006955 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
Alexey Bataev5c427362019-04-10 19:11:33 +00006956 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>();
6957 llvm::Value *NumThreads = CGF.EmitScalarExpr(
6958 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true);
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006959 NumThreadsVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006960 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006961 ThreadLimitVal = ThreadLimitVal
Alexey Bataev5c427362019-04-10 19:11:33 +00006962 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal,
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006963 ThreadLimitVal),
6964 NumThreadsVal, ThreadLimitVal)
6965 : NumThreadsVal;
Alexey Bataev50a1c782017-12-01 21:31:08 +00006966 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006967 if (!ThreadLimitVal)
6968 ThreadLimitVal = Bld.getInt32(0);
6969 if (CondVal)
6970 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1));
6971 return ThreadLimitVal;
6972 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006973 case OMPD_target_teams_distribute_simd:
6974 case OMPD_target_simd:
6975 return Bld.getInt32(1);
6976 case OMPD_parallel:
6977 case OMPD_for:
6978 case OMPD_parallel_for:
6979 case OMPD_parallel_sections:
6980 case OMPD_for_simd:
6981 case OMPD_parallel_for_simd:
6982 case OMPD_cancel:
6983 case OMPD_cancellation_point:
6984 case OMPD_ordered:
6985 case OMPD_threadprivate:
6986 case OMPD_allocate:
6987 case OMPD_task:
6988 case OMPD_simd:
6989 case OMPD_sections:
6990 case OMPD_section:
6991 case OMPD_single:
6992 case OMPD_master:
6993 case OMPD_critical:
6994 case OMPD_taskyield:
6995 case OMPD_barrier:
6996 case OMPD_taskwait:
6997 case OMPD_taskgroup:
6998 case OMPD_atomic:
6999 case OMPD_flush:
7000 case OMPD_teams:
7001 case OMPD_target_data:
7002 case OMPD_target_exit_data:
7003 case OMPD_target_enter_data:
7004 case OMPD_distribute:
7005 case OMPD_distribute_simd:
7006 case OMPD_distribute_parallel_for:
7007 case OMPD_distribute_parallel_for_simd:
7008 case OMPD_teams_distribute:
7009 case OMPD_teams_distribute_simd:
7010 case OMPD_teams_distribute_parallel_for:
7011 case OMPD_teams_distribute_parallel_for_simd:
7012 case OMPD_target_update:
7013 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00007014 case OMPD_declare_variant:
Alexey Bataev5c427362019-04-10 19:11:33 +00007015 case OMPD_declare_target:
7016 case OMPD_end_declare_target:
7017 case OMPD_declare_reduction:
7018 case OMPD_declare_mapper:
7019 case OMPD_taskloop:
7020 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00007021 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00007022 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00007023 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04007024 case OMPD_parallel_master_taskloop_simd:
Alexey Bataev5c427362019-04-10 19:11:33 +00007025 case OMPD_requires:
7026 case OMPD_unknown:
7027 break;
Samuel Antaob68e2db2016-03-03 16:20:23 +00007028 }
Alexey Bataev5c427362019-04-10 19:11:33 +00007029 llvm_unreachable("Unsupported directive kind.");
Samuel Antaob68e2db2016-03-03 16:20:23 +00007030}
7031
Samuel Antao86ace552016-04-27 22:40:57 +00007032namespace {
Alexey Bataevb3638132018-07-19 16:34:13 +00007033LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
7034
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007035// Utility to handle information from clauses associated with a given
Samuel Antao86ace552016-04-27 22:40:57 +00007036// construct that use mappable expressions (e.g. 'map' clause, 'to' clause).
7037// It provides a convenient interface to obtain the information and generate
7038// code for that information.
7039class MappableExprsHandler {
7040public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007041 /// Values for bit flags used to specify the mapping type for
Samuel Antao86ace552016-04-27 22:40:57 +00007042 /// offloading.
Alexey Bataevb3638132018-07-19 16:34:13 +00007043 enum OpenMPOffloadMappingFlags : uint64_t {
7044 /// No flags
7045 OMP_MAP_NONE = 0x0,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007046 /// Allocate memory on the device and move data from host to device.
Samuel Antao86ace552016-04-27 22:40:57 +00007047 OMP_MAP_TO = 0x01,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007048 /// Allocate memory on the device and move data from device to host.
Samuel Antao86ace552016-04-27 22:40:57 +00007049 OMP_MAP_FROM = 0x02,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007050 /// Always perform the requested mapping action on the element, even
Samuel Antao86ace552016-04-27 22:40:57 +00007051 /// if it was already mapped before.
7052 OMP_MAP_ALWAYS = 0x04,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007053 /// Delete the element from the device environment, ignoring the
Samuel Antao86ace552016-04-27 22:40:57 +00007054 /// current reference count associated with the element.
Samuel Antao6782e942016-05-26 16:48:10 +00007055 OMP_MAP_DELETE = 0x08,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007056 /// The element being mapped is a pointer-pointee pair; both the
George Rokos065755d2017-11-07 18:27:04 +00007057 /// pointer and the pointee should be mapped.
7058 OMP_MAP_PTR_AND_OBJ = 0x10,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007059 /// This flags signals that the base address of an entry should be
George Rokos065755d2017-11-07 18:27:04 +00007060 /// passed to the target kernel as an argument.
7061 OMP_MAP_TARGET_PARAM = 0x20,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007062 /// Signal that the runtime library has to return the device pointer
George Rokos065755d2017-11-07 18:27:04 +00007063 /// in the current position for the data being mapped. Used when we have the
7064 /// use_device_ptr clause.
7065 OMP_MAP_RETURN_PARAM = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007066 /// This flag signals that the reference being passed is a pointer to
Samuel Antaod486f842016-05-26 16:53:38 +00007067 /// private data.
George Rokos065755d2017-11-07 18:27:04 +00007068 OMP_MAP_PRIVATE = 0x80,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007069 /// Pass the element to the device by value.
George Rokos065755d2017-11-07 18:27:04 +00007070 OMP_MAP_LITERAL = 0x100,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007071 /// Implicit map
7072 OMP_MAP_IMPLICIT = 0x200,
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007073 /// Close is a hint to the runtime to allocate memory close to
7074 /// the target device.
7075 OMP_MAP_CLOSE = 0x400,
Alexey Bataevb3638132018-07-19 16:34:13 +00007076 /// The 16 MSBs of the flags indicate whether the entry is member of some
7077 /// struct/class.
7078 OMP_MAP_MEMBER_OF = 0xffff000000000000,
7079 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF),
Samuel Antao86ace552016-04-27 22:40:57 +00007080 };
7081
Michael Krused47b9432019-08-05 18:43:21 +00007082 /// Get the offset of the OMP_MAP_MEMBER_OF field.
7083 static unsigned getFlagMemberOffset() {
7084 unsigned Offset = 0;
7085 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1);
7086 Remain = Remain >> 1)
7087 Offset++;
7088 return Offset;
7089 }
7090
Samuel Antaocc10b852016-07-28 14:23:26 +00007091 /// Class that associates information with a base pointer to be passed to the
7092 /// runtime library.
7093 class BasePointerInfo {
7094 /// The base pointer.
7095 llvm::Value *Ptr = nullptr;
7096 /// The base declaration that refers to this device pointer, or null if
7097 /// there is none.
7098 const ValueDecl *DevPtrDecl = nullptr;
7099
7100 public:
7101 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr)
7102 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {}
7103 llvm::Value *operator*() const { return Ptr; }
7104 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; }
7105 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; }
7106 };
7107
Alexey Bataevb3638132018-07-19 16:34:13 +00007108 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>;
7109 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>;
7110 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>;
7111
7112 /// Map between a struct and the its lowest & highest elements which have been
7113 /// mapped.
7114 /// [ValueDecl *] --> {LE(FieldIndex, Pointer),
7115 /// HE(FieldIndex, Pointer)}
7116 struct StructRangeInfoTy {
7117 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = {
7118 0, Address::invalid()};
7119 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = {
7120 0, Address::invalid()};
7121 Address Base = Address::invalid();
7122 };
Samuel Antao86ace552016-04-27 22:40:57 +00007123
7124private:
Alexey Bataevb3638132018-07-19 16:34:13 +00007125 /// Kind that defines how a device pointer has to be returned.
7126 struct MapInfo {
7127 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
7128 OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
Kelvin Lief579432018-12-18 22:18:41 +00007129 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataevb3638132018-07-19 16:34:13 +00007130 bool ReturnDevicePointer = false;
7131 bool IsImplicit = false;
7132
7133 MapInfo() = default;
7134 MapInfo(
7135 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Kelvin Lief579432018-12-18 22:18:41 +00007136 OpenMPMapClauseKind MapType,
7137 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007138 bool ReturnDevicePointer, bool IsImplicit)
Kelvin Lief579432018-12-18 22:18:41 +00007139 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
Alexey Bataevb3638132018-07-19 16:34:13 +00007140 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {}
7141 };
7142
7143 /// If use_device_ptr is used on a pointer which is a struct member and there
7144 /// is no map information about it, then emission of that entry is deferred
7145 /// until the whole struct has been processed.
7146 struct DeferredDevicePtrEntryTy {
7147 const Expr *IE = nullptr;
7148 const ValueDecl *VD = nullptr;
7149
7150 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD)
7151 : IE(IE), VD(VD) {}
7152 };
7153
Michael Krused47b9432019-08-05 18:43:21 +00007154 /// The target directive from where the mappable clauses were extracted. It
7155 /// is either a executable directive or a user-defined mapper directive.
7156 llvm::PointerUnion<const OMPExecutableDirective *,
7157 const OMPDeclareMapperDecl *>
7158 CurDir;
Samuel Antao86ace552016-04-27 22:40:57 +00007159
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007160 /// Function the directive is being generated for.
Samuel Antao86ace552016-04-27 22:40:57 +00007161 CodeGenFunction &CGF;
7162
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007163 /// Set of all first private variables in the current directive.
Alexey Bataevf288cf92019-06-27 18:53:07 +00007164 /// bool data is set to true if the variable is implicitly marked as
7165 /// firstprivate, false otherwise.
7166 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls;
Samuel Antaod486f842016-05-26 16:53:38 +00007167
Samuel Antao6890b092016-07-28 14:25:09 +00007168 /// Map between device pointer declarations and their expression components.
7169 /// The key value for declarations in 'this' is null.
7170 llvm::DenseMap<
7171 const ValueDecl *,
7172 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7173 DevPointersMap;
7174
Samuel Antao86ace552016-04-27 22:40:57 +00007175 llvm::Value *getExprTypeSize(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007176 QualType ExprTy = E->getType().getCanonicalType();
Samuel Antao86ace552016-04-27 22:40:57 +00007177
7178 // Reference types are ignored for mapping purposes.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007179 if (const auto *RefTy = ExprTy->getAs<ReferenceType>())
Samuel Antao86ace552016-04-27 22:40:57 +00007180 ExprTy = RefTy->getPointeeType().getCanonicalType();
7181
7182 // Given that an array section is considered a built-in type, we need to
7183 // do the calculation based on the length of the section instead of relying
7184 // on CGF.getTypeSize(E->getType()).
7185 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) {
7186 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType(
7187 OAE->getBase()->IgnoreParenImpCasts())
7188 .getCanonicalType();
7189
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007190 // If there is no length associated with the expression and lower bound is
7191 // not specified too, that means we are using the whole length of the
7192 // base.
7193 if (!OAE->getLength() && OAE->getColonLoc().isValid() &&
7194 !OAE->getLowerBound())
Samuel Antao86ace552016-04-27 22:40:57 +00007195 return CGF.getTypeSize(BaseTy);
7196
7197 llvm::Value *ElemSize;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007198 if (const auto *PTy = BaseTy->getAs<PointerType>()) {
Samuel Antao86ace552016-04-27 22:40:57 +00007199 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007200 } else {
7201 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr());
Samuel Antao86ace552016-04-27 22:40:57 +00007202 assert(ATy && "Expecting array type if not a pointer type.");
7203 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType());
7204 }
7205
7206 // If we don't have a length at this point, that is because we have an
7207 // array section with a single element.
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007208 if (!OAE->getLength() && OAE->getColonLoc().isInvalid())
Samuel Antao86ace552016-04-27 22:40:57 +00007209 return ElemSize;
7210
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007211 if (const Expr *LenExpr = OAE->getLength()) {
Michael Liaod838cf72019-10-02 00:22:45 +00007212 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr);
7213 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(),
7214 CGF.getContext().getSizeType(),
7215 LenExpr->getExprLoc());
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007216 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize);
7217 }
7218 assert(!OAE->getLength() && OAE->getColonLoc().isValid() &&
7219 OAE->getLowerBound() && "expected array_section[lb:].");
7220 // Size = sizetype - lb * elemtype;
7221 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy);
7222 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound());
7223 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(),
7224 CGF.getContext().getSizeType(),
7225 OAE->getLowerBound()->getExprLoc());
7226 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize);
7227 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal);
7228 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal);
7229 LengthVal = CGF.Builder.CreateSelect(
7230 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0));
7231 return LengthVal;
Samuel Antao86ace552016-04-27 22:40:57 +00007232 }
7233 return CGF.getTypeSize(ExprTy);
7234 }
7235
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007236 /// Return the corresponding bits for a given map clause modifier. Add
Samuel Antao86ace552016-04-27 22:40:57 +00007237 /// a flag marking the map as a pointer if requested. Add a flag marking the
Samuel Antao6782e942016-05-26 16:48:10 +00007238 /// map as the first one of a series of maps that relate to the same map
7239 /// expression.
Kelvin Lief579432018-12-18 22:18:41 +00007240 OpenMPOffloadMappingFlags getMapTypeBits(
7241 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
7242 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const {
Alexey Bataevb3638132018-07-19 16:34:13 +00007243 OpenMPOffloadMappingFlags Bits =
7244 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE;
Samuel Antao86ace552016-04-27 22:40:57 +00007245 switch (MapType) {
7246 case OMPC_MAP_alloc:
Samuel Antao6782e942016-05-26 16:48:10 +00007247 case OMPC_MAP_release:
7248 // alloc and release is the default behavior in the runtime library, i.e.
7249 // if we don't pass any bits alloc/release that is what the runtime is
7250 // going to do. Therefore, we don't need to signal anything for these two
7251 // type modifiers.
Samuel Antao86ace552016-04-27 22:40:57 +00007252 break;
7253 case OMPC_MAP_to:
Alexey Bataevb3638132018-07-19 16:34:13 +00007254 Bits |= OMP_MAP_TO;
Samuel Antao86ace552016-04-27 22:40:57 +00007255 break;
7256 case OMPC_MAP_from:
Alexey Bataevb3638132018-07-19 16:34:13 +00007257 Bits |= OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007258 break;
7259 case OMPC_MAP_tofrom:
Alexey Bataevb3638132018-07-19 16:34:13 +00007260 Bits |= OMP_MAP_TO | OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007261 break;
7262 case OMPC_MAP_delete:
Alexey Bataevb3638132018-07-19 16:34:13 +00007263 Bits |= OMP_MAP_DELETE;
Samuel Antao86ace552016-04-27 22:40:57 +00007264 break;
Alexey Bataevb3638132018-07-19 16:34:13 +00007265 case OMPC_MAP_unknown:
Samuel Antao86ace552016-04-27 22:40:57 +00007266 llvm_unreachable("Unexpected map type!");
Samuel Antao86ace552016-04-27 22:40:57 +00007267 }
7268 if (AddPtrFlag)
George Rokos065755d2017-11-07 18:27:04 +00007269 Bits |= OMP_MAP_PTR_AND_OBJ;
7270 if (AddIsTargetParamFlag)
7271 Bits |= OMP_MAP_TARGET_PARAM;
Kelvin Lief579432018-12-18 22:18:41 +00007272 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always)
7273 != MapModifiers.end())
Samuel Antao86ace552016-04-27 22:40:57 +00007274 Bits |= OMP_MAP_ALWAYS;
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007275 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close)
7276 != MapModifiers.end())
7277 Bits |= OMP_MAP_CLOSE;
Samuel Antao86ace552016-04-27 22:40:57 +00007278 return Bits;
7279 }
7280
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007281 /// Return true if the provided expression is a final array section. A
Samuel Antao86ace552016-04-27 22:40:57 +00007282 /// final array section, is one whose length can't be proved to be one.
7283 bool isFinalArraySectionExpression(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007284 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
Samuel Antao86ace552016-04-27 22:40:57 +00007285
7286 // It is not an array section and therefore not a unity-size one.
7287 if (!OASE)
7288 return false;
7289
7290 // An array section with no colon always refer to a single element.
7291 if (OASE->getColonLoc().isInvalid())
7292 return false;
7293
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007294 const Expr *Length = OASE->getLength();
Samuel Antao86ace552016-04-27 22:40:57 +00007295
7296 // If we don't have a length we have to check if the array has size 1
7297 // for this dimension. Also, we should always expect a length if the
7298 // base type is pointer.
7299 if (!Length) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007300 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType(
7301 OASE->getBase()->IgnoreParenImpCasts())
7302 .getCanonicalType();
7303 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
Samuel Antao86ace552016-04-27 22:40:57 +00007304 return ATy->getSize().getSExtValue() != 1;
7305 // If we don't have a constant dimension length, we have to consider
7306 // the current section as having any size, so it is not necessarily
7307 // unitary. If it happen to be unity size, that's user fault.
7308 return true;
7309 }
7310
7311 // Check if the length evaluates to 1.
Fangrui Song407659a2018-11-30 23:41:18 +00007312 Expr::EvalResult Result;
7313 if (!Length->EvaluateAsInt(Result, CGF.getContext()))
Samuel Antao86ace552016-04-27 22:40:57 +00007314 return true; // Can have more that size 1.
7315
Fangrui Song407659a2018-11-30 23:41:18 +00007316 llvm::APSInt ConstLength = Result.Val.getInt();
Samuel Antao86ace552016-04-27 22:40:57 +00007317 return ConstLength.getSExtValue() != 1;
7318 }
7319
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007320 /// Generate the base pointers, section pointers, sizes and map type
Samuel Antao86ace552016-04-27 22:40:57 +00007321 /// bits for the provided map type, map modifier, and expression components.
7322 /// \a IsFirstComponent should be set to true if the provided set of
7323 /// components is the first associated with a capture.
7324 void generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00007325 OpenMPMapClauseKind MapType,
7326 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Samuel Antao86ace552016-04-27 22:40:57 +00007327 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Samuel Antaocc10b852016-07-28 14:23:26 +00007328 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007329 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
Alexey Bataevb3638132018-07-19 16:34:13 +00007330 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007331 bool IsImplicit,
7332 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7333 OverlappedElements = llvm::None) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007334 // The following summarizes what has to be generated for each map and the
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00007335 // types below. The generated information is expressed in this order:
Samuel Antao86ace552016-04-27 22:40:57 +00007336 // base pointer, section pointer, size, flags
7337 // (to add to the ones that come from the map type and modifier).
7338 //
7339 // double d;
7340 // int i[100];
7341 // float *p;
7342 //
7343 // struct S1 {
7344 // int i;
7345 // float f[50];
7346 // }
7347 // struct S2 {
7348 // int i;
7349 // float f[50];
7350 // S1 s;
7351 // double *p;
7352 // struct S2 *ps;
7353 // }
7354 // S2 s;
7355 // S2 *ps;
7356 //
7357 // map(d)
Alexey Bataevb3638132018-07-19 16:34:13 +00007358 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007359 //
7360 // map(i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007361 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007362 //
7363 // map(i[1:23])
Alexey Bataevb3638132018-07-19 16:34:13 +00007364 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007365 //
7366 // map(p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007367 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007368 //
7369 // map(p[1:24])
Alexey Bataevb3638132018-07-19 16:34:13 +00007370 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007371 //
7372 // map(s)
Alexey Bataevb3638132018-07-19 16:34:13 +00007373 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007374 //
7375 // map(s.i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007376 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007377 //
7378 // map(s.s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007379 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007380 //
7381 // map(s.p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007382 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007383 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007384 // map(to: s.p[:22])
7385 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*)
7386 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**)
7387 // &(s.p), &(s.p[0]), 22*sizeof(double),
7388 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***)
7389 // (*) alloc space for struct members, only this is a target parameter
7390 // (**) map the pointer (nothing to be mapped in this example) (the compiler
7391 // optimizes this entry out, same in the examples below)
7392 // (***) map the pointee (map: to)
Samuel Antao86ace552016-04-27 22:40:57 +00007393 //
7394 // map(s.ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007395 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007396 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007397 // map(from: s.ps->s.i)
7398 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7399 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7400 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007401 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007402 // map(to: s.ps->ps)
7403 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7404 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7405 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007406 //
7407 // map(s.ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007408 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7409 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7410 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7411 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007412 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007413 // map(to: s.ps->ps->s.f[:22])
7414 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7415 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7416 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7417 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007418 //
7419 // map(ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007420 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007421 //
7422 // map(ps->i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007423 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007424 //
7425 // map(ps->s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007426 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007427 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007428 // map(from: ps->p)
7429 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007430 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007431 // map(to: ps->p[:22])
7432 // ps, &(ps->p), sizeof(double*), TARGET_PARAM
7433 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1)
7434 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007435 //
7436 // map(ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007437 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007438 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007439 // map(from: ps->ps->s.i)
7440 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7441 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7442 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007443 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007444 // map(from: ps->ps->ps)
7445 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7446 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7447 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007448 //
7449 // map(ps->ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007450 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7451 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7452 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7453 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007454 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007455 // map(to: ps->ps->ps->s.f[:22])
7456 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7457 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7458 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7459 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
7460 //
7461 // map(to: s.f[:22]) map(from: s.p[:33])
7462 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) +
7463 // sizeof(double*) (**), TARGET_PARAM
7464 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO
7465 // &s, &(s.p), sizeof(double*), MEMBER_OF(1)
7466 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7467 // (*) allocate contiguous space needed to fit all mapped members even if
7468 // we allocate space for members not mapped (in this example,
7469 // s.f[22..49] and s.s are not mapped, yet we must allocate space for
7470 // them as well because they fall between &s.f[0] and &s.p)
7471 //
7472 // map(from: s.f[:22]) map(to: ps->p[:33])
7473 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM
7474 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7475 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*)
7476 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO
7477 // (*) the struct this entry pertains to is the 2nd element in the list of
7478 // arguments, hence MEMBER_OF(2)
7479 //
7480 // map(from: s.f[:22], s.s) map(to: ps->p[:33])
7481 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM
7482 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM
7483 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM
7484 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7485 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*)
7486 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO
7487 // (*) the struct this entry pertains to is the 4th element in the list
7488 // of arguments, hence MEMBER_OF(4)
Samuel Antao86ace552016-04-27 22:40:57 +00007489
7490 // Track if the map information being generated is the first for a capture.
7491 bool IsCaptureFirstInfo = IsFirstComponentList;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007492 // When the variable is on a declare target link or in a to clause with
7493 // unified memory, a reference is needed to hold the host/device address
7494 // of the variable.
7495 bool RequiresReference = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007496
7497 // Scan the components from the base to the complete expression.
7498 auto CI = Components.rbegin();
7499 auto CE = Components.rend();
7500 auto I = CI;
7501
7502 // Track if the map information being generated is the first for a list of
7503 // components.
7504 bool IsExpressionFirstInfo = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00007505 Address BP = Address::invalid();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007506 const Expr *AssocExpr = I->getAssociatedExpression();
7507 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7508 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
Samuel Antao86ace552016-04-27 22:40:57 +00007509
Patrick Lystere13b1e32019-01-02 19:28:48 +00007510 if (isa<MemberExpr>(AssocExpr)) {
Samuel Antao86ace552016-04-27 22:40:57 +00007511 // The base is the 'this' pointer. The content of the pointer is going
7512 // to be the base of the field being mapped.
Alexey Bataevb3638132018-07-19 16:34:13 +00007513 BP = CGF.LoadCXXThisAddress();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007514 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7515 (OASE &&
7516 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08007517 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
Samuel Antao86ace552016-04-27 22:40:57 +00007518 } else {
7519 // The base is the reference to the variable.
7520 // BP = &Var.
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08007521 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
Alexey Bataev92327c52018-03-26 16:40:55 +00007522 if (const auto *VD =
7523 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7524 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007525 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7526 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7527 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
7528 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) {
7529 RequiresReference = true;
7530 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataev2c1dffe2018-04-16 20:34:41 +00007531 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007532 }
Alexey Bataev92327c52018-03-26 16:40:55 +00007533 }
Samuel Antao86ace552016-04-27 22:40:57 +00007534
7535 // If the variable is a pointer and is being dereferenced (i.e. is not
Nico Webera6916892016-06-10 18:53:04 +00007536 // the last component), the base has to be the pointer itself, not its
Samuel Antao403ffd42016-07-27 22:49:49 +00007537 // reference. References are ignored for mapping purposes.
7538 QualType Ty =
7539 I->getAssociatedDeclaration()->getType().getNonReferenceType();
7540 if (Ty->isAnyPointerType() && std::next(I) != CE) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007541 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
Samuel Antao86ace552016-04-27 22:40:57 +00007542
7543 // We do not need to generate individual map information for the
7544 // pointer, it can be associated with the combined storage.
7545 ++I;
7546 }
7547 }
7548
Alexey Bataevb3638132018-07-19 16:34:13 +00007549 // Track whether a component of the list should be marked as MEMBER_OF some
7550 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry
7551 // in a component list should be marked as MEMBER_OF, all subsequent entries
7552 // do not belong to the base struct. E.g.
7553 // struct S2 s;
7554 // s.ps->ps->ps->f[:]
7555 // (1) (2) (3) (4)
7556 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a
7557 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3)
7558 // is the pointee of ps(2) which is not member of struct s, so it should not
7559 // be marked as such (it is still PTR_AND_OBJ).
7560 // The variable is initialized to false so that PTR_AND_OBJ entries which
7561 // are not struct members are not considered (e.g. array of pointers to
7562 // data).
7563 bool ShouldBeMemberOf = false;
7564
7565 // Variable keeping track of whether or not we have encountered a component
7566 // in the component list which is a member expression. Useful when we have a
7567 // pointer or a final array section, in which case it is the previous
7568 // component in the list which tells us whether we have a member expression.
7569 // E.g. X.f[:]
7570 // While processing the final array section "[:]" it is "f" which tells us
7571 // whether we are dealing with a member of a declared struct.
7572 const MemberExpr *EncounteredME = nullptr;
7573
Samuel Antao86ace552016-04-27 22:40:57 +00007574 for (; I != CE; ++I) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007575 // If the current component is member of a struct (parent struct) mark it.
7576 if (!EncounteredME) {
7577 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7578 // If we encounter a PTR_AND_OBJ entry from now on it should be marked
7579 // as MEMBER_OF the parent struct.
7580 if (EncounteredME)
7581 ShouldBeMemberOf = true;
7582 }
7583
Samuel Antao86ace552016-04-27 22:40:57 +00007584 auto Next = std::next(I);
7585
7586 // We need to generate the addresses and sizes if this is the last
7587 // component, if the component is a pointer or if it is an array section
7588 // whose length can't be proved to be one. If this is a pointer, it
7589 // becomes the base address for the following components.
7590
7591 // A final array section, is one whose length can't be proved to be one.
7592 bool IsFinalArraySection =
7593 isFinalArraySectionExpression(I->getAssociatedExpression());
7594
7595 // Get information on whether the element is a pointer. Have to do a
7596 // special treatment for array sections given that they are built-in
7597 // types.
7598 const auto *OASE =
7599 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression());
7600 bool IsPointer =
Alexey Bataevb3638132018-07-19 16:34:13 +00007601 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE)
7602 .getCanonicalType()
7603 ->isAnyPointerType()) ||
Samuel Antao86ace552016-04-27 22:40:57 +00007604 I->getAssociatedExpression()->getType()->isAnyPointerType();
7605
7606 if (Next == CE || IsPointer || IsFinalArraySection) {
Samuel Antao86ace552016-04-27 22:40:57 +00007607 // If this is not the last component, we expect the pointer to be
7608 // associated with an array expression or member expression.
7609 assert((Next == CE ||
7610 isa<MemberExpr>(Next->getAssociatedExpression()) ||
7611 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||
7612 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) &&
7613 "Unexpected expression");
7614
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08007615 Address LB =
7616 CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getAddress();
Samuel Antao86ace552016-04-27 22:40:57 +00007617
Alexey Bataevb3638132018-07-19 16:34:13 +00007618 // If this component is a pointer inside the base struct then we don't
7619 // need to create any entry for it - it will be combined with the object
7620 // it is pointing to into a single PTR_AND_OBJ entry.
7621 bool IsMemberPointer =
7622 IsPointer && EncounteredME &&
7623 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) ==
7624 EncounteredME);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007625 if (!OverlappedElements.empty()) {
7626 // Handle base element with the info for overlapped elements.
7627 assert(!PartialStruct.Base.isValid() && "The base element is set.");
7628 assert(Next == CE &&
7629 "Expected last element for the overlapped elements.");
7630 assert(!IsPointer &&
7631 "Unexpected base element with the pointer type.");
7632 // Mark the whole struct as the struct that requires allocation on the
7633 // device.
7634 PartialStruct.LowestElem = {0, LB};
7635 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(
7636 I->getAssociatedExpression()->getType());
7637 Address HB = CGF.Builder.CreateConstGEP(
7638 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB,
7639 CGF.VoidPtrTy),
James Y Knight751fe282019-02-09 22:22:28 +00007640 TypeSize.getQuantity() - 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007641 PartialStruct.HighestElem = {
7642 std::numeric_limits<decltype(
7643 PartialStruct.HighestElem.first)>::max(),
7644 HB};
7645 PartialStruct.Base = BP;
7646 // Emit data for non-overlapped data.
7647 OpenMPOffloadMappingFlags Flags =
7648 OMP_MAP_MEMBER_OF |
Kelvin Lief579432018-12-18 22:18:41 +00007649 getMapTypeBits(MapType, MapModifiers, IsImplicit,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007650 /*AddPtrFlag=*/false,
7651 /*AddIsTargetParamFlag=*/false);
7652 LB = BP;
7653 llvm::Value *Size = nullptr;
7654 // Do bitcopy of all non-overlapped structure elements.
7655 for (OMPClauseMappableExprCommon::MappableExprComponentListRef
7656 Component : OverlappedElements) {
7657 Address ComponentLB = Address::invalid();
7658 for (const OMPClauseMappableExprCommon::MappableComponent &MC :
7659 Component) {
7660 if (MC.getAssociatedDeclaration()) {
7661 ComponentLB =
7662 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08007663 .getAddress();
Alexey Bataeve82445f2018-09-20 13:54:02 +00007664 Size = CGF.Builder.CreatePtrDiff(
7665 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()),
7666 CGF.EmitCastToVoidPtr(LB.getPointer()));
7667 break;
7668 }
7669 }
7670 BasePointers.push_back(BP.getPointer());
7671 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007672 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty,
7673 /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007674 Types.push_back(Flags);
James Y Knight751fe282019-02-09 22:22:28 +00007675 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007676 }
7677 BasePointers.push_back(BP.getPointer());
7678 Pointers.push_back(LB.getPointer());
7679 Size = CGF.Builder.CreatePtrDiff(
7680 CGF.EmitCastToVoidPtr(
James Y Knight751fe282019-02-09 22:22:28 +00007681 CGF.Builder.CreateConstGEP(HB, 1).getPointer()),
Alexey Bataeve82445f2018-09-20 13:54:02 +00007682 CGF.EmitCastToVoidPtr(LB.getPointer()));
Alexey Bataeva90fc662019-06-25 16:00:43 +00007683 Sizes.push_back(
7684 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007685 Types.push_back(Flags);
7686 break;
7687 }
7688 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
Alexey Bataevb3638132018-07-19 16:34:13 +00007689 if (!IsMemberPointer) {
7690 BasePointers.push_back(BP.getPointer());
7691 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007692 Sizes.push_back(
7693 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Samuel Antao03a3cec2016-07-27 22:52:16 +00007694
Alexey Bataevb3638132018-07-19 16:34:13 +00007695 // We need to add a pointer flag for each map that comes from the
7696 // same expression except for the first one. We also need to signal
7697 // this map is the first one that relates with the current capture
7698 // (there is a set of entries for each capture).
7699 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
Kelvin Lief579432018-12-18 22:18:41 +00007700 MapType, MapModifiers, IsImplicit,
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007701 !IsExpressionFirstInfo || RequiresReference,
7702 IsCaptureFirstInfo && !RequiresReference);
Alexey Bataevb3638132018-07-19 16:34:13 +00007703
7704 if (!IsExpressionFirstInfo) {
7705 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007706 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags.
Alexey Bataevb3638132018-07-19 16:34:13 +00007707 if (IsPointer)
7708 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS |
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007709 OMP_MAP_DELETE | OMP_MAP_CLOSE);
Alexey Bataevb3638132018-07-19 16:34:13 +00007710
7711 if (ShouldBeMemberOf) {
7712 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag
7713 // should be later updated with the correct value of MEMBER_OF.
7714 Flags |= OMP_MAP_MEMBER_OF;
7715 // From now on, all subsequent PTR_AND_OBJ entries should not be
7716 // marked as MEMBER_OF.
7717 ShouldBeMemberOf = false;
7718 }
7719 }
7720
7721 Types.push_back(Flags);
Samuel Antao03a3cec2016-07-27 22:52:16 +00007722 }
7723
Alexey Bataevb3638132018-07-19 16:34:13 +00007724 // If we have encountered a member expression so far, keep track of the
7725 // mapped member. If the parent is "*this", then the value declaration
7726 // is nullptr.
7727 if (EncounteredME) {
7728 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl());
7729 unsigned FieldIndex = FD->getFieldIndex();
Samuel Antao03a3cec2016-07-27 22:52:16 +00007730
Alexey Bataevb3638132018-07-19 16:34:13 +00007731 // Update info about the lowest and highest elements for this struct
7732 if (!PartialStruct.Base.isValid()) {
7733 PartialStruct.LowestElem = {FieldIndex, LB};
7734 PartialStruct.HighestElem = {FieldIndex, LB};
7735 PartialStruct.Base = BP;
7736 } else if (FieldIndex < PartialStruct.LowestElem.first) {
7737 PartialStruct.LowestElem = {FieldIndex, LB};
7738 } else if (FieldIndex > PartialStruct.HighestElem.first) {
7739 PartialStruct.HighestElem = {FieldIndex, LB};
7740 }
7741 }
Samuel Antao86ace552016-04-27 22:40:57 +00007742
7743 // If we have a final array section, we are done with this expression.
7744 if (IsFinalArraySection)
7745 break;
7746
7747 // The pointer becomes the base for the next element.
7748 if (Next != CE)
7749 BP = LB;
7750
7751 IsExpressionFirstInfo = false;
7752 IsCaptureFirstInfo = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007753 }
7754 }
7755 }
7756
Alexey Bataevb3638132018-07-19 16:34:13 +00007757 /// Return the adjusted map modifiers if the declaration a capture refers to
7758 /// appears in a first-private clause. This is expected to be used only with
7759 /// directives that start with 'target'.
7760 MappableExprsHandler::OpenMPOffloadMappingFlags
7761 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const {
7762 assert(Cap.capturesVariable() && "Expected capture by reference only!");
7763
7764 // A first private variable captured by reference will use only the
7765 // 'private ptr' and 'map to' flag. Return the right flags if the captured
7766 // declaration is known as first-private in this handler.
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007767 if (FirstPrivateDecls.count(Cap.getCapturedVar())) {
7768 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) &&
7769 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef)
7770 return MappableExprsHandler::OMP_MAP_ALWAYS |
7771 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataevc2b831f2019-04-02 16:03:40 +00007772 if (Cap.getCapturedVar()->getType()->isAnyPointerType())
7773 return MappableExprsHandler::OMP_MAP_TO |
7774 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ;
Alexey Bataevb3638132018-07-19 16:34:13 +00007775 return MappableExprsHandler::OMP_MAP_PRIVATE |
7776 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007777 }
Alexey Bataevb3638132018-07-19 16:34:13 +00007778 return MappableExprsHandler::OMP_MAP_TO |
7779 MappableExprsHandler::OMP_MAP_FROM;
7780 }
7781
7782 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) {
Michael Krused47b9432019-08-05 18:43:21 +00007783 // Rotate by getFlagMemberOffset() bits.
Alexey Bataevb3638132018-07-19 16:34:13 +00007784 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1)
Michael Krused47b9432019-08-05 18:43:21 +00007785 << getFlagMemberOffset());
Alexey Bataevb3638132018-07-19 16:34:13 +00007786 }
7787
7788 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags,
7789 OpenMPOffloadMappingFlags MemberOfFlag) {
7790 // If the entry is PTR_AND_OBJ but has not been marked with the special
7791 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be
7792 // marked as MEMBER_OF.
7793 if ((Flags & OMP_MAP_PTR_AND_OBJ) &&
7794 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF))
7795 return;
7796
7797 // Reset the placeholder value to prepare the flag for the assignment of the
7798 // proper MEMBER_OF value.
7799 Flags &= ~OMP_MAP_MEMBER_OF;
7800 Flags |= MemberOfFlag;
7801 }
7802
Alexey Bataeve82445f2018-09-20 13:54:02 +00007803 void getPlainLayout(const CXXRecordDecl *RD,
7804 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
7805 bool AsBase) const {
7806 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD);
7807
7808 llvm::StructType *St =
7809 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType();
7810
7811 unsigned NumElements = St->getNumElements();
7812 llvm::SmallVector<
7813 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
7814 RecordLayout(NumElements);
7815
7816 // Fill bases.
7817 for (const auto &I : RD->bases()) {
7818 if (I.isVirtual())
7819 continue;
7820 const auto *Base = I.getType()->getAsCXXRecordDecl();
7821 // Ignore empty bases.
7822 if (Base->isEmpty() || CGF.getContext()
7823 .getASTRecordLayout(Base)
7824 .getNonVirtualSize()
7825 .isZero())
7826 continue;
7827
7828 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
7829 RecordLayout[FieldIndex] = Base;
7830 }
7831 // Fill in virtual bases.
7832 for (const auto &I : RD->vbases()) {
7833 const auto *Base = I.getType()->getAsCXXRecordDecl();
7834 // Ignore empty bases.
7835 if (Base->isEmpty())
7836 continue;
7837 unsigned FieldIndex = RL.getVirtualBaseIndex(Base);
7838 if (RecordLayout[FieldIndex])
7839 continue;
7840 RecordLayout[FieldIndex] = Base;
7841 }
7842 // Fill in all the fields.
7843 assert(!RD->isUnion() && "Unexpected union.");
7844 for (const auto *Field : RD->fields()) {
7845 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
7846 // will fill in later.)
Richard Smith78b239e2019-06-20 20:44:45 +00007847 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) {
Alexey Bataeve82445f2018-09-20 13:54:02 +00007848 unsigned FieldIndex = RL.getLLVMFieldNo(Field);
7849 RecordLayout[FieldIndex] = Field;
7850 }
7851 }
7852 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
7853 &Data : RecordLayout) {
7854 if (Data.isNull())
7855 continue;
7856 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>())
7857 getPlainLayout(Base, Layout, /*AsBase=*/true);
7858 else
7859 Layout.push_back(Data.get<const FieldDecl *>());
7860 }
7861 }
7862
Alexey Bataevb3638132018-07-19 16:34:13 +00007863public:
7864 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
Michael Krused47b9432019-08-05 18:43:21 +00007865 : CurDir(&Dir), CGF(CGF) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007866 // Extract firstprivate clause information.
7867 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>())
7868 for (const auto *D : C->varlists())
Alexey Bataevf288cf92019-06-27 18:53:07 +00007869 FirstPrivateDecls.try_emplace(
7870 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit());
Alexey Bataevb3638132018-07-19 16:34:13 +00007871 // Extract device pointer clause information.
7872 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
7873 for (auto L : C->component_lists())
7874 DevPointersMap[L.first].push_back(L.second);
7875 }
7876
Michael Krused47b9432019-08-05 18:43:21 +00007877 /// Constructor for the declare mapper directive.
7878 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF)
7879 : CurDir(&Dir), CGF(CGF) {}
7880
Alexey Bataevb3638132018-07-19 16:34:13 +00007881 /// Generate code for the combined entry if we have a partially mapped struct
7882 /// and take care of the mapping flags of the arguments corresponding to
7883 /// individual struct members.
7884 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers,
7885 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7886 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes,
7887 const StructRangeInfoTy &PartialStruct) const {
7888 // Base is the base of the struct
7889 BasePointers.push_back(PartialStruct.Base.getPointer());
7890 // Pointer is the address of the lowest element
7891 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer();
7892 Pointers.push_back(LB);
7893 // Size is (addr of {highest+1} element) - (addr of lowest element)
7894 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer();
7895 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1);
7896 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy);
7897 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy);
7898 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00007899 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00007900 /*isSigned=*/false);
Alexey Bataevb3638132018-07-19 16:34:13 +00007901 Sizes.push_back(Size);
7902 // Map type is always TARGET_PARAM
7903 Types.push_back(OMP_MAP_TARGET_PARAM);
7904 // Remove TARGET_PARAM flag from the first element
7905 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM;
7906
7907 // All other current entries will be MEMBER_OF the combined entry
7908 // (except for PTR_AND_OBJ entries which do not have a placeholder value
7909 // 0xFFFF in the MEMBER_OF field).
7910 OpenMPOffloadMappingFlags MemberOfFlag =
7911 getMemberOfFlag(BasePointers.size() - 1);
7912 for (auto &M : CurTypes)
7913 setCorrectMemberOfFlag(M, MemberOfFlag);
7914 }
7915
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007916 /// Generate all the base pointers, section pointers, sizes and map
Samuel Antaocc10b852016-07-28 14:23:26 +00007917 /// types for the extracted mappable expressions. Also, for each item that
7918 /// relates with a device pointer, a pair of the relevant declaration and
7919 /// index where it occurs is appended to the device pointers info array.
7920 void generateAllInfo(MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007921 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7922 MapFlagsArrayTy &Types) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007923 // We have to process the component lists that relate with the same
7924 // declaration in a single chunk so that we can generate the map flags
7925 // correctly. Therefore, we organize all lists in a map.
Alexey Bataev5d1c3f62017-06-27 15:46:42 +00007926 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
Samuel Antao8d2d7302016-05-26 18:30:22 +00007927
7928 // Helper function to fill the information map for the different supported
7929 // clauses.
Samuel Antaocc10b852016-07-28 14:23:26 +00007930 auto &&InfoGen = [&Info](
7931 const ValueDecl *D,
7932 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
Kelvin Lief579432018-12-18 22:18:41 +00007933 OpenMPMapClauseKind MapType,
7934 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007935 bool ReturnDevicePointer, bool IsImplicit) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007936 const ValueDecl *VD =
7937 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
Kelvin Lief579432018-12-18 22:18:41 +00007938 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007939 IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00007940 };
Samuel Antao8d2d7302016-05-26 18:30:22 +00007941
Michael Krused47b9432019-08-05 18:43:21 +00007942 assert(CurDir.is<const OMPExecutableDirective *>() &&
7943 "Expect a executable directive");
7944 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
7945 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>())
Mark de Wever51abceb2019-11-12 20:48:11 +01007946 for (const auto L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007947 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(),
Alexey Bataevb3638132018-07-19 16:34:13 +00007948 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007949 }
Michael Krused47b9432019-08-05 18:43:21 +00007950 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>())
Mark de Wever51abceb2019-11-12 20:48:11 +01007951 for (const auto L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007952 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007953 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007954 }
Michael Krused47b9432019-08-05 18:43:21 +00007955 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>())
Mark de Wever51abceb2019-11-12 20:48:11 +01007956 for (const auto L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007957 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007958 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007959 }
Samuel Antao86ace552016-04-27 22:40:57 +00007960
Samuel Antaocc10b852016-07-28 14:23:26 +00007961 // Look at the use_device_ptr clause information and mark the existing map
7962 // entries as such. If there is no map information for an entry in the
7963 // use_device_ptr list, we create one with map type 'alloc' and zero size
Alexey Bataevb3638132018-07-19 16:34:13 +00007964 // section. It is the user fault if that was not mapped before. If there is
7965 // no map information and the pointer is a struct member, then we defer the
7966 // emission of that entry until the whole struct has been processed.
7967 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>>
7968 DeferredInfo;
7969
Alexey Bataevb3638132018-07-19 16:34:13 +00007970 for (const auto *C :
Michael Krused47b9432019-08-05 18:43:21 +00007971 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) {
Mark de Wever51abceb2019-11-12 20:48:11 +01007972 for (const auto L : C->component_lists()) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007973 assert(!L.second.empty() && "Not expecting empty list of components!");
7974 const ValueDecl *VD = L.second.back().getAssociatedDeclaration();
7975 VD = cast<ValueDecl>(VD->getCanonicalDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007976 const Expr *IE = L.second.back().getAssociatedExpression();
Samuel Antaocc10b852016-07-28 14:23:26 +00007977 // If the first component is a member expression, we have to look into
7978 // 'this', which maps to null in the map of map information. Otherwise
7979 // look directly for the information.
7980 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
7981
7982 // We potentially have map information for this declaration already.
7983 // Look for the first set of components that refer to it.
7984 if (It != Info.end()) {
7985 auto CI = std::find_if(
7986 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) {
7987 return MI.Components.back().getAssociatedDeclaration() == VD;
7988 });
7989 // If we found a map entry, signal that the pointer has to be returned
7990 // and move on to the next declaration.
7991 if (CI != It->second.end()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007992 CI->ReturnDevicePointer = true;
Samuel Antaocc10b852016-07-28 14:23:26 +00007993 continue;
7994 }
7995 }
7996
7997 // We didn't find any match in our map information - generate a zero
Alexey Bataevb3638132018-07-19 16:34:13 +00007998 // size array section - if the pointer is a struct member we defer this
7999 // action until the whole struct has been processed.
Alexey Bataevb3638132018-07-19 16:34:13 +00008000 if (isa<MemberExpr>(IE)) {
8001 // Insert the pointer into Info to be processed by
8002 // generateInfoForComponentList. Because it is a member pointer
8003 // without a pointee, no entry will be generated for it, therefore
8004 // we need to generate one after the whole struct has been processed.
8005 // Nonetheless, generateInfoForComponentList must be called to take
8006 // the pointer into account for the calculation of the range of the
8007 // partial struct.
Kelvin Lief579432018-12-18 22:18:41 +00008008 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00008009 /*ReturnDevicePointer=*/false, C->isImplicit());
8010 DeferredInfo[nullptr].emplace_back(IE, VD);
8011 } else {
Michael Krused47b9432019-08-05 18:43:21 +00008012 llvm::Value *Ptr =
8013 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc());
Alexey Bataevb3638132018-07-19 16:34:13 +00008014 BasePointers.emplace_back(Ptr, VD);
8015 Pointers.push_back(Ptr);
Michael Krused47b9432019-08-05 18:43:21 +00008016 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00008017 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM);
8018 }
Samuel Antaocc10b852016-07-28 14:23:26 +00008019 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008020 }
Samuel Antaocc10b852016-07-28 14:23:26 +00008021
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008022 for (const auto &M : Info) {
Samuel Antao86ace552016-04-27 22:40:57 +00008023 // We need to know when we generate information for the first component
8024 // associated with a capture, because the mapping flags depend on it.
8025 bool IsFirstComponentList = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00008026
8027 // Temporary versions of arrays
8028 MapBaseValuesArrayTy CurBasePointers;
8029 MapValuesArrayTy CurPointers;
8030 MapValuesArrayTy CurSizes;
8031 MapFlagsArrayTy CurTypes;
8032 StructRangeInfoTy PartialStruct;
8033
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008034 for (const MapInfo &L : M.second) {
Samuel Antao86ace552016-04-27 22:40:57 +00008035 assert(!L.Components.empty() &&
8036 "Not expecting declaration with no component lists.");
Samuel Antaocc10b852016-07-28 14:23:26 +00008037
8038 // Remember the current base pointer index.
Alexey Bataevb3638132018-07-19 16:34:13 +00008039 unsigned CurrentBasePointersIdx = CurBasePointers.size();
Michael Krused47b9432019-08-05 18:43:21 +00008040 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8041 CurBasePointers, CurPointers, CurSizes,
8042 CurTypes, PartialStruct,
8043 IsFirstComponentList, L.IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00008044
8045 // If this entry relates with a device pointer, set the relevant
8046 // declaration and add the 'return pointer' flag.
Alexey Bataevb3638132018-07-19 16:34:13 +00008047 if (L.ReturnDevicePointer) {
8048 assert(CurBasePointers.size() > CurrentBasePointersIdx &&
Samuel Antaocc10b852016-07-28 14:23:26 +00008049 "Unexpected number of mapped base pointers.");
8050
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008051 const ValueDecl *RelevantVD =
8052 L.Components.back().getAssociatedDeclaration();
Samuel Antaocc10b852016-07-28 14:23:26 +00008053 assert(RelevantVD &&
8054 "No relevant declaration related with device pointer??");
8055
Alexey Bataevb3638132018-07-19 16:34:13 +00008056 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD);
8057 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008058 }
Samuel Antao86ace552016-04-27 22:40:57 +00008059 IsFirstComponentList = false;
8060 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008061
8062 // Append any pending zero-length pointers which are struct members and
8063 // used with use_device_ptr.
8064 auto CI = DeferredInfo.find(M.first);
8065 if (CI != DeferredInfo.end()) {
8066 for (const DeferredDevicePtrEntryTy &L : CI->second) {
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08008067 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer();
Alexey Bataevb3638132018-07-19 16:34:13 +00008068 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar(
8069 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc());
8070 CurBasePointers.emplace_back(BasePtr, L.VD);
8071 CurPointers.push_back(Ptr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008072 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00008073 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder
8074 // value MEMBER_OF=FFFF so that the entry is later updated with the
8075 // correct value of MEMBER_OF.
8076 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM |
8077 OMP_MAP_MEMBER_OF);
8078 }
8079 }
8080
8081 // If there is an entry in PartialStruct it means we have a struct with
8082 // individual members mapped. Emit an extra combined entry.
8083 if (PartialStruct.Base.isValid())
8084 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8085 PartialStruct);
8086
8087 // We need to append the results of this capture to what we already have.
8088 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8089 Pointers.append(CurPointers.begin(), CurPointers.end());
8090 Sizes.append(CurSizes.begin(), CurSizes.end());
8091 Types.append(CurTypes.begin(), CurTypes.end());
Samuel Antao86ace552016-04-27 22:40:57 +00008092 }
8093 }
8094
Michael Krused47b9432019-08-05 18:43:21 +00008095 /// Generate all the base pointers, section pointers, sizes and map types for
8096 /// the extracted map clauses of user-defined mapper.
8097 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers,
8098 MapValuesArrayTy &Pointers,
8099 MapValuesArrayTy &Sizes,
8100 MapFlagsArrayTy &Types) const {
8101 assert(CurDir.is<const OMPDeclareMapperDecl *>() &&
8102 "Expect a declare mapper directive");
8103 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>();
8104 // We have to process the component lists that relate with the same
8105 // declaration in a single chunk so that we can generate the map flags
8106 // correctly. Therefore, we organize all lists in a map.
8107 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
8108
8109 // Helper function to fill the information map for the different supported
8110 // clauses.
8111 auto &&InfoGen = [&Info](
8112 const ValueDecl *D,
8113 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
8114 OpenMPMapClauseKind MapType,
8115 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8116 bool ReturnDevicePointer, bool IsImplicit) {
8117 const ValueDecl *VD =
8118 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
8119 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
8120 IsImplicit);
8121 };
8122
8123 for (const auto *C : CurMapperDir->clauselists()) {
8124 const auto *MC = cast<OMPMapClause>(C);
Mark de Wever51abceb2019-11-12 20:48:11 +01008125 for (const auto L : MC->component_lists()) {
Michael Krused47b9432019-08-05 18:43:21 +00008126 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(),
8127 /*ReturnDevicePointer=*/false, MC->isImplicit());
8128 }
8129 }
8130
8131 for (const auto &M : Info) {
8132 // We need to know when we generate information for the first component
8133 // associated with a capture, because the mapping flags depend on it.
8134 bool IsFirstComponentList = true;
8135
8136 // Temporary versions of arrays
8137 MapBaseValuesArrayTy CurBasePointers;
8138 MapValuesArrayTy CurPointers;
8139 MapValuesArrayTy CurSizes;
8140 MapFlagsArrayTy CurTypes;
8141 StructRangeInfoTy PartialStruct;
8142
8143 for (const MapInfo &L : M.second) {
8144 assert(!L.Components.empty() &&
8145 "Not expecting declaration with no component lists.");
8146 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8147 CurBasePointers, CurPointers, CurSizes,
8148 CurTypes, PartialStruct,
8149 IsFirstComponentList, L.IsImplicit);
8150 IsFirstComponentList = false;
8151 }
8152
8153 // If there is an entry in PartialStruct it means we have a struct with
8154 // individual members mapped. Emit an extra combined entry.
8155 if (PartialStruct.Base.isValid())
8156 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8157 PartialStruct);
8158
8159 // We need to append the results of this capture to what we already have.
8160 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8161 Pointers.append(CurPointers.begin(), CurPointers.end());
8162 Sizes.append(CurSizes.begin(), CurSizes.end());
8163 Types.append(CurTypes.begin(), CurTypes.end());
8164 }
8165 }
8166
Alexey Bataev60705422018-10-30 15:50:12 +00008167 /// Emit capture info for lambdas for variables captured by reference.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008168 void generateInfoForLambdaCaptures(
8169 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers,
8170 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
8171 MapFlagsArrayTy &Types,
8172 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008173 const auto *RD = VD->getType()
8174 .getCanonicalType()
8175 .getNonReferenceType()
8176 ->getAsCXXRecordDecl();
8177 if (!RD || !RD->isLambda())
8178 return;
8179 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD));
8180 LValue VDLVal = CGF.MakeAddrLValue(
8181 VDAddr, VD->getType().getCanonicalType().getNonReferenceType());
8182 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
8183 FieldDecl *ThisCapture = nullptr;
8184 RD->getCaptureFields(Captures, ThisCapture);
8185 if (ThisCapture) {
8186 LValue ThisLVal =
8187 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture);
Alexey Bataev969dbc02018-11-08 15:47:39 +00008188 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture);
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08008189 LambdaPointers.try_emplace(ThisLVal.getPointer(), VDLVal.getPointer());
8190 BasePointers.push_back(ThisLVal.getPointer());
8191 Pointers.push_back(ThisLValVal.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00008192 Sizes.push_back(
8193 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8194 CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008195 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008196 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8197 }
8198 for (const LambdaCapture &LC : RD->captures()) {
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008199 if (!LC.capturesVariable())
Alexey Bataev60705422018-10-30 15:50:12 +00008200 continue;
8201 const VarDecl *VD = LC.getCapturedVar();
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008202 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType())
8203 continue;
Alexey Bataev60705422018-10-30 15:50:12 +00008204 auto It = Captures.find(VD);
8205 assert(It != Captures.end() && "Found lambda capture without field.");
8206 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second);
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008207 if (LC.getCaptureKind() == LCK_ByRef) {
8208 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second);
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08008209 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer());
8210 BasePointers.push_back(VarLVal.getPointer());
8211 Pointers.push_back(VarLValVal.getPointer());
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008212 Sizes.push_back(CGF.Builder.CreateIntCast(
8213 CGF.getTypeSize(
8214 VD->getType().getCanonicalType().getNonReferenceType()),
8215 CGF.Int64Ty, /*isSigned=*/true));
8216 } else {
8217 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation());
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08008218 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer());
8219 BasePointers.push_back(VarLVal.getPointer());
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008220 Pointers.push_back(VarRVal.getScalarVal());
8221 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0));
8222 }
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008223 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008224 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8225 }
8226 }
8227
8228 /// Set correct indices for lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008229 void adjustMemberOfForLambdaCaptures(
8230 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
8231 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
8232 MapFlagsArrayTy &Types) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008233 for (unsigned I = 0, E = Types.size(); I < E; ++I) {
8234 // Set correct member_of idx for all implicit lambda captures.
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008235 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008236 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT))
8237 continue;
Alexey Bataev969dbc02018-11-08 15:47:39 +00008238 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]);
8239 assert(BasePtr && "Unable to find base lambda address.");
Alexey Bataev60705422018-10-30 15:50:12 +00008240 int TgtIdx = -1;
8241 for (unsigned J = I; J > 0; --J) {
8242 unsigned Idx = J - 1;
8243 if (Pointers[Idx] != BasePtr)
8244 continue;
8245 TgtIdx = Idx;
8246 break;
8247 }
8248 assert(TgtIdx != -1 && "Unable to find parent lambda.");
8249 // All other current entries will be MEMBER_OF the combined entry
8250 // (except for PTR_AND_OBJ entries which do not have a placeholder value
8251 // 0xFFFF in the MEMBER_OF field).
8252 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx);
8253 setCorrectMemberOfFlag(Types[I], MemberOfFlag);
8254 }
8255 }
8256
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008257 /// Generate the base pointers, section pointers, sizes and map types
Samuel Antao86ace552016-04-27 22:40:57 +00008258 /// associated to a given capture.
8259 void generateInfoForCapture(const CapturedStmt::Capture *Cap,
Samuel Antao6890b092016-07-28 14:25:09 +00008260 llvm::Value *Arg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008261 MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00008262 MapValuesArrayTy &Pointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008263 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
8264 StructRangeInfoTy &PartialStruct) const {
Samuel Antao86ace552016-04-27 22:40:57 +00008265 assert(!Cap->capturesVariableArrayType() &&
8266 "Not expecting to generate map info for a variable array type!");
8267
Samuel Antao6890b092016-07-28 14:25:09 +00008268 // We need to know when we generating information for the first component
Alexey Bataevb3638132018-07-19 16:34:13 +00008269 const ValueDecl *VD = Cap->capturesThis()
8270 ? nullptr
8271 : Cap->getCapturedVar()->getCanonicalDecl();
Samuel Antao86ace552016-04-27 22:40:57 +00008272
Samuel Antao6890b092016-07-28 14:25:09 +00008273 // If this declaration appears in a is_device_ptr clause we just have to
8274 // pass the pointer by value. If it is a reference to a declaration, we just
Alexey Bataevb3638132018-07-19 16:34:13 +00008275 // pass its value.
8276 if (DevPointersMap.count(VD)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008277 BasePointers.emplace_back(Arg, VD);
Samuel Antao6890b092016-07-28 14:25:09 +00008278 Pointers.push_back(Arg);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008279 Sizes.push_back(
8280 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8281 CGF.Int64Ty, /*isSigned=*/true));
George Rokos065755d2017-11-07 18:27:04 +00008282 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM);
Samuel Antao6890b092016-07-28 14:25:09 +00008283 return;
8284 }
8285
Alexey Bataeve82445f2018-09-20 13:54:02 +00008286 using MapData =
8287 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
Kelvin Lief579432018-12-18 22:18:41 +00008288 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008289 SmallVector<MapData, 4> DeclComponentLists;
Michael Krused47b9432019-08-05 18:43:21 +00008290 assert(CurDir.is<const OMPExecutableDirective *>() &&
8291 "Expect a executable directive");
8292 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
8293 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
Mark de Wever51abceb2019-11-12 20:48:11 +01008294 for (const auto L : C->decl_component_lists(VD)) {
Samuel Antao86ace552016-04-27 22:40:57 +00008295 assert(L.first == VD &&
8296 "We got information for the wrong declaration??");
8297 assert(!L.second.empty() &&
8298 "Not expecting declaration with no component lists.");
Alexey Bataeve82445f2018-09-20 13:54:02 +00008299 DeclComponentLists.emplace_back(L.second, C->getMapType(),
Kelvin Lief579432018-12-18 22:18:41 +00008300 C->getMapTypeModifiers(),
Alexey Bataeve82445f2018-09-20 13:54:02 +00008301 C->isImplicit());
Samuel Antao86ace552016-04-27 22:40:57 +00008302 }
Alexey Bataeve82445f2018-09-20 13:54:02 +00008303 }
8304
8305 // Find overlapping elements (including the offset from the base element).
8306 llvm::SmallDenseMap<
8307 const MapData *,
8308 llvm::SmallVector<
8309 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>,
8310 4>
8311 OverlappedData;
8312 size_t Count = 0;
8313 for (const MapData &L : DeclComponentLists) {
8314 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8315 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008316 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008317 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008318 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008319 ++Count;
8320 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) {
8321 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1;
Kelvin Lief579432018-12-18 22:18:41 +00008322 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008323 auto CI = Components.rbegin();
8324 auto CE = Components.rend();
8325 auto SI = Components1.rbegin();
8326 auto SE = Components1.rend();
8327 for (; CI != CE && SI != SE; ++CI, ++SI) {
8328 if (CI->getAssociatedExpression()->getStmtClass() !=
8329 SI->getAssociatedExpression()->getStmtClass())
8330 break;
8331 // Are we dealing with different variables/fields?
8332 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
8333 break;
8334 }
8335 // Found overlapping if, at least for one component, reached the head of
8336 // the components list.
8337 if (CI == CE || SI == SE) {
8338 assert((CI != CE || SI != SE) &&
8339 "Unexpected full match of the mapping components.");
8340 const MapData &BaseData = CI == CE ? L : L1;
8341 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData =
8342 SI == SE ? Components : Components1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008343 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData);
8344 OverlappedElements.getSecond().push_back(SubData);
8345 }
8346 }
8347 }
8348 // Sort the overlapped elements for each item.
8349 llvm::SmallVector<const FieldDecl *, 4> Layout;
8350 if (!OverlappedData.empty()) {
8351 if (const auto *CRD =
8352 VD->getType().getCanonicalType()->getAsCXXRecordDecl())
8353 getPlainLayout(CRD, Layout, /*AsBase=*/false);
8354 else {
8355 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl();
8356 Layout.append(RD->field_begin(), RD->field_end());
8357 }
8358 }
8359 for (auto &Pair : OverlappedData) {
8360 llvm::sort(
8361 Pair.getSecond(),
8362 [&Layout](
8363 OMPClauseMappableExprCommon::MappableExprComponentListRef First,
8364 OMPClauseMappableExprCommon::MappableExprComponentListRef
8365 Second) {
8366 auto CI = First.rbegin();
8367 auto CE = First.rend();
8368 auto SI = Second.rbegin();
8369 auto SE = Second.rend();
8370 for (; CI != CE && SI != SE; ++CI, ++SI) {
8371 if (CI->getAssociatedExpression()->getStmtClass() !=
8372 SI->getAssociatedExpression()->getStmtClass())
8373 break;
8374 // Are we dealing with different variables/fields?
8375 if (CI->getAssociatedDeclaration() !=
8376 SI->getAssociatedDeclaration())
8377 break;
8378 }
Richard Trieu5061e832018-09-21 21:20:33 +00008379
8380 // Lists contain the same elements.
8381 if (CI == CE && SI == SE)
8382 return false;
8383
8384 // List with less elements is less than list with more elements.
8385 if (CI == CE || SI == SE)
8386 return CI == CE;
8387
Alexey Bataeve82445f2018-09-20 13:54:02 +00008388 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
8389 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
8390 if (FD1->getParent() == FD2->getParent())
8391 return FD1->getFieldIndex() < FD2->getFieldIndex();
8392 const auto It =
8393 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) {
8394 return FD == FD1 || FD == FD2;
8395 });
8396 return *It == FD1;
8397 });
8398 }
8399
8400 // Associated with a capture, because the mapping flags depend on it.
8401 // Go through all of the elements with the overlapped elements.
8402 for (const auto &Pair : OverlappedData) {
8403 const MapData &L = *Pair.getFirst();
8404 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8405 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008406 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008407 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008408 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008409 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
8410 OverlappedComponents = Pair.getSecond();
8411 bool IsFirstComponentList = true;
Kelvin Lief579432018-12-18 22:18:41 +00008412 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008413 BasePointers, Pointers, Sizes, Types,
8414 PartialStruct, IsFirstComponentList,
8415 IsImplicit, OverlappedComponents);
8416 }
8417 // Go through other elements without overlapped elements.
8418 bool IsFirstComponentList = OverlappedData.empty();
8419 for (const MapData &L : DeclComponentLists) {
8420 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8421 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008422 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008423 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008424 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008425 auto It = OverlappedData.find(&L);
8426 if (It == OverlappedData.end())
Kelvin Lief579432018-12-18 22:18:41 +00008427 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008428 BasePointers, Pointers, Sizes, Types,
8429 PartialStruct, IsFirstComponentList,
8430 IsImplicit);
8431 IsFirstComponentList = false;
8432 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008433 }
Samuel Antao86ace552016-04-27 22:40:57 +00008434
Alexey Bataevb3638132018-07-19 16:34:13 +00008435 /// Generate the base pointers, section pointers, sizes and map types
8436 /// associated with the declare target link variables.
8437 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers,
8438 MapValuesArrayTy &Pointers,
8439 MapValuesArrayTy &Sizes,
8440 MapFlagsArrayTy &Types) const {
Michael Krused47b9432019-08-05 18:43:21 +00008441 assert(CurDir.is<const OMPExecutableDirective *>() &&
8442 "Expect a executable directive");
8443 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
Alexey Bataevb3638132018-07-19 16:34:13 +00008444 // Map other list items in the map clause which are not captured variables
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00008445 // but "declare target link" global variables.
Michael Krused47b9432019-08-05 18:43:21 +00008446 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
Mark de Wever51abceb2019-11-12 20:48:11 +01008447 for (const auto L : C->component_lists()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00008448 if (!L.first)
8449 continue;
8450 const auto *VD = dyn_cast<VarDecl>(L.first);
8451 if (!VD)
8452 continue;
8453 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00008454 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00008455 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
8456 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)
Alexey Bataevb3638132018-07-19 16:34:13 +00008457 continue;
8458 StructRangeInfoTy PartialStruct;
8459 generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00008460 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008461 Pointers, Sizes, Types, PartialStruct,
8462 /*IsFirstComponentList=*/true, C->isImplicit());
8463 assert(!PartialStruct.Base.isValid() &&
8464 "No partial structs for declare target link expected.");
8465 }
8466 }
Samuel Antao86ace552016-04-27 22:40:57 +00008467 }
Samuel Antaod486f842016-05-26 16:53:38 +00008468
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008469 /// Generate the default map information for a given capture \a CI,
Samuel Antaod486f842016-05-26 16:53:38 +00008470 /// record field declaration \a RI and captured value \a CV.
Samuel Antaocc10b852016-07-28 14:23:26 +00008471 void generateDefaultMapInfo(const CapturedStmt::Capture &CI,
8472 const FieldDecl &RI, llvm::Value *CV,
8473 MapBaseValuesArrayTy &CurBasePointers,
8474 MapValuesArrayTy &CurPointers,
8475 MapValuesArrayTy &CurSizes,
Alexey Bataevb3638132018-07-19 16:34:13 +00008476 MapFlagsArrayTy &CurMapTypes) const {
Alexey Bataevf288cf92019-06-27 18:53:07 +00008477 bool IsImplicit = true;
Samuel Antaod486f842016-05-26 16:53:38 +00008478 // Do the default mapping.
8479 if (CI.capturesThis()) {
8480 CurBasePointers.push_back(CV);
8481 CurPointers.push_back(CV);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008482 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr());
Alexey Bataeva90fc662019-06-25 16:00:43 +00008483 CurSizes.push_back(
8484 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()),
8485 CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008486 // Default map type.
Samuel Antaocc10b852016-07-28 14:23:26 +00008487 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM);
Samuel Antaod486f842016-05-26 16:53:38 +00008488 } else if (CI.capturesVariableByCopy()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008489 CurBasePointers.push_back(CV);
8490 CurPointers.push_back(CV);
Samuel Antaod486f842016-05-26 16:53:38 +00008491 if (!RI.getType()->isAnyPointerType()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008492 // We have to signal to the runtime captures passed by value that are
8493 // not pointers.
George Rokos065755d2017-11-07 18:27:04 +00008494 CurMapTypes.push_back(OMP_MAP_LITERAL);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008495 CurSizes.push_back(CGF.Builder.CreateIntCast(
8496 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008497 } else {
8498 // Pointers are implicitly mapped with a zero size and no flags
8499 // (other than first map that is added for all implicit maps).
Alexey Bataevb3638132018-07-19 16:34:13 +00008500 CurMapTypes.push_back(OMP_MAP_NONE);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008501 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
Samuel Antaod486f842016-05-26 16:53:38 +00008502 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008503 const VarDecl *VD = CI.getCapturedVar();
8504 auto I = FirstPrivateDecls.find(VD);
8505 if (I != FirstPrivateDecls.end())
8506 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008507 } else {
8508 assert(CI.capturesVariable() && "Expected captured reference.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008509 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr());
Samuel Antaod486f842016-05-26 16:53:38 +00008510 QualType ElementType = PtrTy->getPointeeType();
Alexey Bataeva90fc662019-06-25 16:00:43 +00008511 CurSizes.push_back(CGF.Builder.CreateIntCast(
8512 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008513 // The default map type for a scalar/complex type is 'to' because by
8514 // default the value doesn't have to be retrieved. For an aggregate
8515 // type, the default is 'tofrom'.
Alexey Bataevb3638132018-07-19 16:34:13 +00008516 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI));
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008517 const VarDecl *VD = CI.getCapturedVar();
Alexey Bataevf288cf92019-06-27 18:53:07 +00008518 auto I = FirstPrivateDecls.find(VD);
8519 if (I != FirstPrivateDecls.end() &&
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008520 VD->getType().isConstant(CGF.getContext())) {
8521 llvm::Constant *Addr =
8522 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD);
8523 // Copy the value of the original variable to the new global copy.
8524 CGF.Builder.CreateMemCpy(
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08008525 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(),
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008526 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)),
Rui Ueyama49a3ad22019-07-16 04:46:31 +00008527 CurSizes.back(), /*IsVolatile=*/false);
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008528 // Use new global variable as the base pointers.
8529 CurBasePointers.push_back(Addr);
8530 CurPointers.push_back(Addr);
8531 } else {
8532 CurBasePointers.push_back(CV);
Alexey Bataevf288cf92019-06-27 18:53:07 +00008533 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) {
Alexey Bataevc2b831f2019-04-02 16:03:40 +00008534 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue(
8535 CV, ElementType, CGF.getContext().getDeclAlign(VD),
8536 AlignmentSource::Decl));
8537 CurPointers.push_back(PtrAddr.getPointer());
8538 } else {
8539 CurPointers.push_back(CV);
8540 }
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008541 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008542 if (I != FirstPrivateDecls.end())
8543 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008544 }
George Rokos065755d2017-11-07 18:27:04 +00008545 // Every default map produces a single argument which is a target parameter.
8546 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM;
Alexey Bataevb3638132018-07-19 16:34:13 +00008547
8548 // Add flag stating this is an implicit map.
Alexey Bataevf288cf92019-06-27 18:53:07 +00008549 if (IsImplicit)
8550 CurMapTypes.back() |= OMP_MAP_IMPLICIT;
Samuel Antaod486f842016-05-26 16:53:38 +00008551 }
Samuel Antao86ace552016-04-27 22:40:57 +00008552};
Samuel Antaodf158d52016-04-27 22:58:19 +00008553} // anonymous namespace
8554
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008555/// Emit the arrays used to pass the captures and map information to the
Samuel Antaodf158d52016-04-27 22:58:19 +00008556/// offloading runtime library. If there is no map or capture information,
8557/// return nullptr by reference.
8558static void
Samuel Antaocc10b852016-07-28 14:23:26 +00008559emitOffloadingArrays(CodeGenFunction &CGF,
8560 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers,
Samuel Antaodf158d52016-04-27 22:58:19 +00008561 MappableExprsHandler::MapValuesArrayTy &Pointers,
8562 MappableExprsHandler::MapValuesArrayTy &Sizes,
Samuel Antaocc10b852016-07-28 14:23:26 +00008563 MappableExprsHandler::MapFlagsArrayTy &MapTypes,
8564 CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008565 CodeGenModule &CGM = CGF.CGM;
8566 ASTContext &Ctx = CGF.getContext();
Samuel Antaodf158d52016-04-27 22:58:19 +00008567
Samuel Antaocc10b852016-07-28 14:23:26 +00008568 // Reset the array information.
8569 Info.clearArrayInfo();
8570 Info.NumberOfPtrs = BasePointers.size();
Samuel Antaodf158d52016-04-27 22:58:19 +00008571
Samuel Antaocc10b852016-07-28 14:23:26 +00008572 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008573 // Detect if we have any capture size requiring runtime evaluation of the
8574 // size so that a constant array could be eventually used.
8575 bool hasRuntimeEvaluationCaptureSize = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008576 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008577 if (!isa<llvm::Constant>(S)) {
8578 hasRuntimeEvaluationCaptureSize = true;
8579 break;
8580 }
8581
Samuel Antaocc10b852016-07-28 14:23:26 +00008582 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true);
Richard Smith772e2662019-10-04 01:25:59 +00008583 QualType PointerArrayType = Ctx.getConstantArrayType(
8584 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal,
8585 /*IndexTypeQuals=*/0);
Samuel Antaodf158d52016-04-27 22:58:19 +00008586
Samuel Antaocc10b852016-07-28 14:23:26 +00008587 Info.BasePointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008588 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
Samuel Antaocc10b852016-07-28 14:23:26 +00008589 Info.PointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008590 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
8591
8592 // If we don't have any VLA types or other types that require runtime
8593 // evaluation, we can use a constant array for the map sizes, otherwise we
8594 // need to fill up the arrays as we do for the pointers.
Alexey Bataeva90fc662019-06-25 16:00:43 +00008595 QualType Int64Ty =
8596 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Samuel Antaodf158d52016-04-27 22:58:19 +00008597 if (hasRuntimeEvaluationCaptureSize) {
Richard Smith772e2662019-10-04 01:25:59 +00008598 QualType SizeArrayType = Ctx.getConstantArrayType(
8599 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal,
8600 /*IndexTypeQuals=*/0);
Samuel Antaocc10b852016-07-28 14:23:26 +00008601 Info.SizesArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008602 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
8603 } else {
8604 // We expect all the sizes to be constant, so we collect them to create
8605 // a constant array.
8606 SmallVector<llvm::Constant *, 16> ConstSizes;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008607 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008608 ConstSizes.push_back(cast<llvm::Constant>(S));
8609
8610 auto *SizesArrayInit = llvm::ConstantArray::get(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008611 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008612 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008613 auto *SizesArrayGbl = new llvm::GlobalVariable(
8614 CGM.getModule(), SizesArrayInit->getType(),
8615 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008616 SizesArrayInit, Name);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008617 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008618 Info.SizesArray = SizesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008619 }
8620
8621 // The map types are always constant so we don't need to generate code to
8622 // fill arrays. Instead, we create an array constant.
Alexey Bataevb3638132018-07-19 16:34:13 +00008623 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0);
8624 llvm::copy(MapTypes, Mapping.begin());
Samuel Antaodf158d52016-04-27 22:58:19 +00008625 llvm::Constant *MapTypesArrayInit =
Alexey Bataevb3638132018-07-19 16:34:13 +00008626 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008627 std::string MaptypesName =
8628 CGM.getOpenMPRuntime().getName({"offload_maptypes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008629 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
8630 CGM.getModule(), MapTypesArrayInit->getType(),
8631 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008632 MapTypesArrayInit, MaptypesName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008633 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008634 Info.MapTypesArray = MapTypesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008635
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008636 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) {
8637 llvm::Value *BPVal = *BasePointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008638 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008639 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008640 Info.BasePointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008641 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8642 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008643 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8644 CGF.Builder.CreateStore(BPVal, BPAddr);
8645
Samuel Antaocc10b852016-07-28 14:23:26 +00008646 if (Info.requiresDevicePointerInfo())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008647 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl())
Alexey Bataev43a919f2018-04-13 17:48:43 +00008648 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr);
Samuel Antaocc10b852016-07-28 14:23:26 +00008649
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008650 llvm::Value *PVal = Pointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008651 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008652 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008653 Info.PointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008654 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8655 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008656 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8657 CGF.Builder.CreateStore(PVal, PAddr);
8658
8659 if (hasRuntimeEvaluationCaptureSize) {
8660 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008661 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008662 Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008663 /*Idx0=*/0,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008664 /*Idx1=*/I);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008665 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty));
Samuel Antaodf158d52016-04-27 22:58:19 +00008666 CGF.Builder.CreateStore(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008667 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true),
Samuel Antaodf158d52016-04-27 22:58:19 +00008668 SAddr);
8669 }
8670 }
8671 }
8672}
Michael Krused47b9432019-08-05 18:43:21 +00008673
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008674/// Emit the arguments to be passed to the runtime library based on the
Samuel Antaodf158d52016-04-27 22:58:19 +00008675/// arrays of pointers, sizes and map types.
8676static void emitOffloadingArraysArgument(
8677 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg,
8678 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008679 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008680 CodeGenModule &CGM = CGF.CGM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008681 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008682 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008683 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8684 Info.BasePointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008685 /*Idx0=*/0, /*Idx1=*/0);
8686 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008687 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8688 Info.PointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008689 /*Idx0=*/0,
8690 /*Idx1=*/0);
8691 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008692 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008693 /*Idx0=*/0, /*Idx1=*/0);
8694 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
George Rokos63bc9d62017-11-21 18:25:12 +00008695 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008696 Info.MapTypesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008697 /*Idx0=*/0,
8698 /*Idx1=*/0);
8699 } else {
8700 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
8701 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008702 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008703 MapTypesArrayArg =
George Rokos63bc9d62017-11-21 18:25:12 +00008704 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008705 }
Samuel Antao86ace552016-04-27 22:40:57 +00008706}
8707
Alexey Bataev7bb33532019-01-07 21:30:43 +00008708/// Check for inner distribute directive.
8709static const OMPExecutableDirective *
8710getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
8711 const auto *CS = D.getInnermostCapturedStmt();
8712 const auto *Body =
8713 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00008714 const Stmt *ChildStmt =
8715 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
Alexey Bataev7bb33532019-01-07 21:30:43 +00008716
Alexey Bataev5c427362019-04-10 19:11:33 +00008717 if (const auto *NestedDir =
8718 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008719 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind();
8720 switch (D.getDirectiveKind()) {
8721 case OMPD_target:
8722 if (isOpenMPDistributeDirective(DKind))
8723 return NestedDir;
8724 if (DKind == OMPD_teams) {
8725 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
8726 /*IgnoreCaptured=*/true);
8727 if (!Body)
8728 return nullptr;
Alexey Bataev5c427362019-04-10 19:11:33 +00008729 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
8730 if (const auto *NND =
8731 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008732 DKind = NND->getDirectiveKind();
8733 if (isOpenMPDistributeDirective(DKind))
8734 return NND;
8735 }
8736 }
8737 return nullptr;
8738 case OMPD_target_teams:
8739 if (isOpenMPDistributeDirective(DKind))
8740 return NestedDir;
8741 return nullptr;
8742 case OMPD_target_parallel:
8743 case OMPD_target_simd:
8744 case OMPD_target_parallel_for:
8745 case OMPD_target_parallel_for_simd:
8746 return nullptr;
8747 case OMPD_target_teams_distribute:
8748 case OMPD_target_teams_distribute_simd:
8749 case OMPD_target_teams_distribute_parallel_for:
8750 case OMPD_target_teams_distribute_parallel_for_simd:
8751 case OMPD_parallel:
8752 case OMPD_for:
8753 case OMPD_parallel_for:
8754 case OMPD_parallel_sections:
8755 case OMPD_for_simd:
8756 case OMPD_parallel_for_simd:
8757 case OMPD_cancel:
8758 case OMPD_cancellation_point:
8759 case OMPD_ordered:
8760 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00008761 case OMPD_allocate:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008762 case OMPD_task:
8763 case OMPD_simd:
8764 case OMPD_sections:
8765 case OMPD_section:
8766 case OMPD_single:
8767 case OMPD_master:
8768 case OMPD_critical:
8769 case OMPD_taskyield:
8770 case OMPD_barrier:
8771 case OMPD_taskwait:
8772 case OMPD_taskgroup:
8773 case OMPD_atomic:
8774 case OMPD_flush:
8775 case OMPD_teams:
8776 case OMPD_target_data:
8777 case OMPD_target_exit_data:
8778 case OMPD_target_enter_data:
8779 case OMPD_distribute:
8780 case OMPD_distribute_simd:
8781 case OMPD_distribute_parallel_for:
8782 case OMPD_distribute_parallel_for_simd:
8783 case OMPD_teams_distribute:
8784 case OMPD_teams_distribute_simd:
8785 case OMPD_teams_distribute_parallel_for:
8786 case OMPD_teams_distribute_parallel_for_simd:
8787 case OMPD_target_update:
8788 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00008789 case OMPD_declare_variant:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008790 case OMPD_declare_target:
8791 case OMPD_end_declare_target:
8792 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00008793 case OMPD_declare_mapper:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008794 case OMPD_taskloop:
8795 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00008796 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00008797 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00008798 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04008799 case OMPD_parallel_master_taskloop_simd:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008800 case OMPD_requires:
8801 case OMPD_unknown:
8802 llvm_unreachable("Unexpected directive.");
8803 }
8804 }
8805
8806 return nullptr;
8807}
8808
Michael Krused47b9432019-08-05 18:43:21 +00008809/// Emit the user-defined mapper function. The code generation follows the
8810/// pattern in the example below.
8811/// \code
8812/// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle,
8813/// void *base, void *begin,
8814/// int64_t size, int64_t type) {
8815/// // Allocate space for an array section first.
8816/// if (size > 1 && !maptype.IsDelete)
8817/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
8818/// size*sizeof(Ty), clearToFrom(type));
8819/// // Map members.
8820/// for (unsigned i = 0; i < size; i++) {
8821/// // For each component specified by this mapper:
8822/// for (auto c : all_components) {
8823/// if (c.hasMapper())
8824/// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size,
8825/// c.arg_type);
8826/// else
8827/// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base,
8828/// c.arg_begin, c.arg_size, c.arg_type);
8829/// }
8830/// }
8831/// // Delete the array section.
8832/// if (size > 1 && maptype.IsDelete)
8833/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
8834/// size*sizeof(Ty), clearToFrom(type));
8835/// }
8836/// \endcode
8837void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D,
8838 CodeGenFunction *CGF) {
8839 if (UDMMap.count(D) > 0)
8840 return;
8841 ASTContext &C = CGM.getContext();
8842 QualType Ty = D->getType();
8843 QualType PtrTy = C.getPointerType(Ty).withRestrict();
8844 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
8845 auto *MapperVarDecl =
8846 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl());
8847 SourceLocation Loc = D->getLocation();
8848 CharUnits ElementSize = C.getTypeSizeInChars(Ty);
8849
8850 // Prepare mapper function arguments and attributes.
8851 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
8852 C.VoidPtrTy, ImplicitParamDecl::Other);
8853 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
8854 ImplicitParamDecl::Other);
8855 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
8856 C.VoidPtrTy, ImplicitParamDecl::Other);
8857 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
8858 ImplicitParamDecl::Other);
8859 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
8860 ImplicitParamDecl::Other);
8861 FunctionArgList Args;
8862 Args.push_back(&HandleArg);
8863 Args.push_back(&BaseArg);
8864 Args.push_back(&BeginArg);
8865 Args.push_back(&SizeArg);
8866 Args.push_back(&TypeArg);
8867 const CGFunctionInfo &FnInfo =
8868 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
8869 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
8870 SmallString<64> TyStr;
8871 llvm::raw_svector_ostream Out(TyStr);
8872 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out);
8873 std::string Name = getName({"omp_mapper", TyStr, D->getName()});
8874 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
8875 Name, &CGM.getModule());
8876 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
8877 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
8878 // Start the mapper function code generation.
8879 CodeGenFunction MapperCGF(CGM);
8880 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
8881 // Compute the starting and end addreses of array elements.
8882 llvm::Value *Size = MapperCGF.EmitLoadOfScalar(
8883 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false,
8884 C.getPointerType(Int64Ty), Loc);
8885 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast(
8886 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(),
8887 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy)));
8888 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size);
8889 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar(
8890 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false,
8891 C.getPointerType(Int64Ty), Loc);
8892 // Prepare common arguments for array initiation and deletion.
8893 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar(
8894 MapperCGF.GetAddrOfLocalVar(&HandleArg),
8895 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8896 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar(
8897 MapperCGF.GetAddrOfLocalVar(&BaseArg),
8898 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8899 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar(
8900 MapperCGF.GetAddrOfLocalVar(&BeginArg),
8901 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8902
8903 // Emit array initiation if this is an array section and \p MapType indicates
8904 // that memory allocation is required.
8905 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head");
8906 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
8907 ElementSize, HeadBB, /*IsInit=*/true);
8908
8909 // Emit a for loop to iterate through SizeArg of elements and map all of them.
8910
8911 // Emit the loop header block.
8912 MapperCGF.EmitBlock(HeadBB);
8913 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body");
8914 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done");
8915 // Evaluate whether the initial condition is satisfied.
8916 llvm::Value *IsEmpty =
8917 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty");
8918 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
8919 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock();
8920
8921 // Emit the loop body block.
8922 MapperCGF.EmitBlock(BodyBB);
8923 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI(
8924 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent");
8925 PtrPHI->addIncoming(PtrBegin, EntryBB);
8926 Address PtrCurrent =
8927 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg)
8928 .getAlignment()
8929 .alignmentOfArrayElement(ElementSize));
8930 // Privatize the declared variable of mapper to be the current array element.
8931 CodeGenFunction::OMPPrivateScope Scope(MapperCGF);
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08008932 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() {
Michael Krused47b9432019-08-05 18:43:21 +00008933 return MapperCGF
8934 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>())
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08008935 .getAddress();
Michael Krused47b9432019-08-05 18:43:21 +00008936 });
8937 (void)Scope.Privatize();
8938
8939 // Get map clause information. Fill up the arrays with all mapped variables.
8940 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
8941 MappableExprsHandler::MapValuesArrayTy Pointers;
8942 MappableExprsHandler::MapValuesArrayTy Sizes;
8943 MappableExprsHandler::MapFlagsArrayTy MapTypes;
8944 MappableExprsHandler MEHandler(*D, MapperCGF);
8945 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes);
8946
8947 // Call the runtime API __tgt_mapper_num_components to get the number of
8948 // pre-existing components.
8949 llvm::Value *OffloadingArgs[] = {Handle};
8950 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall(
8951 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs);
8952 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl(
8953 PreviousSize,
8954 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset()));
8955
8956 // Fill up the runtime mapper handle for all components.
8957 for (unsigned I = 0; I < BasePointers.size(); ++I) {
8958 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast(
8959 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
8960 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast(
8961 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
8962 llvm::Value *CurSizeArg = Sizes[I];
8963
8964 // Extract the MEMBER_OF field from the map type.
8965 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member");
8966 MapperCGF.EmitBlock(MemberBB);
8967 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]);
8968 llvm::Value *Member = MapperCGF.Builder.CreateAnd(
8969 OriMapType,
8970 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF));
8971 llvm::BasicBlock *MemberCombineBB =
8972 MapperCGF.createBasicBlock("omp.member.combine");
8973 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type");
8974 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member);
8975 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB);
8976 // Add the number of pre-existing components to the MEMBER_OF field if it
8977 // is valid.
8978 MapperCGF.EmitBlock(MemberCombineBB);
8979 llvm::Value *CombinedMember =
8980 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
8981 // Do nothing if it is not a member of previous components.
8982 MapperCGF.EmitBlock(TypeBB);
8983 llvm::PHINode *MemberMapType =
8984 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype");
8985 MemberMapType->addIncoming(OriMapType, MemberBB);
8986 MemberMapType->addIncoming(CombinedMember, MemberCombineBB);
8987
8988 // Combine the map type inherited from user-defined mapper with that
8989 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM
8990 // bits of the \a MapType, which is the input argument of the mapper
8991 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM
8992 // bits of MemberMapType.
8993 // [OpenMP 5.0], 1.2.6. map-type decay.
8994 // | alloc | to | from | tofrom | release | delete
8995 // ----------------------------------------------------------
8996 // alloc | alloc | alloc | alloc | alloc | release | delete
8997 // to | alloc | to | alloc | to | release | delete
8998 // from | alloc | alloc | from | from | release | delete
8999 // tofrom | alloc | to | from | tofrom | release | delete
9000 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd(
9001 MapType,
9002 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO |
9003 MappableExprsHandler::OMP_MAP_FROM));
9004 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc");
9005 llvm::BasicBlock *AllocElseBB =
9006 MapperCGF.createBasicBlock("omp.type.alloc.else");
9007 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to");
9008 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else");
9009 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from");
9010 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end");
9011 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom);
9012 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
9013 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM.
9014 MapperCGF.EmitBlock(AllocBB);
9015 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd(
9016 MemberMapType,
9017 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9018 MappableExprsHandler::OMP_MAP_FROM)));
9019 MapperCGF.Builder.CreateBr(EndBB);
9020 MapperCGF.EmitBlock(AllocElseBB);
9021 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ(
9022 LeftToFrom,
9023 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO));
9024 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
9025 // In case of to, clear OMP_MAP_FROM.
9026 MapperCGF.EmitBlock(ToBB);
9027 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd(
9028 MemberMapType,
9029 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM));
9030 MapperCGF.Builder.CreateBr(EndBB);
9031 MapperCGF.EmitBlock(ToElseBB);
9032 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ(
9033 LeftToFrom,
9034 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM));
9035 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB);
9036 // In case of from, clear OMP_MAP_TO.
9037 MapperCGF.EmitBlock(FromBB);
9038 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd(
9039 MemberMapType,
9040 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO));
9041 // In case of tofrom, do nothing.
9042 MapperCGF.EmitBlock(EndBB);
9043 llvm::PHINode *CurMapType =
9044 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype");
9045 CurMapType->addIncoming(AllocMapType, AllocBB);
9046 CurMapType->addIncoming(ToMapType, ToBB);
9047 CurMapType->addIncoming(FromMapType, FromBB);
9048 CurMapType->addIncoming(MemberMapType, ToElseBB);
9049
9050 // TODO: call the corresponding mapper function if a user-defined mapper is
9051 // associated with this map clause.
9052 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9053 // data structure.
9054 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg,
9055 CurSizeArg, CurMapType};
9056 MapperCGF.EmitRuntimeCall(
9057 createRuntimeFunction(OMPRTL__tgt_push_mapper_component),
9058 OffloadingArgs);
9059 }
9060
9061 // Update the pointer to point to the next element that needs to be mapped,
9062 // and check whether we have mapped all elements.
9063 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32(
9064 PtrPHI, /*Idx0=*/1, "omp.arraymap.next");
9065 PtrPHI->addIncoming(PtrNext, BodyBB);
9066 llvm::Value *IsDone =
9067 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone");
9068 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit");
9069 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
9070
9071 MapperCGF.EmitBlock(ExitBB);
9072 // Emit array deletion if this is an array section and \p MapType indicates
9073 // that deletion is required.
9074 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
9075 ElementSize, DoneBB, /*IsInit=*/false);
9076
9077 // Emit the function exit block.
9078 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true);
9079 MapperCGF.FinishFunction();
9080 UDMMap.try_emplace(D, Fn);
9081 if (CGF) {
9082 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn);
9083 Decls.second.push_back(D);
9084 }
9085}
9086
9087/// Emit the array initialization or deletion portion for user-defined mapper
9088/// code generation. First, it evaluates whether an array section is mapped and
9089/// whether the \a MapType instructs to delete this section. If \a IsInit is
9090/// true, and \a MapType indicates to not delete this array, array
9091/// initialization code is generated. If \a IsInit is false, and \a MapType
9092/// indicates to not this array, array deletion code is generated.
9093void CGOpenMPRuntime::emitUDMapperArrayInitOrDel(
9094 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base,
9095 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType,
9096 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) {
9097 StringRef Prefix = IsInit ? ".init" : ".del";
9098
9099 // Evaluate if this is an array section.
9100 llvm::BasicBlock *IsDeleteBB =
9101 MapperCGF.createBasicBlock("omp.array" + Prefix + ".evaldelete");
9102 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.array" + Prefix);
9103 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE(
9104 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray");
9105 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB);
9106
9107 // Evaluate if we are going to delete this section.
9108 MapperCGF.EmitBlock(IsDeleteBB);
9109 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd(
9110 MapType,
9111 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE));
9112 llvm::Value *DeleteCond;
9113 if (IsInit) {
9114 DeleteCond = MapperCGF.Builder.CreateIsNull(
9115 DeleteBit, "omp.array" + Prefix + ".delete");
9116 } else {
9117 DeleteCond = MapperCGF.Builder.CreateIsNotNull(
9118 DeleteBit, "omp.array" + Prefix + ".delete");
9119 }
9120 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB);
9121
9122 MapperCGF.EmitBlock(BodyBB);
9123 // Get the array size by multiplying element size and element number (i.e., \p
9124 // Size).
9125 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul(
9126 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
9127 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves
9128 // memory allocation/deletion purpose only.
9129 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd(
9130 MapType,
9131 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9132 MappableExprsHandler::OMP_MAP_FROM)));
9133 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9134 // data structure.
9135 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg};
9136 MapperCGF.EmitRuntimeCall(
9137 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs);
9138}
9139
Alexey Bataev7bb33532019-01-07 21:30:43 +00009140void CGOpenMPRuntime::emitTargetNumIterationsCall(
Alexey Bataevec7946e2019-09-23 14:06:51 +00009141 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9142 llvm::Value *DeviceID,
9143 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9144 const OMPLoopDirective &D)>
9145 SizeEmitter) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00009146 OpenMPDirectiveKind Kind = D.getDirectiveKind();
9147 const OMPExecutableDirective *TD = &D;
9148 // Get nested teams distribute kind directive, if any.
9149 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind))
9150 TD = getNestedDistributeDirective(CGM.getContext(), D);
9151 if (!TD)
9152 return;
9153 const auto *LD = cast<OMPLoopDirective>(TD);
Alexey Bataevec7946e2019-09-23 14:06:51 +00009154 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF,
Alexey Bataev7bb33532019-01-07 21:30:43 +00009155 PrePostActionTy &) {
Alexey Bataevec7946e2019-09-23 14:06:51 +00009156 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) {
9157 llvm::Value *Args[] = {DeviceID, NumIterations};
9158 CGF.EmitRuntimeCall(
9159 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args);
9160 }
Alexey Bataev7bb33532019-01-07 21:30:43 +00009161 };
9162 emitInlinedDirective(CGF, OMPD_unknown, CodeGen);
9163}
9164
Alexey Bataevec7946e2019-09-23 14:06:51 +00009165void CGOpenMPRuntime::emitTargetCall(
9166 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9167 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
9168 const Expr *Device,
9169 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9170 const OMPLoopDirective &D)>
9171 SizeEmitter) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00009172 if (!CGF.HaveInsertPoint())
9173 return;
Samuel Antaobed3c462015-10-02 16:14:20 +00009174
Samuel Antaoee8fb302016-01-06 13:42:12 +00009175 assert(OutlinedFn && "Invalid outlined function!");
9176
Alexey Bataev8451efa2018-01-15 19:06:12 +00009177 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>();
9178 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
Alexey Bataev475a7442018-01-12 19:39:11 +00009179 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009180 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF,
9181 PrePostActionTy &) {
9182 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9183 };
9184 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen);
Samuel Antao86ace552016-04-27 22:40:57 +00009185
Alexey Bataev8451efa2018-01-15 19:06:12 +00009186 CodeGenFunction::OMPTargetDataInfo InputInfo;
9187 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobed3c462015-10-02 16:14:20 +00009188 // Fill up the pointer arrays and transfer execution to the device.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009189 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo,
Alexey Bataevec7946e2019-09-23 14:06:51 +00009190 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars,
9191 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobed3c462015-10-02 16:14:20 +00009192 // On top of the arrays that were filled up, the target offloading call
9193 // takes as arguments the device id as well as the host pointer. The host
9194 // pointer is used by the runtime library to identify the current target
9195 // region, so it only has to be unique and not necessarily point to
9196 // anything. It could be the pointer to the outlined function that
9197 // implements the target region, but we aren't using that so that the
9198 // compiler doesn't need to keep that, and could therefore inline the host
9199 // function if proven worthwhile during optimization.
9200
Samuel Antaoee8fb302016-01-06 13:42:12 +00009201 // From this point on, we need to have an ID of the target region defined.
9202 assert(OutlinedFnID && "Invalid outlined function ID!");
Samuel Antaobed3c462015-10-02 16:14:20 +00009203
9204 // Emit device ID if any.
9205 llvm::Value *DeviceID;
George Rokos63bc9d62017-11-21 18:25:12 +00009206 if (Device) {
Samuel Antaobed3c462015-10-02 16:14:20 +00009207 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009208 CGF.Int64Ty, /*isSigned=*/true);
9209 } else {
9210 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9211 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009212
Samuel Antaodf158d52016-04-27 22:58:19 +00009213 // Emit the number of elements in the offloading arrays.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009214 llvm::Value *PointerNum =
9215 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaodf158d52016-04-27 22:58:19 +00009216
Samuel Antaob68e2db2016-03-03 16:20:23 +00009217 // Return value of the runtime offloading call.
9218 llvm::Value *Return;
9219
Alexey Bataev5c427362019-04-10 19:11:33 +00009220 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D);
9221 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009222
Alexey Bataevec7946e2019-09-23 14:06:51 +00009223 // Emit tripcount for the target loop-based directive.
9224 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter);
9225
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009226 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00009227 // The target region is an outlined function launched by the runtime
9228 // via calls __tgt_target() or __tgt_target_teams().
9229 //
9230 // __tgt_target() launches a target region with one team and one thread,
9231 // executing a serial region. This master thread may in turn launch
9232 // more threads within its team upon encountering a parallel region,
9233 // however, no additional teams can be launched on the device.
9234 //
9235 // __tgt_target_teams() launches a target region with one or more teams,
9236 // each with one or more threads. This call is required for target
9237 // constructs such as:
9238 // 'target teams'
9239 // 'target' / 'teams'
9240 // 'target teams distribute parallel for'
9241 // 'target parallel'
9242 // and so on.
9243 //
9244 // Note that on the host and CPU targets, the runtime implementation of
9245 // these calls simply call the outlined function without forking threads.
9246 // The outlined functions themselves have runtime calls to
9247 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by
9248 // the compiler in emitTeamsCall() and emitParallelCall().
9249 //
9250 // In contrast, on the NVPTX target, the implementation of
9251 // __tgt_target_teams() launches a GPU kernel with the requested number
9252 // of teams and threads so no additional calls to the runtime are required.
Samuel Antaob68e2db2016-03-03 16:20:23 +00009253 if (NumTeams) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00009254 // If we have NumTeams defined this means that we have an enclosed teams
9255 // region. Therefore we also expect to have NumThreads defined. These two
9256 // values should be defined in the presence of a teams directive,
9257 // regardless of having any clauses associated. If the user is using teams
9258 // but no clauses, these two values will be the default that should be
9259 // passed to the runtime library - a 32-bit integer with the value zero.
9260 assert(NumThreads && "Thread limit expression should be available along "
9261 "with number of teams.");
Alexey Bataev8451efa2018-01-15 19:06:12 +00009262 llvm::Value *OffloadingArgs[] = {DeviceID,
9263 OutlinedFnID,
9264 PointerNum,
9265 InputInfo.BasePointersArray.getPointer(),
9266 InputInfo.PointersArray.getPointer(),
9267 InputInfo.SizesArray.getPointer(),
9268 MapTypesArray,
9269 NumTeams,
9270 NumThreads};
Samuel Antaob68e2db2016-03-03 16:20:23 +00009271 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00009272 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait
9273 : OMPRTL__tgt_target_teams),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009274 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009275 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009276 llvm::Value *OffloadingArgs[] = {DeviceID,
9277 OutlinedFnID,
9278 PointerNum,
9279 InputInfo.BasePointersArray.getPointer(),
9280 InputInfo.PointersArray.getPointer(),
9281 InputInfo.SizesArray.getPointer(),
9282 MapTypesArray};
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009283 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00009284 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait
9285 : OMPRTL__tgt_target),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009286 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009287 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009288
Alexey Bataev2a007e02017-10-02 14:20:58 +00009289 // Check the error code and execute the host version if required.
9290 llvm::BasicBlock *OffloadFailedBlock =
9291 CGF.createBasicBlock("omp_offload.failed");
9292 llvm::BasicBlock *OffloadContBlock =
9293 CGF.createBasicBlock("omp_offload.cont");
9294 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return);
9295 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
9296
9297 CGF.EmitBlock(OffloadFailedBlock);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009298 if (RequiresOuterTask) {
9299 CapturedVars.clear();
9300 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9301 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009302 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev2a007e02017-10-02 14:20:58 +00009303 CGF.EmitBranch(OffloadContBlock);
9304
9305 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00009306 };
9307
Samuel Antaoee8fb302016-01-06 13:42:12 +00009308 // Notify that the host version must be executed.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009309 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars,
9310 RequiresOuterTask](CodeGenFunction &CGF,
9311 PrePostActionTy &) {
9312 if (RequiresOuterTask) {
9313 CapturedVars.clear();
9314 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9315 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009316 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009317 };
9318
9319 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray,
9320 &CapturedVars, RequiresOuterTask,
9321 &CS](CodeGenFunction &CGF, PrePostActionTy &) {
9322 // Fill up the arrays with all the captured variables.
9323 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
9324 MappableExprsHandler::MapValuesArrayTy Pointers;
9325 MappableExprsHandler::MapValuesArrayTy Sizes;
9326 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9327
Alexey Bataev8451efa2018-01-15 19:06:12 +00009328 // Get mappable expression information.
9329 MappableExprsHandler MEHandler(D, CGF);
Alexey Bataev969dbc02018-11-08 15:47:39 +00009330 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
Alexey Bataev8451efa2018-01-15 19:06:12 +00009331
9332 auto RI = CS.getCapturedRecordDecl()->field_begin();
9333 auto CV = CapturedVars.begin();
9334 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
9335 CE = CS.capture_end();
9336 CI != CE; ++CI, ++RI, ++CV) {
Alexey Bataevb3638132018-07-19 16:34:13 +00009337 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers;
9338 MappableExprsHandler::MapValuesArrayTy CurPointers;
9339 MappableExprsHandler::MapValuesArrayTy CurSizes;
9340 MappableExprsHandler::MapFlagsArrayTy CurMapTypes;
9341 MappableExprsHandler::StructRangeInfoTy PartialStruct;
Alexey Bataev8451efa2018-01-15 19:06:12 +00009342
9343 // VLA sizes are passed to the outlined region by copy and do not have map
9344 // information associated.
9345 if (CI->capturesVariableArrayType()) {
9346 CurBasePointers.push_back(*CV);
9347 CurPointers.push_back(*CV);
Alexey Bataeva90fc662019-06-25 16:00:43 +00009348 CurSizes.push_back(CGF.Builder.CreateIntCast(
9349 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev8451efa2018-01-15 19:06:12 +00009350 // Copy to the device as an argument. No need to retrieve it.
9351 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL |
Alexey Bataevf288cf92019-06-27 18:53:07 +00009352 MappableExprsHandler::OMP_MAP_TARGET_PARAM |
9353 MappableExprsHandler::OMP_MAP_IMPLICIT);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009354 } else {
9355 // If we have any information in the map clause, we use it, otherwise we
9356 // just do a default mapping.
9357 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00009358 CurSizes, CurMapTypes, PartialStruct);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009359 if (CurBasePointers.empty())
9360 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers,
9361 CurPointers, CurSizes, CurMapTypes);
Alexey Bataev60705422018-10-30 15:50:12 +00009362 // Generate correct mapping for variables captured by reference in
9363 // lambdas.
9364 if (CI->capturesVariable())
Alexey Bataev969dbc02018-11-08 15:47:39 +00009365 MEHandler.generateInfoForLambdaCaptures(
9366 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes,
9367 CurMapTypes, LambdaPointers);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009368 }
9369 // We expect to have at least an element of information for this capture.
9370 assert(!CurBasePointers.empty() &&
9371 "Non-existing map pointer for capture!");
9372 assert(CurBasePointers.size() == CurPointers.size() &&
9373 CurBasePointers.size() == CurSizes.size() &&
9374 CurBasePointers.size() == CurMapTypes.size() &&
9375 "Inconsistent map information sizes!");
9376
Alexey Bataevb3638132018-07-19 16:34:13 +00009377 // If there is an entry in PartialStruct it means we have a struct with
9378 // individual members mapped. Emit an extra combined entry.
9379 if (PartialStruct.Base.isValid())
9380 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes,
9381 CurMapTypes, PartialStruct);
9382
Alexey Bataev8451efa2018-01-15 19:06:12 +00009383 // We need to append the results of this capture to what we already have.
9384 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
9385 Pointers.append(CurPointers.begin(), CurPointers.end());
9386 Sizes.append(CurSizes.begin(), CurSizes.end());
9387 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end());
9388 }
Alexey Bataev60705422018-10-30 15:50:12 +00009389 // Adjust MEMBER_OF flags for the lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00009390 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers,
9391 Pointers, MapTypes);
Alexey Bataev92327c52018-03-26 16:40:55 +00009392 // Map other list items in the map clause which are not captured variables
9393 // but "declare target link" global variables.
Alexey Bataevb3638132018-07-19 16:34:13 +00009394 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes,
9395 MapTypes);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009396
9397 TargetDataInfo Info;
9398 // Fill up the arrays and create the arguments.
9399 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
9400 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
9401 Info.PointersArray, Info.SizesArray,
9402 Info.MapTypesArray, Info);
9403 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
9404 InputInfo.BasePointersArray =
9405 Address(Info.BasePointersArray, CGM.getPointerAlign());
9406 InputInfo.PointersArray =
9407 Address(Info.PointersArray, CGM.getPointerAlign());
9408 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign());
9409 MapTypesArray = Info.MapTypesArray;
9410 if (RequiresOuterTask)
9411 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
9412 else
9413 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
9414 };
9415
9416 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask](
9417 CodeGenFunction &CGF, PrePostActionTy &) {
9418 if (RequiresOuterTask) {
9419 CodeGenFunction::OMPTargetDataInfo InputInfo;
9420 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo);
9421 } else {
9422 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen);
9423 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009424 };
9425
9426 // If we have a target function ID it means that we need to support
9427 // offloading, otherwise, just execute on the host. We need to execute on host
9428 // regardless of the conditional in the if clause if, e.g., the user do not
9429 // specify target triples.
9430 if (OutlinedFnID) {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009431 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -05009432 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009433 } else {
9434 RegionCodeGenTy ThenRCG(TargetThenGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00009435 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00009436 }
9437 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009438 RegionCodeGenTy ElseRCG(TargetElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00009439 ElseRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00009440 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009441}
Samuel Antaoee8fb302016-01-06 13:42:12 +00009442
9443void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
9444 StringRef ParentName) {
9445 if (!S)
9446 return;
9447
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009448 // Codegen OMP target directives that offload compute to the device.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009449 bool RequiresDeviceCodegen =
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009450 isa<OMPExecutableDirective>(S) &&
9451 isOpenMPTargetExecutionDirective(
9452 cast<OMPExecutableDirective>(S)->getDirectiveKind());
Samuel Antaoee8fb302016-01-06 13:42:12 +00009453
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009454 if (RequiresDeviceCodegen) {
9455 const auto &E = *cast<OMPExecutableDirective>(S);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009456 unsigned DeviceID;
9457 unsigned FileID;
9458 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009459 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID,
Samuel Antao2de62b02016-02-13 23:35:10 +00009460 FileID, Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009461
9462 // Is this a target region that should not be emitted as an entry point? If
9463 // so just signal we are done with this target region.
Samuel Antao2de62b02016-02-13 23:35:10 +00009464 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
9465 ParentName, Line))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009466 return;
9467
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009468 switch (E.getDirectiveKind()) {
9469 case OMPD_target:
9470 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName,
9471 cast<OMPTargetDirective>(E));
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009472 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009473 case OMPD_target_parallel:
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009474 CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009475 CGM, ParentName, cast<OMPTargetParallelDirective>(E));
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009476 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009477 case OMPD_target_teams:
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009478 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009479 CGM, ParentName, cast<OMPTargetTeamsDirective>(E));
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009480 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009481 case OMPD_target_teams_distribute:
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009482 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009483 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E));
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009484 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009485 case OMPD_target_teams_distribute_simd:
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009486 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009487 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E));
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009488 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009489 case OMPD_target_parallel_for:
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009490 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009491 CGM, ParentName, cast<OMPTargetParallelForDirective>(E));
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009492 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009493 case OMPD_target_parallel_for_simd:
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009494 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009495 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E));
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009496 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009497 case OMPD_target_simd:
Alexey Bataevf8365372017-11-17 17:57:25 +00009498 CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009499 CGM, ParentName, cast<OMPTargetSimdDirective>(E));
Alexey Bataevf8365372017-11-17 17:57:25 +00009500 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009501 case OMPD_target_teams_distribute_parallel_for:
Carlo Bertolli52978c32018-01-03 21:12:44 +00009502 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
9503 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009504 cast<OMPTargetTeamsDistributeParallelForDirective>(E));
Carlo Bertolli52978c32018-01-03 21:12:44 +00009505 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009506 case OMPD_target_teams_distribute_parallel_for_simd:
Alexey Bataev647dd842018-01-15 20:59:40 +00009507 CodeGenFunction::
9508 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
9509 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009510 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E));
Alexey Bataev647dd842018-01-15 20:59:40 +00009511 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009512 case OMPD_parallel:
9513 case OMPD_for:
9514 case OMPD_parallel_for:
9515 case OMPD_parallel_sections:
9516 case OMPD_for_simd:
9517 case OMPD_parallel_for_simd:
9518 case OMPD_cancel:
9519 case OMPD_cancellation_point:
9520 case OMPD_ordered:
9521 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00009522 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009523 case OMPD_task:
9524 case OMPD_simd:
9525 case OMPD_sections:
9526 case OMPD_section:
9527 case OMPD_single:
9528 case OMPD_master:
9529 case OMPD_critical:
9530 case OMPD_taskyield:
9531 case OMPD_barrier:
9532 case OMPD_taskwait:
9533 case OMPD_taskgroup:
9534 case OMPD_atomic:
9535 case OMPD_flush:
9536 case OMPD_teams:
9537 case OMPD_target_data:
9538 case OMPD_target_exit_data:
9539 case OMPD_target_enter_data:
9540 case OMPD_distribute:
9541 case OMPD_distribute_simd:
9542 case OMPD_distribute_parallel_for:
9543 case OMPD_distribute_parallel_for_simd:
9544 case OMPD_teams_distribute:
9545 case OMPD_teams_distribute_simd:
9546 case OMPD_teams_distribute_parallel_for:
9547 case OMPD_teams_distribute_parallel_for_simd:
9548 case OMPD_target_update:
9549 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00009550 case OMPD_declare_variant:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009551 case OMPD_declare_target:
9552 case OMPD_end_declare_target:
9553 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00009554 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009555 case OMPD_taskloop:
9556 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00009557 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00009558 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00009559 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04009560 case OMPD_parallel_master_taskloop_simd:
Kelvin Li1408f912018-09-26 04:28:39 +00009561 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009562 case OMPD_unknown:
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009563 llvm_unreachable("Unknown target directive for OpenMP device codegen.");
9564 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009565 return;
9566 }
9567
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009568 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
Alexey Bataev475a7442018-01-12 19:39:11 +00009569 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009570 return;
9571
9572 scanForTargetRegionsFunctions(
Alexey Bataev475a7442018-01-12 19:39:11 +00009573 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009574 return;
9575 }
9576
9577 // If this is a lambda function, look into its body.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009578 if (const auto *L = dyn_cast<LambdaExpr>(S))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009579 S = L->getBody();
9580
9581 // Keep looking for target regions recursively.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009582 for (const Stmt *II : S->children())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009583 scanForTargetRegionsFunctions(II, ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009584}
9585
9586bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009587 // If emitting code for the host, we do not process FD here. Instead we do
9588 // the normal code generation.
Alexey Bataev729e2422019-08-23 16:11:14 +00009589 if (!CGM.getLangOpts().OpenMPIsDevice) {
9590 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) {
9591 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9592 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9593 // Do not emit device_type(nohost) functions for the host.
9594 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
9595 return true;
9596 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009597 return false;
Alexey Bataev729e2422019-08-23 16:11:14 +00009598 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009599
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009600 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009601 StringRef Name = CGM.getMangledName(GD);
9602 // Try to detect target regions in the function.
Alexey Bataev729e2422019-08-23 16:11:14 +00009603 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009604 scanForTargetRegionsFunctions(FD->getBody(), Name);
Alexey Bataev729e2422019-08-23 16:11:14 +00009605 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9606 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9607 // Do not emit device_type(nohost) functions for the host.
9608 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
9609 return true;
9610 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009611
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009612 // Do not to emit function if it is not marked as declare target.
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009613 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009614 AlreadyEmittedTargetFunctions.count(Name) == 0;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009615}
9616
9617bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
9618 if (!CGM.getLangOpts().OpenMPIsDevice)
9619 return false;
9620
9621 // Check if there are Ctors/Dtors in this declaration and look for target
9622 // regions in it. We use the complete variant to produce the kernel name
9623 // mangling.
9624 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009625 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
9626 for (const CXXConstructorDecl *Ctor : RD->ctors()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009627 StringRef ParentName =
9628 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
9629 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
9630 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009631 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009632 StringRef ParentName =
9633 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
9634 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
9635 }
9636 }
9637
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009638 // Do not to emit variable if it is not marked as declare target.
Alexey Bataev92327c52018-03-26 16:40:55 +00009639 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009640 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
9641 cast<VarDecl>(GD.getDecl()));
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009642 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
9643 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9644 HasRequiresUnifiedSharedMemory)) {
Alexey Bataevd01b7492018-08-15 19:45:12 +00009645 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009646 return true;
9647 }
9648 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009649}
9650
Alexey Bataev1af5bd52019-03-05 17:47:18 +00009651llvm::Constant *
9652CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF,
9653 const VarDecl *VD) {
9654 assert(VD->getType().isConstant(CGM.getContext()) &&
9655 "Expected constant variable.");
9656 StringRef VarName;
9657 llvm::Constant *Addr;
9658 llvm::GlobalValue::LinkageTypes Linkage;
9659 QualType Ty = VD->getType();
9660 SmallString<128> Buffer;
9661 {
9662 unsigned DeviceID;
9663 unsigned FileID;
9664 unsigned Line;
9665 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID,
9666 FileID, Line);
9667 llvm::raw_svector_ostream OS(Buffer);
9668 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID)
9669 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
9670 VarName = OS.str();
9671 }
9672 Linkage = llvm::GlobalValue::InternalLinkage;
9673 Addr =
9674 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName,
9675 getDefaultFirstprivateAddressSpace());
9676 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage);
9677 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty);
9678 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr));
9679 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9680 VarName, Addr, VarSize,
9681 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage);
9682 return Addr;
9683}
9684
Alexey Bataev03f270c2018-03-30 18:31:07 +00009685void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
9686 llvm::Constant *Addr) {
Alexey Bataev36724b72019-10-03 16:46:49 +00009687 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
9688 !CGM.getLangOpts().OpenMPIsDevice)
Alexey Bataev4db9dc62019-09-23 15:53:51 +00009689 return;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009690 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9691 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
9692 if (!Res) {
9693 if (CGM.getLangOpts().OpenMPIsDevice) {
9694 // Register non-target variables being emitted in device code (debug info
9695 // may cause this).
9696 StringRef VarName = CGM.getMangledName(VD);
9697 EmittedNonTargetVariables.try_emplace(VarName, Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009698 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009699 return;
Alexey Bataev03f270c2018-03-30 18:31:07 +00009700 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009701 // Register declare target variables.
9702 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
9703 StringRef VarName;
9704 CharUnits VarSize;
9705 llvm::GlobalValue::LinkageTypes Linkage;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009706
9707 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9708 !HasRequiresUnifiedSharedMemory) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009709 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9710 VarName = CGM.getMangledName(VD);
9711 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) {
9712 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType());
9713 assert(!VarSize.isZero() && "Expected non-zero size of the variable");
9714 } else {
9715 VarSize = CharUnits::Zero();
9716 }
9717 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
9718 // Temp solution to prevent optimizations of the internal variables.
9719 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) {
9720 std::string RefName = getName({VarName, "ref"});
9721 if (!CGM.GetGlobalValue(RefName)) {
9722 llvm::Constant *AddrRef =
9723 getOrCreateInternalVariable(Addr->getType(), RefName);
9724 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef);
9725 GVAddrRef->setConstant(/*Val=*/true);
9726 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage);
9727 GVAddrRef->setInitializer(Addr);
9728 CGM.addCompilerUsedGlobal(GVAddrRef);
9729 }
9730 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009731 } else {
9732 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
9733 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9734 HasRequiresUnifiedSharedMemory)) &&
9735 "Declare target attribute must link or to with unified memory.");
9736 if (*Res == OMPDeclareTargetDeclAttr::MT_Link)
9737 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink;
9738 else
9739 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9740
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009741 if (CGM.getLangOpts().OpenMPIsDevice) {
9742 VarName = Addr->getName();
9743 Addr = nullptr;
9744 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009745 VarName = getAddrOfDeclareTargetVar(VD).getName();
9746 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009747 }
9748 VarSize = CGM.getPointerSize();
9749 Linkage = llvm::GlobalValue::WeakAnyLinkage;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009750 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009751
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009752 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9753 VarName, Addr, VarSize, Flags, Linkage);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009754}
9755
Samuel Antaoee8fb302016-01-06 13:42:12 +00009756bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009757 if (isa<FunctionDecl>(GD.getDecl()) ||
9758 isa<OMPDeclareReductionDecl>(GD.getDecl()))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009759 return emitTargetFunctions(GD);
9760
9761 return emitTargetGlobalVariable(GD);
9762}
9763
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009764void CGOpenMPRuntime::emitDeferredTargetDecls() const {
9765 for (const VarDecl *VD : DeferredGlobalVariables) {
9766 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009767 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009768 if (!Res)
9769 continue;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009770 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9771 !HasRequiresUnifiedSharedMemory) {
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009772 CGM.EmitGlobal(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009773 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009774 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
9775 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9776 HasRequiresUnifiedSharedMemory)) &&
9777 "Expected link clause or to clause with unified memory.");
9778 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009779 }
9780 }
9781}
9782
Alexey Bataev60705422018-10-30 15:50:12 +00009783void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas(
9784 CodeGenFunction &CGF, const OMPExecutableDirective &D) const {
9785 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) &&
9786 " Expected target-based directive.");
9787}
9788
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009789void CGOpenMPRuntime::checkArchForUnifiedAddressing(
9790 const OMPRequiresDecl *D) {
9791 for (const OMPClause *Clause : D->clauselists()) {
9792 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
9793 HasRequiresUnifiedSharedMemory = true;
9794 break;
9795 }
9796 }
9797}
9798
Alexey Bataevc5687252019-03-21 19:35:27 +00009799bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD,
9800 LangAS &AS) {
9801 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())
9802 return false;
9803 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
9804 switch(A->getAllocatorType()) {
9805 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
9806 // Not supported, fallback to the default mem space.
9807 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
9808 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
9809 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
9810 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
9811 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
9812 case OMPAllocateDeclAttr::OMPConstMemAlloc:
9813 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
9814 AS = LangAS::Default;
9815 return true;
9816 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
9817 llvm_unreachable("Expected predefined allocator for the variables with the "
9818 "static storage.");
9819 }
9820 return false;
9821}
9822
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00009823bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const {
9824 return HasRequiresUnifiedSharedMemory;
9825}
9826
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009827CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
9828 CodeGenModule &CGM)
9829 : CGM(CGM) {
9830 if (CGM.getLangOpts().OpenMPIsDevice) {
9831 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
9832 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
9833 }
9834}
9835
9836CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() {
9837 if (CGM.getLangOpts().OpenMPIsDevice)
9838 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
9839}
9840
Alexey Bataev6d944102018-05-02 15:45:28 +00009841bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009842 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal)
9843 return true;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009844
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009845 StringRef Name = CGM.getMangledName(GD);
Alexey Bataev6d944102018-05-02 15:45:28 +00009846 const auto *D = cast<FunctionDecl>(GD.getDecl());
Alexey Bataev34f8a702018-03-28 14:28:54 +00009847 // Do not to emit function if it is marked as declare target as it was already
9848 // emitted.
Alexey Bataev97b72212018-08-14 18:31:20 +00009849 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009850 if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) {
9851 if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name)))
Alexey Bataev34f8a702018-03-28 14:28:54 +00009852 return !F->isDeclaration();
9853 return false;
9854 }
9855 return true;
9856 }
9857
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009858 return !AlreadyEmittedTargetFunctions.insert(Name).second;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009859}
9860
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009861llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() {
9862 // If we don't have entries or if we are emitting code for the device, we
9863 // don't need to do anything.
9864 if (CGM.getLangOpts().OMPTargetTriples.empty() ||
9865 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice ||
9866 (OffloadEntriesInfoManager.empty() &&
9867 !HasEmittedDeclareTargetRegion &&
9868 !HasEmittedTargetRegion))
9869 return nullptr;
9870
9871 // Create and register the function that handles the requires directives.
9872 ASTContext &C = CGM.getContext();
9873
9874 llvm::Function *RequiresRegFn;
9875 {
9876 CodeGenFunction CGF(CGM);
9877 const auto &FI = CGM.getTypes().arrangeNullaryFunction();
9878 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
9879 std::string ReqName = getName({"omp_offloading", "requires_reg"});
9880 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI);
9881 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {});
9882 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE;
9883 // TODO: check for other requires clauses.
9884 // The requires directive takes effect only when a target region is
9885 // present in the compilation unit. Otherwise it is ignored and not
9886 // passed to the runtime. This avoids the runtime from throwing an error
9887 // for mismatching requires clauses across compilation units that don't
9888 // contain at least 1 target region.
9889 assert((HasEmittedTargetRegion ||
9890 HasEmittedDeclareTargetRegion ||
9891 !OffloadEntriesInfoManager.empty()) &&
9892 "Target or declare target region expected.");
9893 if (HasRequiresUnifiedSharedMemory)
9894 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY;
9895 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires),
9896 llvm::ConstantInt::get(CGM.Int64Ty, Flags));
9897 CGF.FinishFunction();
9898 }
9899 return RequiresRegFn;
9900}
9901
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009902void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
9903 const OMPExecutableDirective &D,
9904 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00009905 llvm::Function *OutlinedFn,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009906 ArrayRef<llvm::Value *> CapturedVars) {
9907 if (!CGF.HaveInsertPoint())
9908 return;
9909
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009910 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009911 CodeGenFunction::RunCleanupsScope Scope(CGF);
9912
9913 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
9914 llvm::Value *Args[] = {
9915 RTLoc,
9916 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
9917 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
9918 llvm::SmallVector<llvm::Value *, 16> RealArgs;
9919 RealArgs.append(std::begin(Args), std::end(Args));
9920 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
9921
James Y Knight9871db02019-02-05 16:42:33 +00009922 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009923 CGF.EmitRuntimeCall(RTLFn, RealArgs);
9924}
9925
9926void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
Carlo Bertollic6872252016-04-04 15:55:02 +00009927 const Expr *NumTeams,
9928 const Expr *ThreadLimit,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009929 SourceLocation Loc) {
9930 if (!CGF.HaveInsertPoint())
9931 return;
9932
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009933 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009934
Carlo Bertollic6872252016-04-04 15:55:02 +00009935 llvm::Value *NumTeamsVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009936 NumTeams
Carlo Bertollic6872252016-04-04 15:55:02 +00009937 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
9938 CGF.CGM.Int32Ty, /* isSigned = */ true)
9939 : CGF.Builder.getInt32(0);
9940
9941 llvm::Value *ThreadLimitVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009942 ThreadLimit
Carlo Bertollic6872252016-04-04 15:55:02 +00009943 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
9944 CGF.CGM.Int32Ty, /* isSigned = */ true)
9945 : CGF.Builder.getInt32(0);
9946
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009947 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
Carlo Bertollic6872252016-04-04 15:55:02 +00009948 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
9949 ThreadLimitVal};
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009950 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams),
9951 PushNumTeamsArgs);
9952}
Samuel Antaodf158d52016-04-27 22:58:19 +00009953
Samuel Antaocc10b852016-07-28 14:23:26 +00009954void CGOpenMPRuntime::emitTargetDataCalls(
9955 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
9956 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009957 if (!CGF.HaveInsertPoint())
9958 return;
9959
Samuel Antaocc10b852016-07-28 14:23:26 +00009960 // Action used to replace the default codegen action and turn privatization
9961 // off.
9962 PrePostActionTy NoPrivAction;
Samuel Antaodf158d52016-04-27 22:58:19 +00009963
9964 // Generate the code for the opening of the data environment. Capture all the
9965 // arguments of the runtime call by reference because they are used in the
9966 // closing of the region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009967 auto &&BeginThenGen = [this, &D, Device, &Info,
9968 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009969 // Fill up the arrays with all the mapped variables.
Samuel Antaocc10b852016-07-28 14:23:26 +00009970 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
Samuel Antaodf158d52016-04-27 22:58:19 +00009971 MappableExprsHandler::MapValuesArrayTy Pointers;
9972 MappableExprsHandler::MapValuesArrayTy Sizes;
9973 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9974
9975 // Get map clause information.
9976 MappableExprsHandler MCHandler(D, CGF);
9977 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
Samuel Antaodf158d52016-04-27 22:58:19 +00009978
9979 // Fill up the arrays and create the arguments.
Samuel Antaocc10b852016-07-28 14:23:26 +00009980 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +00009981
9982 llvm::Value *BasePointersArrayArg = nullptr;
9983 llvm::Value *PointersArrayArg = nullptr;
9984 llvm::Value *SizesArrayArg = nullptr;
9985 llvm::Value *MapTypesArrayArg = nullptr;
9986 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00009987 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +00009988
9989 // Emit device ID if any.
9990 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +00009991 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009992 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009993 CGF.Int64Ty, /*isSigned=*/true);
9994 } else {
9995 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9996 }
Samuel Antaodf158d52016-04-27 22:58:19 +00009997
9998 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009999 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +000010000
10001 llvm::Value *OffloadingArgs[] = {
10002 DeviceID, PointerNum, BasePointersArrayArg,
10003 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010004 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin),
Samuel Antaodf158d52016-04-27 22:58:19 +000010005 OffloadingArgs);
Samuel Antaocc10b852016-07-28 14:23:26 +000010006
10007 // If device pointer privatization is required, emit the body of the region
10008 // here. It will have to be duplicated: with and without privatization.
10009 if (!Info.CaptureDeviceAddrMap.empty())
10010 CodeGen(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010011 };
10012
10013 // Generate code for the closing of the data region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010014 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF,
10015 PrePostActionTy &) {
Samuel Antaocc10b852016-07-28 14:23:26 +000010016 assert(Info.isValid() && "Invalid data environment closing arguments.");
Samuel Antaodf158d52016-04-27 22:58:19 +000010017
10018 llvm::Value *BasePointersArrayArg = nullptr;
10019 llvm::Value *PointersArrayArg = nullptr;
10020 llvm::Value *SizesArrayArg = nullptr;
10021 llvm::Value *MapTypesArrayArg = nullptr;
10022 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +000010023 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +000010024
10025 // Emit device ID if any.
10026 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010027 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +000010028 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010029 CGF.Int64Ty, /*isSigned=*/true);
10030 } else {
10031 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10032 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010033
10034 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010035 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +000010036
10037 llvm::Value *OffloadingArgs[] = {
10038 DeviceID, PointerNum, BasePointersArrayArg,
10039 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010040 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end),
Samuel Antaodf158d52016-04-27 22:58:19 +000010041 OffloadingArgs);
10042 };
10043
Samuel Antaocc10b852016-07-28 14:23:26 +000010044 // If we need device pointer privatization, we need to emit the body of the
10045 // region with no privatization in the 'else' branch of the conditional.
10046 // Otherwise, we don't have to do anything.
10047 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF,
10048 PrePostActionTy &) {
10049 if (!Info.CaptureDeviceAddrMap.empty()) {
10050 CodeGen.setAction(NoPrivAction);
10051 CodeGen(CGF);
10052 }
10053 };
10054
10055 // We don't have to do anything to close the region if the if clause evaluates
10056 // to false.
10057 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
Samuel Antaodf158d52016-04-27 22:58:19 +000010058
10059 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -050010060 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +000010061 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +000010062 RegionCodeGenTy RCG(BeginThenGen);
10063 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010064 }
10065
Samuel Antaocc10b852016-07-28 14:23:26 +000010066 // If we don't require privatization of device pointers, we emit the body in
10067 // between the runtime calls. This avoids duplicating the body code.
10068 if (Info.CaptureDeviceAddrMap.empty()) {
10069 CodeGen.setAction(NoPrivAction);
10070 CodeGen(CGF);
10071 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010072
10073 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -050010074 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +000010075 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +000010076 RegionCodeGenTy RCG(EndThenGen);
10077 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010078 }
10079}
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010080
Samuel Antao8d2d7302016-05-26 18:30:22 +000010081void CGOpenMPRuntime::emitTargetDataStandAloneCall(
Samuel Antao8dd66282016-04-27 23:14:30 +000010082 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10083 const Expr *Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010084 if (!CGF.HaveInsertPoint())
10085 return;
10086
Samuel Antao8dd66282016-04-27 23:14:30 +000010087 assert((isa<OMPTargetEnterDataDirective>(D) ||
Samuel Antao8d2d7302016-05-26 18:30:22 +000010088 isa<OMPTargetExitDataDirective>(D) ||
10089 isa<OMPTargetUpdateDirective>(D)) &&
10090 "Expecting either target enter, exit data, or update directives.");
Samuel Antao8dd66282016-04-27 23:14:30 +000010091
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010092 CodeGenFunction::OMPTargetDataInfo InputInfo;
10093 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010094 // Generate the code for the opening of the data environment.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010095 auto &&ThenGen = [this, &D, Device, &InputInfo,
10096 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010097 // Emit device ID if any.
10098 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010099 if (Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010100 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010101 CGF.Int64Ty, /*isSigned=*/true);
10102 } else {
10103 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10104 }
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010105
10106 // Emit the number of elements in the offloading arrays.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010107 llvm::Constant *PointerNum =
10108 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010109
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010110 llvm::Value *OffloadingArgs[] = {DeviceID,
10111 PointerNum,
10112 InputInfo.BasePointersArray.getPointer(),
10113 InputInfo.PointersArray.getPointer(),
10114 InputInfo.SizesArray.getPointer(),
10115 MapTypesArray};
Samuel Antao8d2d7302016-05-26 18:30:22 +000010116
Samuel Antao8d2d7302016-05-26 18:30:22 +000010117 // Select the right runtime function call for each expected standalone
10118 // directive.
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010119 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Samuel Antao8d2d7302016-05-26 18:30:22 +000010120 OpenMPRTLFunction RTLFn;
10121 switch (D.getDirectiveKind()) {
Samuel Antao8d2d7302016-05-26 18:30:22 +000010122 case OMPD_target_enter_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010123 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait
10124 : OMPRTL__tgt_target_data_begin;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010125 break;
10126 case OMPD_target_exit_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010127 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait
10128 : OMPRTL__tgt_target_data_end;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010129 break;
10130 case OMPD_target_update:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010131 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait
10132 : OMPRTL__tgt_target_data_update;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010133 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010134 case OMPD_parallel:
10135 case OMPD_for:
10136 case OMPD_parallel_for:
10137 case OMPD_parallel_sections:
10138 case OMPD_for_simd:
10139 case OMPD_parallel_for_simd:
10140 case OMPD_cancel:
10141 case OMPD_cancellation_point:
10142 case OMPD_ordered:
10143 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +000010144 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010145 case OMPD_task:
10146 case OMPD_simd:
10147 case OMPD_sections:
10148 case OMPD_section:
10149 case OMPD_single:
10150 case OMPD_master:
10151 case OMPD_critical:
10152 case OMPD_taskyield:
10153 case OMPD_barrier:
10154 case OMPD_taskwait:
10155 case OMPD_taskgroup:
10156 case OMPD_atomic:
10157 case OMPD_flush:
10158 case OMPD_teams:
10159 case OMPD_target_data:
10160 case OMPD_distribute:
10161 case OMPD_distribute_simd:
10162 case OMPD_distribute_parallel_for:
10163 case OMPD_distribute_parallel_for_simd:
10164 case OMPD_teams_distribute:
10165 case OMPD_teams_distribute_simd:
10166 case OMPD_teams_distribute_parallel_for:
10167 case OMPD_teams_distribute_parallel_for_simd:
10168 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +000010169 case OMPD_declare_variant:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010170 case OMPD_declare_target:
10171 case OMPD_end_declare_target:
10172 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +000010173 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010174 case OMPD_taskloop:
10175 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +000010176 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +000010177 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +000010178 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -040010179 case OMPD_parallel_master_taskloop_simd:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010180 case OMPD_target:
10181 case OMPD_target_simd:
10182 case OMPD_target_teams_distribute:
10183 case OMPD_target_teams_distribute_simd:
10184 case OMPD_target_teams_distribute_parallel_for:
10185 case OMPD_target_teams_distribute_parallel_for_simd:
10186 case OMPD_target_teams:
10187 case OMPD_target_parallel:
10188 case OMPD_target_parallel_for:
10189 case OMPD_target_parallel_for_simd:
Kelvin Li1408f912018-09-26 04:28:39 +000010190 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010191 case OMPD_unknown:
10192 llvm_unreachable("Unexpected standalone target data directive.");
10193 break;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010194 }
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010195 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010196 };
10197
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010198 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray](
10199 CodeGenFunction &CGF, PrePostActionTy &) {
10200 // Fill up the arrays with all the mapped variables.
10201 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
10202 MappableExprsHandler::MapValuesArrayTy Pointers;
10203 MappableExprsHandler::MapValuesArrayTy Sizes;
10204 MappableExprsHandler::MapFlagsArrayTy MapTypes;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010205
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010206 // Get map clause information.
10207 MappableExprsHandler MEHandler(D, CGF);
10208 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
10209
10210 TargetDataInfo Info;
10211 // Fill up the arrays and create the arguments.
10212 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
10213 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
10214 Info.PointersArray, Info.SizesArray,
10215 Info.MapTypesArray, Info);
10216 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
10217 InputInfo.BasePointersArray =
10218 Address(Info.BasePointersArray, CGM.getPointerAlign());
10219 InputInfo.PointersArray =
10220 Address(Info.PointersArray, CGM.getPointerAlign());
10221 InputInfo.SizesArray =
10222 Address(Info.SizesArray, CGM.getPointerAlign());
10223 MapTypesArray = Info.MapTypesArray;
10224 if (D.hasClausesOfKind<OMPDependClause>())
10225 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
10226 else
Alexey Bataev768f1f22018-01-09 19:59:25 +000010227 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010228 };
10229
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010230 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -050010231 emitIfClause(CGF, IfCond, TargetThenGen,
10232 [](CodeGenFunction &CGF, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010233 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010234 RegionCodeGenTy ThenRCG(TargetThenGen);
10235 ThenRCG(CGF);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010236 }
10237}
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010238
10239namespace {
10240 /// Kind of parameter in a function with 'declare simd' directive.
10241 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector };
10242 /// Attribute set of the parameter.
10243 struct ParamAttrTy {
10244 ParamKindTy Kind = Vector;
10245 llvm::APSInt StrideOrArg;
10246 llvm::APSInt Alignment;
10247 };
10248} // namespace
10249
10250static unsigned evaluateCDTSize(const FunctionDecl *FD,
10251 ArrayRef<ParamAttrTy> ParamAttrs) {
10252 // Every vector variant of a SIMD-enabled function has a vector length (VLEN).
10253 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument
10254 // of that clause. The VLEN value must be power of 2.
10255 // In other case the notion of the function`s "characteristic data type" (CDT)
10256 // is used to compute the vector length.
10257 // CDT is defined in the following order:
10258 // a) For non-void function, the CDT is the return type.
10259 // b) If the function has any non-uniform, non-linear parameters, then the
10260 // CDT is the type of the first such parameter.
10261 // c) If the CDT determined by a) or b) above is struct, union, or class
10262 // type which is pass-by-value (except for the type that maps to the
10263 // built-in complex data type), the characteristic data type is int.
10264 // d) If none of the above three cases is applicable, the CDT is int.
10265 // The VLEN is then determined based on the CDT and the size of vector
10266 // register of that ISA for which current vector version is generated. The
10267 // VLEN is computed using the formula below:
10268 // VLEN = sizeof(vector_register) / sizeof(CDT),
10269 // where vector register size specified in section 3.2.1 Registers and the
10270 // Stack Frame of original AMD64 ABI document.
10271 QualType RetType = FD->getReturnType();
10272 if (RetType.isNull())
10273 return 0;
10274 ASTContext &C = FD->getASTContext();
10275 QualType CDT;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010276 if (!RetType.isNull() && !RetType->isVoidType()) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010277 CDT = RetType;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010278 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010279 unsigned Offset = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010280 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010281 if (ParamAttrs[Offset].Kind == Vector)
10282 CDT = C.getPointerType(C.getRecordType(MD->getParent()));
10283 ++Offset;
10284 }
10285 if (CDT.isNull()) {
10286 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10287 if (ParamAttrs[I + Offset].Kind == Vector) {
10288 CDT = FD->getParamDecl(I)->getType();
10289 break;
10290 }
10291 }
10292 }
10293 }
10294 if (CDT.isNull())
10295 CDT = C.IntTy;
10296 CDT = CDT->getCanonicalTypeUnqualified();
10297 if (CDT->isRecordType() || CDT->isUnionType())
10298 CDT = C.IntTy;
10299 return C.getTypeSize(CDT);
10300}
10301
10302static void
10303emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
Benjamin Kramer81cb4b72016-11-24 16:01:20 +000010304 const llvm::APSInt &VLENVal,
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010305 ArrayRef<ParamAttrTy> ParamAttrs,
10306 OMPDeclareSimdDeclAttr::BranchStateTy State) {
10307 struct ISADataTy {
10308 char ISA;
10309 unsigned VecRegSize;
10310 };
10311 ISADataTy ISAData[] = {
10312 {
10313 'b', 128
10314 }, // SSE
10315 {
10316 'c', 256
10317 }, // AVX
10318 {
10319 'd', 256
10320 }, // AVX2
10321 {
10322 'e', 512
10323 }, // AVX512
10324 };
10325 llvm::SmallVector<char, 2> Masked;
10326 switch (State) {
10327 case OMPDeclareSimdDeclAttr::BS_Undefined:
10328 Masked.push_back('N');
10329 Masked.push_back('M');
10330 break;
10331 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10332 Masked.push_back('N');
10333 break;
10334 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10335 Masked.push_back('M');
10336 break;
10337 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010338 for (char Mask : Masked) {
10339 for (const ISADataTy &Data : ISAData) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010340 SmallString<256> Buffer;
10341 llvm::raw_svector_ostream Out(Buffer);
10342 Out << "_ZGV" << Data.ISA << Mask;
10343 if (!VLENVal) {
Simon Pilgrim823a99c2019-05-22 13:02:19 +000010344 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs);
10345 assert(NumElts && "Non-zero simdlen/cdtsize expected");
10346 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010347 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010348 Out << VLENVal;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010349 }
10350 for (const ParamAttrTy &ParamAttr : ParamAttrs) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010351 switch (ParamAttr.Kind){
10352 case LinearWithVarStride:
10353 Out << 's' << ParamAttr.StrideOrArg;
10354 break;
10355 case Linear:
10356 Out << 'l';
10357 if (!!ParamAttr.StrideOrArg)
10358 Out << ParamAttr.StrideOrArg;
10359 break;
10360 case Uniform:
10361 Out << 'u';
10362 break;
10363 case Vector:
10364 Out << 'v';
10365 break;
10366 }
10367 if (!!ParamAttr.Alignment)
10368 Out << 'a' << ParamAttr.Alignment;
10369 }
10370 Out << '_' << Fn->getName();
10371 Fn->addFnAttr(Out.str());
10372 }
10373 }
10374}
10375
Alexey Bataeva0a22642019-04-16 13:56:21 +000010376// This are the Functions that are needed to mangle the name of the
10377// vector functions generated by the compiler, according to the rules
10378// defined in the "Vector Function ABI specifications for AArch64",
10379// available at
10380// https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi.
10381
10382/// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI.
10383///
10384/// TODO: Need to implement the behavior for reference marked with a
10385/// var or no linear modifiers (1.b in the section). For this, we
10386/// need to extend ParamKindTy to support the linear modifiers.
10387static bool getAArch64MTV(QualType QT, ParamKindTy Kind) {
10388 QT = QT.getCanonicalType();
10389
10390 if (QT->isVoidType())
10391 return false;
10392
10393 if (Kind == ParamKindTy::Uniform)
10394 return false;
10395
10396 if (Kind == ParamKindTy::Linear)
10397 return false;
10398
10399 // TODO: Handle linear references with modifiers
10400
10401 if (Kind == ParamKindTy::LinearWithVarStride)
10402 return false;
10403
10404 return true;
10405}
10406
10407/// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
10408static bool getAArch64PBV(QualType QT, ASTContext &C) {
10409 QT = QT.getCanonicalType();
10410 unsigned Size = C.getTypeSize(QT);
10411
10412 // Only scalars and complex within 16 bytes wide set PVB to true.
10413 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
10414 return false;
10415
10416 if (QT->isFloatingType())
10417 return true;
10418
10419 if (QT->isIntegerType())
10420 return true;
10421
10422 if (QT->isPointerType())
10423 return true;
10424
10425 // TODO: Add support for complex types (section 3.1.2, item 2).
10426
10427 return false;
10428}
10429
10430/// Computes the lane size (LS) of a return type or of an input parameter,
10431/// as defined by `LS(P)` in 3.2.1 of the AAVFABI.
10432/// TODO: Add support for references, section 3.2.1, item 1.
10433static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) {
10434 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) {
10435 QualType PTy = QT.getCanonicalType()->getPointeeType();
10436 if (getAArch64PBV(PTy, C))
10437 return C.getTypeSize(PTy);
10438 }
10439 if (getAArch64PBV(QT, C))
10440 return C.getTypeSize(QT);
10441
10442 return C.getTypeSize(C.getUIntPtrType());
10443}
10444
10445// Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the
10446// signature of the scalar function, as defined in 3.2.2 of the
10447// AAVFABI.
10448static std::tuple<unsigned, unsigned, bool>
10449getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) {
10450 QualType RetType = FD->getReturnType().getCanonicalType();
10451
10452 ASTContext &C = FD->getASTContext();
10453
10454 bool OutputBecomesInput = false;
10455
10456 llvm::SmallVector<unsigned, 8> Sizes;
10457 if (!RetType->isVoidType()) {
10458 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C));
10459 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {}))
10460 OutputBecomesInput = true;
10461 }
10462 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10463 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType();
10464 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C));
10465 }
10466
10467 assert(!Sizes.empty() && "Unable to determine NDS and WDS.");
10468 // The LS of a function parameter / return value can only be a power
10469 // of 2, starting from 8 bits, up to 128.
10470 assert(std::all_of(Sizes.begin(), Sizes.end(),
10471 [](unsigned Size) {
10472 return Size == 8 || Size == 16 || Size == 32 ||
10473 Size == 64 || Size == 128;
10474 }) &&
10475 "Invalid size");
10476
10477 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)),
10478 *std::max_element(std::begin(Sizes), std::end(Sizes)),
10479 OutputBecomesInput);
10480}
10481
10482/// Mangle the parameter part of the vector function name according to
10483/// their OpenMP classification. The mangling function is defined in
10484/// section 3.5 of the AAVFABI.
10485static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) {
10486 SmallString<256> Buffer;
10487 llvm::raw_svector_ostream Out(Buffer);
10488 for (const auto &ParamAttr : ParamAttrs) {
10489 switch (ParamAttr.Kind) {
10490 case LinearWithVarStride:
10491 Out << "ls" << ParamAttr.StrideOrArg;
10492 break;
10493 case Linear:
10494 Out << 'l';
10495 // Don't print the step value if it is not present or if it is
10496 // equal to 1.
10497 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1)
10498 Out << ParamAttr.StrideOrArg;
10499 break;
10500 case Uniform:
10501 Out << 'u';
10502 break;
10503 case Vector:
10504 Out << 'v';
10505 break;
10506 }
10507
10508 if (!!ParamAttr.Alignment)
10509 Out << 'a' << ParamAttr.Alignment;
10510 }
10511
10512 return Out.str();
10513}
10514
10515// Function used to add the attribute. The parameter `VLEN` is
10516// templated to allow the use of "x" when targeting scalable functions
10517// for SVE.
10518template <typename T>
10519static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix,
10520 char ISA, StringRef ParSeq,
10521 StringRef MangledName, bool OutputBecomesInput,
10522 llvm::Function *Fn) {
10523 SmallString<256> Buffer;
10524 llvm::raw_svector_ostream Out(Buffer);
10525 Out << Prefix << ISA << LMask << VLEN;
10526 if (OutputBecomesInput)
10527 Out << "v";
10528 Out << ParSeq << "_" << MangledName;
10529 Fn->addFnAttr(Out.str());
10530}
10531
10532// Helper function to generate the Advanced SIMD names depending on
10533// the value of the NDS when simdlen is not present.
10534static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask,
10535 StringRef Prefix, char ISA,
10536 StringRef ParSeq, StringRef MangledName,
10537 bool OutputBecomesInput,
10538 llvm::Function *Fn) {
10539 switch (NDS) {
10540 case 8:
10541 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10542 OutputBecomesInput, Fn);
10543 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName,
10544 OutputBecomesInput, Fn);
10545 break;
10546 case 16:
10547 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10548 OutputBecomesInput, Fn);
10549 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10550 OutputBecomesInput, Fn);
10551 break;
10552 case 32:
10553 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10554 OutputBecomesInput, Fn);
10555 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10556 OutputBecomesInput, Fn);
10557 break;
10558 case 64:
10559 case 128:
10560 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10561 OutputBecomesInput, Fn);
10562 break;
10563 default:
10564 llvm_unreachable("Scalar type is too wide.");
10565 }
10566}
10567
10568/// Emit vector function attributes for AArch64, as defined in the AAVFABI.
10569static void emitAArch64DeclareSimdFunction(
10570 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN,
10571 ArrayRef<ParamAttrTy> ParamAttrs,
10572 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
10573 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) {
10574
10575 // Get basic data for building the vector signature.
10576 const auto Data = getNDSWDS(FD, ParamAttrs);
10577 const unsigned NDS = std::get<0>(Data);
10578 const unsigned WDS = std::get<1>(Data);
10579 const bool OutputBecomesInput = std::get<2>(Data);
10580
10581 // Check the values provided via `simdlen` by the user.
10582 // 1. A `simdlen(1)` doesn't produce vector signatures,
10583 if (UserVLEN == 1) {
10584 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10585 DiagnosticsEngine::Warning,
10586 "The clause simdlen(1) has no effect when targeting aarch64.");
10587 CGM.getDiags().Report(SLoc, DiagID);
10588 return;
10589 }
10590
10591 // 2. Section 3.3.1, item 1: user input must be a power of 2 for
10592 // Advanced SIMD output.
10593 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
10594 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10595 DiagnosticsEngine::Warning, "The value specified in simdlen must be a "
10596 "power of 2 when targeting Advanced SIMD.");
10597 CGM.getDiags().Report(SLoc, DiagID);
10598 return;
10599 }
10600
10601 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural
10602 // limits.
10603 if (ISA == 's' && UserVLEN != 0) {
10604 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
10605 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10606 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit "
10607 "lanes in the architectural constraints "
10608 "for SVE (min is 128-bit, max is "
10609 "2048-bit, by steps of 128-bit)");
10610 CGM.getDiags().Report(SLoc, DiagID) << WDS;
10611 return;
10612 }
10613 }
10614
10615 // Sort out parameter sequence.
10616 const std::string ParSeq = mangleVectorParameters(ParamAttrs);
10617 StringRef Prefix = "_ZGV";
10618 // Generate simdlen from user input (if any).
10619 if (UserVLEN) {
10620 if (ISA == 's') {
10621 // SVE generates only a masked function.
10622 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10623 OutputBecomesInput, Fn);
10624 } else {
10625 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10626 // Advanced SIMD generates one or two functions, depending on
10627 // the `[not]inbranch` clause.
10628 switch (State) {
10629 case OMPDeclareSimdDeclAttr::BS_Undefined:
10630 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10631 OutputBecomesInput, Fn);
10632 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10633 OutputBecomesInput, Fn);
10634 break;
10635 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10636 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10637 OutputBecomesInput, Fn);
10638 break;
10639 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10640 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10641 OutputBecomesInput, Fn);
10642 break;
10643 }
10644 }
10645 } else {
10646 // If no user simdlen is provided, follow the AAVFABI rules for
10647 // generating the vector length.
10648 if (ISA == 's') {
10649 // SVE, section 3.4.1, item 1.
10650 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName,
10651 OutputBecomesInput, Fn);
10652 } else {
10653 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10654 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or
10655 // two vector names depending on the use of the clause
10656 // `[not]inbranch`.
10657 switch (State) {
10658 case OMPDeclareSimdDeclAttr::BS_Undefined:
10659 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10660 OutputBecomesInput, Fn);
10661 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10662 OutputBecomesInput, Fn);
10663 break;
10664 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10665 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10666 OutputBecomesInput, Fn);
10667 break;
10668 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10669 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10670 OutputBecomesInput, Fn);
10671 break;
10672 }
10673 }
10674 }
10675}
10676
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010677void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
10678 llvm::Function *Fn) {
10679 ASTContext &C = CGM.getContext();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010680 FD = FD->getMostRecentDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010681 // Map params to their positions in function decl.
10682 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
10683 if (isa<CXXMethodDecl>(FD))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010684 ParamPositions.try_emplace(FD, 0);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010685 unsigned ParamPos = ParamPositions.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010686 for (const ParmVarDecl *P : FD->parameters()) {
10687 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010688 ++ParamPos;
10689 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010690 while (FD) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010691 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010692 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
10693 // Mark uniform parameters.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010694 for (const Expr *E : Attr->uniforms()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010695 E = E->IgnoreParenImpCasts();
10696 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010697 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010698 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010699 } else {
10700 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10701 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010702 Pos = ParamPositions[PVD];
10703 }
10704 ParamAttrs[Pos].Kind = Uniform;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010705 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010706 // Get alignment info.
10707 auto NI = Attr->alignments_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010708 for (const Expr *E : Attr->aligneds()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010709 E = E->IgnoreParenImpCasts();
10710 unsigned Pos;
10711 QualType ParmTy;
10712 if (isa<CXXThisExpr>(E)) {
10713 Pos = ParamPositions[FD];
10714 ParmTy = E->getType();
10715 } else {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010716 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10717 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010718 Pos = ParamPositions[PVD];
10719 ParmTy = PVD->getType();
10720 }
10721 ParamAttrs[Pos].Alignment =
10722 (*NI)
10723 ? (*NI)->EvaluateKnownConstInt(C)
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010724 : llvm::APSInt::getUnsigned(
10725 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy))
10726 .getQuantity());
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010727 ++NI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010728 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010729 // Mark linear parameters.
10730 auto SI = Attr->steps_begin();
10731 auto MI = Attr->modifiers_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010732 for (const Expr *E : Attr->linears()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010733 E = E->IgnoreParenImpCasts();
10734 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010735 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010736 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010737 } else {
10738 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10739 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010740 Pos = ParamPositions[PVD];
10741 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010742 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010743 ParamAttr.Kind = Linear;
10744 if (*SI) {
Fangrui Song407659a2018-11-30 23:41:18 +000010745 Expr::EvalResult Result;
10746 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010747 if (const auto *DRE =
10748 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
10749 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010750 ParamAttr.Kind = LinearWithVarStride;
10751 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(
10752 ParamPositions[StridePVD->getCanonicalDecl()]);
10753 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010754 }
Fangrui Song407659a2018-11-30 23:41:18 +000010755 } else {
10756 ParamAttr.StrideOrArg = Result.Val.getInt();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010757 }
10758 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010759 ++SI;
10760 ++MI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010761 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010762 llvm::APSInt VLENVal;
Alexey Bataeva0a22642019-04-16 13:56:21 +000010763 SourceLocation ExprLoc;
10764 const Expr *VLENExpr = Attr->getSimdlen();
10765 if (VLENExpr) {
10766 VLENVal = VLENExpr->EvaluateKnownConstInt(C);
10767 ExprLoc = VLENExpr->getExprLoc();
10768 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010769 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
10770 if (CGM.getTriple().getArch() == llvm::Triple::x86 ||
Alexey Bataeva0a22642019-04-16 13:56:21 +000010771 CGM.getTriple().getArch() == llvm::Triple::x86_64) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010772 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
Alexey Bataeva0a22642019-04-16 13:56:21 +000010773 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) {
10774 unsigned VLEN = VLENVal.getExtValue();
10775 StringRef MangledName = Fn->getName();
10776 if (CGM.getTarget().hasFeature("sve"))
10777 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10778 MangledName, 's', 128, Fn, ExprLoc);
10779 if (CGM.getTarget().hasFeature("neon"))
10780 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10781 MangledName, 'n', 128, Fn, ExprLoc);
10782 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010783 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010784 FD = FD->getPreviousDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010785 }
10786}
Alexey Bataev8b427062016-05-25 12:36:08 +000010787
10788namespace {
10789/// Cleanup action for doacross support.
10790class DoacrossCleanupTy final : public EHScopeStack::Cleanup {
10791public:
10792 static const int DoacrossFinArgs = 2;
10793
10794private:
James Y Knight9871db02019-02-05 16:42:33 +000010795 llvm::FunctionCallee RTLFn;
Alexey Bataev8b427062016-05-25 12:36:08 +000010796 llvm::Value *Args[DoacrossFinArgs];
10797
10798public:
James Y Knight9871db02019-02-05 16:42:33 +000010799 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
10800 ArrayRef<llvm::Value *> CallArgs)
Alexey Bataev8b427062016-05-25 12:36:08 +000010801 : RTLFn(RTLFn) {
10802 assert(CallArgs.size() == DoacrossFinArgs);
10803 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10804 }
10805 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10806 if (!CGF.HaveInsertPoint())
10807 return;
10808 CGF.EmitRuntimeCall(RTLFn, Args);
10809 }
10810};
10811} // namespace
10812
10813void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000010814 const OMPLoopDirective &D,
10815 ArrayRef<Expr *> NumIterations) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010816 if (!CGF.HaveInsertPoint())
10817 return;
10818
10819 ASTContext &C = CGM.getContext();
10820 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
10821 RecordDecl *RD;
10822 if (KmpDimTy.isNull()) {
10823 // Build struct kmp_dim { // loop bounds info casted to kmp_int64
10824 // kmp_int64 lo; // lower
10825 // kmp_int64 up; // upper
10826 // kmp_int64 st; // stride
10827 // };
10828 RD = C.buildImplicitRecord("kmp_dim");
10829 RD->startDefinition();
10830 addFieldToRecordDecl(C, RD, Int64Ty);
10831 addFieldToRecordDecl(C, RD, Int64Ty);
10832 addFieldToRecordDecl(C, RD, Int64Ty);
10833 RD->completeDefinition();
10834 KmpDimTy = C.getRecordType(RD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010835 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010836 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010837 }
Alexey Bataevf138fda2018-08-13 19:04:24 +000010838 llvm::APInt Size(/*numBits=*/32, NumIterations.size());
10839 QualType ArrayTy =
Richard Smith772e2662019-10-04 01:25:59 +000010840 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0);
Alexey Bataev8b427062016-05-25 12:36:08 +000010841
Alexey Bataevf138fda2018-08-13 19:04:24 +000010842 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
10843 CGF.EmitNullInitialization(DimsAddr, ArrayTy);
Alexey Bataev8b427062016-05-25 12:36:08 +000010844 enum { LowerFD = 0, UpperFD, StrideFD };
10845 // Fill dims with data.
Alexey Bataevf138fda2018-08-13 19:04:24 +000010846 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +000010847 LValue DimsLVal = CGF.MakeAddrLValue(
10848 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010849 // dims.upper = num_iterations;
10850 LValue UpperLVal = CGF.EmitLValueForField(
10851 DimsLVal, *std::next(RD->field_begin(), UpperFD));
10852 llvm::Value *NumIterVal =
10853 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]),
10854 D.getNumIterations()->getType(), Int64Ty,
10855 D.getNumIterations()->getExprLoc());
10856 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
10857 // dims.stride = 1;
10858 LValue StrideLVal = CGF.EmitLValueForField(
10859 DimsLVal, *std::next(RD->field_begin(), StrideFD));
10860 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
10861 StrideLVal);
10862 }
Alexey Bataev8b427062016-05-25 12:36:08 +000010863
10864 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
10865 // kmp_int32 num_dims, struct kmp_dim * dims);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010866 llvm::Value *Args[] = {
10867 emitUpdateLocation(CGF, D.getBeginLoc()),
10868 getThreadID(CGF, D.getBeginLoc()),
10869 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()),
10870 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knight751fe282019-02-09 22:22:28 +000010871 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(),
Alexey Bataevf138fda2018-08-13 19:04:24 +000010872 CGM.VoidPtrTy)};
Alexey Bataev8b427062016-05-25 12:36:08 +000010873
James Y Knight9871db02019-02-05 16:42:33 +000010874 llvm::FunctionCallee RTLFn =
10875 createRuntimeFunction(OMPRTL__kmpc_doacross_init);
Alexey Bataev8b427062016-05-25 12:36:08 +000010876 CGF.EmitRuntimeCall(RTLFn, Args);
10877 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
Stephen Kelly1c301dc2018-08-09 21:09:38 +000010878 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())};
James Y Knight9871db02019-02-05 16:42:33 +000010879 llvm::FunctionCallee FiniRTLFn =
10880 createRuntimeFunction(OMPRTL__kmpc_doacross_fini);
Alexey Bataev8b427062016-05-25 12:36:08 +000010881 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
10882 llvm::makeArrayRef(FiniArgs));
10883}
10884
10885void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
10886 const OMPDependClause *C) {
10887 QualType Int64Ty =
10888 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010889 llvm::APInt Size(/*numBits=*/32, C->getNumLoops());
10890 QualType ArrayTy = CGM.getContext().getConstantArrayType(
Richard Smith772e2662019-10-04 01:25:59 +000010891 Int64Ty, Size, nullptr, ArrayType::Normal, 0);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010892 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr");
10893 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) {
10894 const Expr *CounterVal = C->getLoopData(I);
10895 assert(CounterVal);
10896 llvm::Value *CntVal = CGF.EmitScalarConversion(
10897 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
10898 CounterVal->getExprLoc());
James Y Knight751fe282019-02-09 22:22:28 +000010899 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I),
10900 /*Volatile=*/false, Int64Ty);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010901 }
10902 llvm::Value *Args[] = {
10903 emitUpdateLocation(CGF, C->getBeginLoc()),
10904 getThreadID(CGF, C->getBeginLoc()),
James Y Knight751fe282019-02-09 22:22:28 +000010905 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()};
James Y Knight9871db02019-02-05 16:42:33 +000010906 llvm::FunctionCallee RTLFn;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010907 if (C->getDependencyKind() == OMPC_DEPEND_source) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010908 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010909 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010910 assert(C->getDependencyKind() == OMPC_DEPEND_sink);
10911 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait);
10912 }
10913 CGF.EmitRuntimeCall(RTLFn, Args);
10914}
10915
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010916void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000010917 llvm::FunctionCallee Callee,
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010918 ArrayRef<llvm::Value *> Args) const {
10919 assert(Loc.isValid() && "Outlined function call location must be valid.");
Alexey Bataev3c595a62017-08-14 15:01:03 +000010920 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
10921
James Y Knight9871db02019-02-05 16:42:33 +000010922 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010923 if (Fn->doesNotThrow()) {
Alexey Bataev3c595a62017-08-14 15:01:03 +000010924 CGF.EmitNounwindRuntimeCall(Fn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010925 return;
10926 }
10927 }
Alexey Bataev3c595a62017-08-14 15:01:03 +000010928 CGF.EmitRuntimeCall(Callee, Args);
10929}
10930
10931void CGOpenMPRuntime::emitOutlinedFunctionCall(
James Y Knight9871db02019-02-05 16:42:33 +000010932 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn,
Alexey Bataev3c595a62017-08-14 15:01:03 +000010933 ArrayRef<llvm::Value *> Args) const {
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010934 emitCall(CGF, Loc, OutlinedFn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010935}
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010936
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +000010937void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) {
10938 if (const auto *FD = dyn_cast<FunctionDecl>(D))
10939 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
10940 HasEmittedDeclareTargetRegion = true;
10941}
10942
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010943Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
10944 const VarDecl *NativeParam,
10945 const VarDecl *TargetParam) const {
10946 return CGF.GetAddrOfLocalVar(NativeParam);
10947}
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010948
Alexey Bataev4f680db2019-03-19 16:41:16 +000010949namespace {
10950/// Cleanup action for allocate support.
10951class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup {
10952public:
10953 static const int CleanupArgs = 3;
10954
10955private:
10956 llvm::FunctionCallee RTLFn;
10957 llvm::Value *Args[CleanupArgs];
10958
10959public:
10960 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
10961 ArrayRef<llvm::Value *> CallArgs)
10962 : RTLFn(RTLFn) {
10963 assert(CallArgs.size() == CleanupArgs &&
10964 "Size of arguments does not match.");
10965 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10966 }
10967 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10968 if (!CGF.HaveInsertPoint())
10969 return;
10970 CGF.EmitRuntimeCall(RTLFn, Args);
10971 }
10972};
10973} // namespace
10974
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000010975Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF,
10976 const VarDecl *VD) {
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010977 if (!VD)
10978 return Address::invalid();
Alexey Bataev4f680db2019-03-19 16:41:16 +000010979 const VarDecl *CVD = VD->getCanonicalDecl();
10980 if (!CVD->hasAttr<OMPAllocateDeclAttr>())
10981 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010982 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
10983 // Use the default allocation.
Alexey Bataev0fd3c682019-04-02 19:44:46 +000010984 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
10985 !AA->getAllocator())
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010986 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010987 llvm::Value *Size;
10988 CharUnits Align = CGM.getContext().getDeclAlign(CVD);
10989 if (CVD->getType()->isVariablyModifiedType()) {
10990 Size = CGF.getTypeSize(CVD->getType());
Alexey Bataev9c397812019-04-03 17:57:06 +000010991 // Align the size: ((size + align - 1) / align) * align
10992 Size = CGF.Builder.CreateNUWAdd(
10993 Size, CGM.getSize(Align - CharUnits::fromQuantity(1)));
10994 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align));
10995 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align));
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010996 } else {
10997 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType());
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010998 Size = CGM.getSize(Sz.alignTo(Align));
Alexey Bataev4f680db2019-03-19 16:41:16 +000010999 }
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011000 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc());
11001 assert(AA->getAllocator() &&
11002 "Expected allocator expression for non-default allocator.");
11003 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator());
Alexey Bataev6cf7b712019-04-08 19:06:42 +000011004 // According to the standard, the original allocator type is a enum (integer).
11005 // Convert to pointer type, if required.
11006 if (Allocator->getType()->isIntegerTy())
11007 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy);
11008 else if (Allocator->getType()->isPointerTy())
11009 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator,
11010 CGM.VoidPtrTy);
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011011 llvm::Value *Args[] = {ThreadID, Size, Allocator};
11012
11013 llvm::Value *Addr =
11014 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args,
11015 CVD->getName() + ".void.addr");
11016 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr,
11017 Allocator};
11018 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free);
11019
11020 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
11021 llvm::makeArrayRef(FiniArgs));
11022 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11023 Addr,
11024 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())),
11025 CVD->getName() + ".addr");
11026 return Address(Addr, Align);
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000011027}
11028
Alexey Bataevfde11e92019-11-07 11:03:10 -050011029namespace {
11030using OMPContextSelectorData =
Alexey Bataevf8ff3d72019-11-21 16:36:49 -050011031 OpenMPCtxSelectorData<ArrayRef<StringRef>, llvm::APSInt>;
Alexey Bataevfde11e92019-11-07 11:03:10 -050011032using CompleteOMPContextSelectorData = SmallVector<OMPContextSelectorData, 4>;
11033} // anonymous namespace
11034
Alexey Bataev2df5f122019-10-01 20:18:32 +000011035/// Checks current context and returns true if it matches the context selector.
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011036template <OpenMPContextSelectorSetKind CtxSet, OpenMPContextSelectorKind Ctx,
11037 typename... Arguments>
11038static bool checkContext(const OMPContextSelectorData &Data,
11039 Arguments... Params) {
Alexey Bataevfde11e92019-11-07 11:03:10 -050011040 assert(Data.CtxSet != OMP_CTX_SET_unknown && Data.Ctx != OMP_CTX_unknown &&
Alexey Bataev2df5f122019-10-01 20:18:32 +000011041 "Unknown context selector or context selector set.");
11042 return false;
11043}
11044
11045/// Checks for implementation={vendor(<vendor>)} context selector.
11046/// \returns true iff <vendor>="llvm", false otherwise.
11047template <>
Alexey Bataevfde11e92019-11-07 11:03:10 -050011048bool checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(
11049 const OMPContextSelectorData &Data) {
11050 return llvm::all_of(Data.Names,
Alexey Bataev303657a2019-10-08 19:44:16 +000011051 [](StringRef S) { return !S.compare_lower("llvm"); });
Alexey Bataev2df5f122019-10-01 20:18:32 +000011052}
11053
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011054/// Checks for device={kind(<kind>)} context selector.
11055/// \returns true if <kind>="host" and compilation is for host.
11056/// true if <kind>="nohost" and compilation is for device.
11057/// true if <kind>="cpu" and compilation is for Arm, X86 or PPC CPU.
11058/// true if <kind>="gpu" and compilation is for NVPTX or AMDGCN.
11059/// false otherwise.
11060template <>
11061bool checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>(
11062 const OMPContextSelectorData &Data, CodeGenModule &CGM) {
11063 for (StringRef Name : Data.Names) {
11064 if (!Name.compare_lower("host")) {
11065 if (CGM.getLangOpts().OpenMPIsDevice)
11066 return false;
11067 continue;
11068 }
11069 if (!Name.compare_lower("nohost")) {
11070 if (!CGM.getLangOpts().OpenMPIsDevice)
11071 return false;
11072 continue;
11073 }
11074 switch (CGM.getTriple().getArch()) {
11075 case llvm::Triple::arm:
11076 case llvm::Triple::armeb:
11077 case llvm::Triple::aarch64:
11078 case llvm::Triple::aarch64_be:
11079 case llvm::Triple::aarch64_32:
11080 case llvm::Triple::ppc:
11081 case llvm::Triple::ppc64:
11082 case llvm::Triple::ppc64le:
11083 case llvm::Triple::x86:
11084 case llvm::Triple::x86_64:
11085 if (Name.compare_lower("cpu"))
11086 return false;
11087 break;
11088 case llvm::Triple::amdgcn:
11089 case llvm::Triple::nvptx:
11090 case llvm::Triple::nvptx64:
11091 if (Name.compare_lower("gpu"))
11092 return false;
11093 break;
11094 case llvm::Triple::UnknownArch:
11095 case llvm::Triple::arc:
11096 case llvm::Triple::avr:
11097 case llvm::Triple::bpfel:
11098 case llvm::Triple::bpfeb:
11099 case llvm::Triple::hexagon:
11100 case llvm::Triple::mips:
11101 case llvm::Triple::mipsel:
11102 case llvm::Triple::mips64:
11103 case llvm::Triple::mips64el:
11104 case llvm::Triple::msp430:
11105 case llvm::Triple::r600:
11106 case llvm::Triple::riscv32:
11107 case llvm::Triple::riscv64:
11108 case llvm::Triple::sparc:
11109 case llvm::Triple::sparcv9:
11110 case llvm::Triple::sparcel:
11111 case llvm::Triple::systemz:
11112 case llvm::Triple::tce:
11113 case llvm::Triple::tcele:
11114 case llvm::Triple::thumb:
11115 case llvm::Triple::thumbeb:
11116 case llvm::Triple::xcore:
11117 case llvm::Triple::le32:
11118 case llvm::Triple::le64:
11119 case llvm::Triple::amdil:
11120 case llvm::Triple::amdil64:
11121 case llvm::Triple::hsail:
11122 case llvm::Triple::hsail64:
11123 case llvm::Triple::spir:
11124 case llvm::Triple::spir64:
11125 case llvm::Triple::kalimba:
11126 case llvm::Triple::shave:
11127 case llvm::Triple::lanai:
11128 case llvm::Triple::wasm32:
11129 case llvm::Triple::wasm64:
11130 case llvm::Triple::renderscript32:
11131 case llvm::Triple::renderscript64:
11132 return false;
11133 }
11134 }
11135 return true;
11136}
11137
11138bool matchesContext(CodeGenModule &CGM,
11139 const CompleteOMPContextSelectorData &ContextData) {
Alexey Bataevfde11e92019-11-07 11:03:10 -050011140 for (const OMPContextSelectorData &Data : ContextData) {
Alexey Bataev5459a902019-11-22 11:42:08 -050011141 switch (Data.Ctx) {
11142 case OMP_CTX_vendor:
11143 assert(Data.CtxSet == OMP_CTX_SET_implementation &&
11144 "Expected implementation context selector set.");
11145 if (!checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(Data))
11146 return false;
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011147 break;
Alexey Bataev5459a902019-11-22 11:42:08 -050011148 case OMP_CTX_kind:
11149 assert(Data.CtxSet == OMP_CTX_SET_device &&
11150 "Expected device context selector set.");
11151 if (!checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>(Data,
11152 CGM))
11153 return false;
Alexey Bataevfde11e92019-11-07 11:03:10 -050011154 break;
Alexey Bataev5459a902019-11-22 11:42:08 -050011155 case OMP_CTX_unknown:
11156 llvm_unreachable("Unknown context selector kind.");
Alexey Bataevfde11e92019-11-07 11:03:10 -050011157 }
11158 }
11159 return true;
11160}
11161
11162static CompleteOMPContextSelectorData
11163translateAttrToContextSelectorData(ASTContext &C,
11164 const OMPDeclareVariantAttr *A) {
11165 CompleteOMPContextSelectorData Data;
11166 for (unsigned I = 0, E = A->scores_size(); I < E; ++I) {
11167 Data.emplace_back();
11168 auto CtxSet = static_cast<OpenMPContextSelectorSetKind>(
11169 *std::next(A->ctxSelectorSets_begin(), I));
11170 auto Ctx = static_cast<OpenMPContextSelectorKind>(
11171 *std::next(A->ctxSelectors_begin(), I));
11172 Data.back().CtxSet = CtxSet;
11173 Data.back().Ctx = Ctx;
11174 const Expr *Score = *std::next(A->scores_begin(), I);
11175 Data.back().Score = Score->EvaluateKnownConstInt(C);
Alexey Bataev5459a902019-11-22 11:42:08 -050011176 switch (Ctx) {
11177 case OMP_CTX_vendor:
11178 assert(CtxSet == OMP_CTX_SET_implementation &&
11179 "Expected implementation context selector set.");
11180 Data.back().Names =
11181 llvm::makeArrayRef(A->implVendors_begin(), A->implVendors_end());
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011182 break;
Alexey Bataev5459a902019-11-22 11:42:08 -050011183 case OMP_CTX_kind:
11184 assert(CtxSet == OMP_CTX_SET_device &&
11185 "Expected device context selector set.");
11186 Data.back().Names =
11187 llvm::makeArrayRef(A->deviceKinds_begin(), A->deviceKinds_end());
Alexey Bataevfde11e92019-11-07 11:03:10 -050011188 break;
Alexey Bataev5459a902019-11-22 11:42:08 -050011189 case OMP_CTX_unknown:
11190 llvm_unreachable("Unknown context selector kind.");
Alexey Bataevfde11e92019-11-07 11:03:10 -050011191 }
11192 }
11193 return Data;
11194}
11195
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011196static bool isStrictSubset(const CompleteOMPContextSelectorData &LHS,
11197 const CompleteOMPContextSelectorData &RHS) {
11198 llvm::SmallDenseMap<std::pair<int, int>, llvm::StringSet<>, 4> RHSData;
11199 for (const OMPContextSelectorData &D : RHS) {
11200 auto &Pair = RHSData.FindAndConstruct(std::make_pair(D.CtxSet, D.Ctx));
11201 Pair.getSecond().insert(D.Names.begin(), D.Names.end());
11202 }
11203 bool AllSetsAreEqual = true;
11204 for (const OMPContextSelectorData &D : LHS) {
11205 auto It = RHSData.find(std::make_pair(D.CtxSet, D.Ctx));
11206 if (It == RHSData.end())
11207 return false;
11208 if (D.Names.size() > It->getSecond().size())
11209 return false;
11210 if (llvm::set_union(It->getSecond(), D.Names))
11211 return false;
11212 AllSetsAreEqual =
11213 AllSetsAreEqual && (D.Names.size() == It->getSecond().size());
11214 }
11215
11216 return LHS.size() != RHS.size() || !AllSetsAreEqual;
11217}
11218
Alexey Bataevfde11e92019-11-07 11:03:10 -050011219static bool greaterCtxScore(const CompleteOMPContextSelectorData &LHS,
11220 const CompleteOMPContextSelectorData &RHS) {
11221 // Score is calculated as sum of all scores + 1.
11222 llvm::APSInt LHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false);
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011223 bool RHSIsSubsetOfLHS = isStrictSubset(RHS, LHS);
11224 if (RHSIsSubsetOfLHS) {
11225 LHSScore = llvm::APSInt::get(0);
11226 } else {
11227 for (const OMPContextSelectorData &Data : LHS) {
11228 if (Data.Score.getBitWidth() > LHSScore.getBitWidth()) {
11229 LHSScore = LHSScore.extend(Data.Score.getBitWidth()) + Data.Score;
11230 } else if (Data.Score.getBitWidth() < LHSScore.getBitWidth()) {
11231 LHSScore += Data.Score.extend(LHSScore.getBitWidth());
11232 } else {
11233 LHSScore += Data.Score;
11234 }
Alexey Bataevfde11e92019-11-07 11:03:10 -050011235 }
11236 }
11237 llvm::APSInt RHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false);
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011238 if (!RHSIsSubsetOfLHS && isStrictSubset(LHS, RHS)) {
11239 RHSScore = llvm::APSInt::get(0);
11240 } else {
11241 for (const OMPContextSelectorData &Data : RHS) {
11242 if (Data.Score.getBitWidth() > RHSScore.getBitWidth()) {
11243 RHSScore = RHSScore.extend(Data.Score.getBitWidth()) + Data.Score;
11244 } else if (Data.Score.getBitWidth() < RHSScore.getBitWidth()) {
11245 RHSScore += Data.Score.extend(RHSScore.getBitWidth());
11246 } else {
11247 RHSScore += Data.Score;
11248 }
Alexey Bataevfde11e92019-11-07 11:03:10 -050011249 }
11250 }
11251 return llvm::APSInt::compareValues(LHSScore, RHSScore) >= 0;
Alexey Bataev0364c762019-10-03 20:49:48 +000011252}
11253
Alexey Bataev2df5f122019-10-01 20:18:32 +000011254/// Finds the variant function that matches current context with its context
11255/// selector.
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011256static const FunctionDecl *getDeclareVariantFunction(CodeGenModule &CGM,
Alexey Bataev0364c762019-10-03 20:49:48 +000011257 const FunctionDecl *FD) {
Alexey Bataev2df5f122019-10-01 20:18:32 +000011258 if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>())
11259 return FD;
11260 // Iterate through all DeclareVariant attributes and check context selectors.
Alexey Bataev0364c762019-10-03 20:49:48 +000011261 const OMPDeclareVariantAttr *TopMostAttr = nullptr;
Alexey Bataevfde11e92019-11-07 11:03:10 -050011262 CompleteOMPContextSelectorData TopMostData;
Alexey Bataev0364c762019-10-03 20:49:48 +000011263 for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) {
Alexey Bataevfde11e92019-11-07 11:03:10 -050011264 CompleteOMPContextSelectorData Data =
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011265 translateAttrToContextSelectorData(CGM.getContext(), A);
11266 if (!matchesContext(CGM, Data))
Alexey Bataevfde11e92019-11-07 11:03:10 -050011267 continue;
Alexey Bataev0364c762019-10-03 20:49:48 +000011268 // If the attribute matches the context, find the attribute with the highest
11269 // score.
Alexey Bataevfde11e92019-11-07 11:03:10 -050011270 if (!TopMostAttr || !greaterCtxScore(TopMostData, Data)) {
11271 TopMostAttr = A;
11272 TopMostData.swap(Data);
11273 }
Alexey Bataev2df5f122019-10-01 20:18:32 +000011274 }
Alexey Bataev0364c762019-10-03 20:49:48 +000011275 if (!TopMostAttr)
Alexey Bataev2df5f122019-10-01 20:18:32 +000011276 return FD;
Alexey Bataev2df5f122019-10-01 20:18:32 +000011277 return cast<FunctionDecl>(
Alexey Bataev0364c762019-10-03 20:49:48 +000011278 cast<DeclRefExpr>(TopMostAttr->getVariantFuncRef()->IgnoreParenImpCasts())
Alexey Bataev2df5f122019-10-01 20:18:32 +000011279 ->getDecl());
11280}
11281
11282bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) {
11283 const auto *D = cast<FunctionDecl>(GD.getDecl());
11284 // If the original function is defined already, use its definition.
11285 StringRef MangledName = CGM.getMangledName(GD);
11286 llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName);
11287 if (Orig && !Orig->isDeclaration())
11288 return false;
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011289 const FunctionDecl *NewFD = getDeclareVariantFunction(CGM, D);
Alexey Bataev2df5f122019-10-01 20:18:32 +000011290 // Emit original function if it does not have declare variant attribute or the
11291 // context does not match.
11292 if (NewFD == D)
11293 return false;
11294 GlobalDecl NewGD = GD.getWithDecl(NewFD);
Alexey Bataevc2cd2d42019-10-10 17:28:10 +000011295 if (tryEmitDeclareVariant(NewGD, GD, Orig, IsForDefinition)) {
Alexey Bataev2df5f122019-10-01 20:18:32 +000011296 DeferredVariantFunction.erase(D);
11297 return true;
11298 }
11299 DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD)));
11300 return true;
11301}
11302
James Y Knight9871db02019-02-05 16:42:33 +000011303llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011304 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11305 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11306 llvm_unreachable("Not supported in SIMD-only mode");
11307}
11308
James Y Knight9871db02019-02-05 16:42:33 +000011309llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011310 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11311 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11312 llvm_unreachable("Not supported in SIMD-only mode");
11313}
11314
James Y Knight9871db02019-02-05 16:42:33 +000011315llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011316 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11317 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
11318 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
11319 bool Tied, unsigned &NumberOfParts) {
11320 llvm_unreachable("Not supported in SIMD-only mode");
11321}
11322
11323void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF,
11324 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000011325 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011326 ArrayRef<llvm::Value *> CapturedVars,
11327 const Expr *IfCond) {
11328 llvm_unreachable("Not supported in SIMD-only mode");
11329}
11330
11331void CGOpenMPSIMDRuntime::emitCriticalRegion(
11332 CodeGenFunction &CGF, StringRef CriticalName,
11333 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
11334 const Expr *Hint) {
11335 llvm_unreachable("Not supported in SIMD-only mode");
11336}
11337
11338void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF,
11339 const RegionCodeGenTy &MasterOpGen,
11340 SourceLocation Loc) {
11341 llvm_unreachable("Not supported in SIMD-only mode");
11342}
11343
11344void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
11345 SourceLocation Loc) {
11346 llvm_unreachable("Not supported in SIMD-only mode");
11347}
11348
11349void CGOpenMPSIMDRuntime::emitTaskgroupRegion(
11350 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen,
11351 SourceLocation Loc) {
11352 llvm_unreachable("Not supported in SIMD-only mode");
11353}
11354
11355void CGOpenMPSIMDRuntime::emitSingleRegion(
11356 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen,
11357 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars,
11358 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs,
11359 ArrayRef<const Expr *> AssignmentOps) {
11360 llvm_unreachable("Not supported in SIMD-only mode");
11361}
11362
11363void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF,
11364 const RegionCodeGenTy &OrderedOpGen,
11365 SourceLocation Loc,
11366 bool IsThreads) {
11367 llvm_unreachable("Not supported in SIMD-only mode");
11368}
11369
11370void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF,
11371 SourceLocation Loc,
11372 OpenMPDirectiveKind Kind,
11373 bool EmitChecks,
11374 bool ForceSimpleCall) {
11375 llvm_unreachable("Not supported in SIMD-only mode");
11376}
11377
11378void CGOpenMPSIMDRuntime::emitForDispatchInit(
11379 CodeGenFunction &CGF, SourceLocation Loc,
11380 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
11381 bool Ordered, const DispatchRTInput &DispatchValues) {
11382 llvm_unreachable("Not supported in SIMD-only mode");
11383}
11384
11385void CGOpenMPSIMDRuntime::emitForStaticInit(
11386 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind,
11387 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) {
11388 llvm_unreachable("Not supported in SIMD-only mode");
11389}
11390
11391void CGOpenMPSIMDRuntime::emitDistributeStaticInit(
11392 CodeGenFunction &CGF, SourceLocation Loc,
11393 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) {
11394 llvm_unreachable("Not supported in SIMD-only mode");
11395}
11396
11397void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
11398 SourceLocation Loc,
11399 unsigned IVSize,
11400 bool IVSigned) {
11401 llvm_unreachable("Not supported in SIMD-only mode");
11402}
11403
11404void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF,
11405 SourceLocation Loc,
11406 OpenMPDirectiveKind DKind) {
11407 llvm_unreachable("Not supported in SIMD-only mode");
11408}
11409
11410llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF,
11411 SourceLocation Loc,
11412 unsigned IVSize, bool IVSigned,
11413 Address IL, Address LB,
11414 Address UB, Address ST) {
11415 llvm_unreachable("Not supported in SIMD-only mode");
11416}
11417
11418void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
11419 llvm::Value *NumThreads,
11420 SourceLocation Loc) {
11421 llvm_unreachable("Not supported in SIMD-only mode");
11422}
11423
11424void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF,
11425 OpenMPProcBindClauseKind ProcBind,
11426 SourceLocation Loc) {
11427 llvm_unreachable("Not supported in SIMD-only mode");
11428}
11429
11430Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
11431 const VarDecl *VD,
11432 Address VDAddr,
11433 SourceLocation Loc) {
11434 llvm_unreachable("Not supported in SIMD-only mode");
11435}
11436
11437llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition(
11438 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit,
11439 CodeGenFunction *CGF) {
11440 llvm_unreachable("Not supported in SIMD-only mode");
11441}
11442
11443Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate(
11444 CodeGenFunction &CGF, QualType VarType, StringRef Name) {
11445 llvm_unreachable("Not supported in SIMD-only mode");
11446}
11447
11448void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF,
11449 ArrayRef<const Expr *> Vars,
11450 SourceLocation Loc) {
11451 llvm_unreachable("Not supported in SIMD-only mode");
11452}
11453
11454void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
11455 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000011456 llvm::Function *TaskFunction,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011457 QualType SharedsTy, Address Shareds,
11458 const Expr *IfCond,
11459 const OMPTaskDataTy &Data) {
11460 llvm_unreachable("Not supported in SIMD-only mode");
11461}
11462
11463void CGOpenMPSIMDRuntime::emitTaskLoopCall(
11464 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000011465 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011466 const Expr *IfCond, const OMPTaskDataTy &Data) {
11467 llvm_unreachable("Not supported in SIMD-only mode");
11468}
11469
11470void CGOpenMPSIMDRuntime::emitReduction(
11471 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates,
11472 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
11473 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) {
11474 assert(Options.SimpleReduction && "Only simple reduction is expected.");
11475 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
11476 ReductionOps, Options);
11477}
11478
11479llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit(
11480 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
11481 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
11482 llvm_unreachable("Not supported in SIMD-only mode");
11483}
11484
11485void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
11486 SourceLocation Loc,
11487 ReductionCodeGen &RCG,
11488 unsigned N) {
11489 llvm_unreachable("Not supported in SIMD-only mode");
11490}
11491
11492Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
11493 SourceLocation Loc,
11494 llvm::Value *ReductionsPtr,
11495 LValue SharedLVal) {
11496 llvm_unreachable("Not supported in SIMD-only mode");
11497}
11498
11499void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
11500 SourceLocation Loc) {
11501 llvm_unreachable("Not supported in SIMD-only mode");
11502}
11503
11504void CGOpenMPSIMDRuntime::emitCancellationPointCall(
11505 CodeGenFunction &CGF, SourceLocation Loc,
11506 OpenMPDirectiveKind CancelRegion) {
11507 llvm_unreachable("Not supported in SIMD-only mode");
11508}
11509
11510void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF,
11511 SourceLocation Loc, const Expr *IfCond,
11512 OpenMPDirectiveKind CancelRegion) {
11513 llvm_unreachable("Not supported in SIMD-only mode");
11514}
11515
11516void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction(
11517 const OMPExecutableDirective &D, StringRef ParentName,
11518 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
11519 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
11520 llvm_unreachable("Not supported in SIMD-only mode");
11521}
11522
Alexey Bataevec7946e2019-09-23 14:06:51 +000011523void CGOpenMPSIMDRuntime::emitTargetCall(
11524 CodeGenFunction &CGF, const OMPExecutableDirective &D,
11525 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
11526 const Expr *Device,
11527 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
11528 const OMPLoopDirective &D)>
11529 SizeEmitter) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011530 llvm_unreachable("Not supported in SIMD-only mode");
11531}
11532
11533bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) {
11534 llvm_unreachable("Not supported in SIMD-only mode");
11535}
11536
11537bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
11538 llvm_unreachable("Not supported in SIMD-only mode");
11539}
11540
11541bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) {
11542 return false;
11543}
11544
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011545void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF,
11546 const OMPExecutableDirective &D,
11547 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000011548 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011549 ArrayRef<llvm::Value *> CapturedVars) {
11550 llvm_unreachable("Not supported in SIMD-only mode");
11551}
11552
11553void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
11554 const Expr *NumTeams,
11555 const Expr *ThreadLimit,
11556 SourceLocation Loc) {
11557 llvm_unreachable("Not supported in SIMD-only mode");
11558}
11559
11560void CGOpenMPSIMDRuntime::emitTargetDataCalls(
11561 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
11562 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
11563 llvm_unreachable("Not supported in SIMD-only mode");
11564}
11565
11566void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
11567 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
11568 const Expr *Device) {
11569 llvm_unreachable("Not supported in SIMD-only mode");
11570}
11571
11572void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000011573 const OMPLoopDirective &D,
11574 ArrayRef<Expr *> NumIterations) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011575 llvm_unreachable("Not supported in SIMD-only mode");
11576}
11577
11578void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
11579 const OMPDependClause *C) {
11580 llvm_unreachable("Not supported in SIMD-only mode");
11581}
11582
11583const VarDecl *
11584CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD,
11585 const VarDecl *NativeParam) const {
11586 llvm_unreachable("Not supported in SIMD-only mode");
11587}
11588
11589Address
11590CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF,
11591 const VarDecl *NativeParam,
11592 const VarDecl *TargetParam) const {
11593 llvm_unreachable("Not supported in SIMD-only mode");
11594}