blob: 7f6f498a3392cf2980cd30097e383a2bea8172a7 [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 Hatanakaf139ae32019-12-03 15:17:01 -0800360 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(CGF); });
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 Hatanakaf139ae32019-12-03 15:17:01 -0800845 InitRVal = RValue::getAggregate(LV.getAddress(CGF));
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 Hatanakaf139ae32019-12-03 15:17:01 -0800969 DRD, SharedLVal.getAddress(CGF));
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 Hatanakaf139ae32019-12-03 15:17:01 -08001010 auto *ElemType = cast<llvm::PointerType>(
1011 SharedAddresses[N].first.getPointer(CGF)->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 Hatanakaf139ae32019-12-03 15:17:01 -08001015 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(CGF),
1016 SharedAddresses[N].first.getPointer(CGF));
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 Hatanakaf139ae32019-12-03 15:17:01 -08001066 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(CGF),
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 Hatanakaf139ae32019-12-03 15:17:01 -08001074 PrivateAddr, SharedLVal.getAddress(CGF),
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 Hatanakaf139ae32019-12-03 15:17:01 -08001111 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001112 } else {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001113 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), 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 Hatanakaf139ae32019-12-03 15:17:01 -08001119 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF),
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 Hatanakaf139ae32019-12-03 15:17:01 -08001183 BaseLValue.getPointer(CGF), SharedAddresses[N].first.getPointer(CGF));
Jonas Hahnfeld273d2612017-12-06 19:15:28 +00001184 llvm::Value *PrivatePointer =
1185 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1186 PrivateAddr.getPointer(),
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001187 SharedAddresses[N].first.getAddress(CGF).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 Hatanakaf139ae32019-12-03 15:17:01 -08001191 OriginalBaseLValue.getAddress(CGF).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 Hatanakaf139ae32019-12-03 15:17:01 -08001384 .getAddress(CGF);
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 Hatanakaf139ae32019-12-03 15:17:01 -08001389 .getAddress(CGF);
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 Hatanakaf139ae32019-12-03 15:17:01 -08001499 .getPointer(CGF)};
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 Hatanakaf139ae32019-12-03 15:17:01 -08001710 !isa<llvm::Instruction>(LVal.getPointer(CGF)) ||
1711 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() ==
1712 TopBlock ||
1713 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() ==
Alexey Bataev780f5552019-10-17 17:12:03 +00001714 CGF.Builder.GetInsertBlock()) {
Alexey Bataev1e491372018-01-23 18:44:14 +00001715 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc);
Alexey Bataevaee18552017-08-16 14:01:00 +00001716 // If value loaded in entry block, cache it and use it everywhere in
1717 // function.
Alexey Bataev780f5552019-10-17 17:12:03 +00001718 if (CGF.Builder.GetInsertBlock() == TopBlock) {
Alexey Bataevaee18552017-08-16 14:01:00 +00001719 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1720 Elem.second.ThreadID = ThreadID;
1721 }
1722 return ThreadID;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001723 }
Alexey Bataevd6c57552014-07-25 07:55:17 +00001724 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001725 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001726
1727 // This is not an outlined function region - need to call __kmpc_int32
1728 // kmpc_global_thread_num(ident_t *loc).
1729 // Generate thread id value and cache this value for use across the
1730 // function.
Alexey Bataevfd006c42018-10-05 15:08:53 +00001731 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1732 if (!Elem.second.ServiceInsertPt)
1733 setLocThreadIdInsertPt(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001734 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001735 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001736 llvm::CallInst *Call = CGF.Builder.CreateCall(
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001737 createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
1738 emitUpdateLocation(CGF, Loc));
1739 Call->setCallingConv(CGF.getRuntimeCC());
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001740 Elem.second.ThreadID = Call;
1741 return Call;
Alexey Bataev9959db52014-05-06 10:08:46 +00001742}
1743
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001744void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001745 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataevfd006c42018-10-05 15:08:53 +00001746 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) {
1747 clearLocThreadIdInsertPt(CGF);
Alexey Bataev03b340a2014-10-21 03:16:40 +00001748 OpenMPLocThreadIDMap.erase(CGF.CurFn);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001749 }
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001750 if (FunctionUDRMap.count(CGF.CurFn) > 0) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001751 for(auto *D : FunctionUDRMap[CGF.CurFn])
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001752 UDRMap.erase(D);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001753 FunctionUDRMap.erase(CGF.CurFn);
1754 }
Michael Krused47b9432019-08-05 18:43:21 +00001755 auto I = FunctionUDMMap.find(CGF.CurFn);
1756 if (I != FunctionUDMMap.end()) {
1757 for(auto *D : I->second)
1758 UDMMap.erase(D);
1759 FunctionUDMMap.erase(I);
1760 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001761}
1762
1763llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001764 return IdentTy->getPointerTo();
Alexey Bataev9959db52014-05-06 10:08:46 +00001765}
1766
1767llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001768 if (!Kmpc_MicroTy) {
1769 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
1770 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
1771 llvm::PointerType::getUnqual(CGM.Int32Ty)};
1772 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
1773 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001774 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
1775}
1776
James Y Knight9871db02019-02-05 16:42:33 +00001777llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
1778 llvm::FunctionCallee RTLFn = nullptr;
Alexey Bataev50b3c952016-02-19 10:38:26 +00001779 switch (static_cast<OpenMPRTLFunction>(Function)) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001780 case OMPRTL__kmpc_fork_call: {
1781 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
1782 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +00001783 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1784 getKmpc_MicroPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001785 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001786 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
Alexey Bataev9959db52014-05-06 10:08:46 +00001787 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
James Y Knight9871db02019-02-05 16:42:33 +00001788 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) {
Johannes Doerfertac991bb2019-01-19 05:36:54 +00001789 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
1790 llvm::LLVMContext &Ctx = F->getContext();
1791 llvm::MDBuilder MDB(Ctx);
1792 // Annotate the callback behavior of the __kmpc_fork_call:
1793 // - The callback callee is argument number 2 (microtask).
1794 // - The first two arguments of the callback callee are unknown (-1).
1795 // - All variadic arguments to the __kmpc_fork_call are passed to the
1796 // callback callee.
1797 F->addMetadata(
1798 llvm::LLVMContext::MD_callback,
1799 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
1800 2, {-1, -1},
1801 /* VarArgsArePassed */ true)}));
1802 }
1803 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001804 break;
1805 }
1806 case OMPRTL__kmpc_global_thread_num: {
1807 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +00001808 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001809 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001810 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
Alexey Bataev9959db52014-05-06 10:08:46 +00001811 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
1812 break;
1813 }
Alexey Bataev97720002014-11-11 04:05:39 +00001814 case OMPRTL__kmpc_threadprivate_cached: {
1815 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
1816 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
1817 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1818 CGM.VoidPtrTy, CGM.SizeTy,
1819 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001820 auto *FnTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001821 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
1822 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
1823 break;
1824 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001825 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001826 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
1827 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001828 llvm::Type *TypeParams[] = {
1829 getIdentTyPointerTy(), CGM.Int32Ty,
1830 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001831 auto *FnTy =
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001832 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1833 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
1834 break;
1835 }
Alexey Bataevfc57d162015-12-15 10:55:09 +00001836 case OMPRTL__kmpc_critical_with_hint: {
1837 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid,
1838 // kmp_critical_name *crit, uintptr_t hint);
1839 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1840 llvm::PointerType::getUnqual(KmpCriticalNameTy),
1841 CGM.IntPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001842 auto *FnTy =
Alexey Bataevfc57d162015-12-15 10:55:09 +00001843 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1844 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint");
1845 break;
1846 }
Alexey Bataev97720002014-11-11 04:05:39 +00001847 case OMPRTL__kmpc_threadprivate_register: {
1848 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
1849 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
1850 // typedef void *(*kmpc_ctor)(void *);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001851 auto *KmpcCtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001852 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1853 /*isVarArg*/ false)->getPointerTo();
1854 // typedef void *(*kmpc_cctor)(void *, void *);
1855 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001856 auto *KmpcCopyCtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001857 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001858 /*isVarArg*/ false)
1859 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00001860 // typedef void (*kmpc_dtor)(void *);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001861 auto *KmpcDtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001862 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
1863 ->getPointerTo();
1864 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
1865 KmpcCopyCtorTy, KmpcDtorTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001866 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
Alexey Bataev97720002014-11-11 04:05:39 +00001867 /*isVarArg*/ false);
1868 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
1869 break;
1870 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001871 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001872 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
1873 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001874 llvm::Type *TypeParams[] = {
1875 getIdentTyPointerTy(), CGM.Int32Ty,
1876 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001877 auto *FnTy =
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001878 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1879 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
1880 break;
1881 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001882 case OMPRTL__kmpc_cancel_barrier: {
1883 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
1884 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001885 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001886 auto *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001887 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1888 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001889 break;
1890 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001891 case OMPRTL__kmpc_barrier: {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001892 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001893 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001894 auto *FnTy =
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001895 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1896 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
1897 break;
1898 }
Alexander Musmanc6388682014-12-15 07:07:06 +00001899 case OMPRTL__kmpc_for_static_fini: {
1900 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
1901 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001902 auto *FnTy =
Alexander Musmanc6388682014-12-15 07:07:06 +00001903 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1904 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
1905 break;
1906 }
Alexey Bataevb2059782014-10-13 08:23:51 +00001907 case OMPRTL__kmpc_push_num_threads: {
1908 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
1909 // kmp_int32 num_threads)
1910 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1911 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001912 auto *FnTy =
Alexey Bataevb2059782014-10-13 08:23:51 +00001913 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1914 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
1915 break;
1916 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001917 case OMPRTL__kmpc_serialized_parallel: {
1918 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
1919 // global_tid);
1920 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001921 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001922 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1923 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
1924 break;
1925 }
1926 case OMPRTL__kmpc_end_serialized_parallel: {
1927 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
1928 // global_tid);
1929 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001930 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001931 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1932 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
1933 break;
1934 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001935 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001936 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001937 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001938 auto *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001939 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001940 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
1941 break;
1942 }
Alexey Bataev8d690652014-12-04 07:23:53 +00001943 case OMPRTL__kmpc_master: {
1944 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
1945 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001946 auto *FnTy =
Alexey Bataev8d690652014-12-04 07:23:53 +00001947 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1948 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
1949 break;
1950 }
1951 case OMPRTL__kmpc_end_master: {
1952 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
1953 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001954 auto *FnTy =
Alexey Bataev8d690652014-12-04 07:23:53 +00001955 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1956 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
1957 break;
1958 }
Alexey Bataev9f797f32015-02-05 05:57:51 +00001959 case OMPRTL__kmpc_omp_taskyield: {
1960 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
1961 // int end_part);
1962 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001963 auto *FnTy =
Alexey Bataev9f797f32015-02-05 05:57:51 +00001964 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1965 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
1966 break;
1967 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001968 case OMPRTL__kmpc_single: {
1969 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
1970 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001971 auto *FnTy =
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001972 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1973 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
1974 break;
1975 }
1976 case OMPRTL__kmpc_end_single: {
1977 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
1978 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001979 auto *FnTy =
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001980 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1981 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
1982 break;
1983 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00001984 case OMPRTL__kmpc_omp_task_alloc: {
1985 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
1986 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
1987 // kmp_routine_entry_t *task_entry);
1988 assert(KmpRoutineEntryPtrTy != nullptr &&
1989 "Type kmp_routine_entry_t must be created.");
1990 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1991 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
1992 // Return void * and then cast to particular kmp_task_t type.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001993 auto *FnTy =
Alexey Bataev62b63b12015-03-10 07:28:44 +00001994 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
1995 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
1996 break;
1997 }
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00001998 case OMPRTL__kmpc_omp_target_task_alloc: {
1999 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid,
2000 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
2001 // kmp_routine_entry_t *task_entry, kmp_int64 device_id);
2002 assert(KmpRoutineEntryPtrTy != nullptr &&
2003 "Type kmp_routine_entry_t must be created.");
2004 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
2005 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy,
2006 CGM.Int64Ty};
2007 // Return void * and then cast to particular kmp_task_t type.
2008 auto *FnTy =
2009 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2010 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc");
2011 break;
2012 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002013 case OMPRTL__kmpc_omp_task: {
2014 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2015 // *new_task);
2016 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2017 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002018 auto *FnTy =
Alexey Bataev62b63b12015-03-10 07:28:44 +00002019 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2020 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
2021 break;
2022 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00002023 case OMPRTL__kmpc_copyprivate: {
2024 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
Alexey Bataev66beaa92015-04-30 03:47:32 +00002025 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
Alexey Bataeva63048e2015-03-23 06:18:07 +00002026 // kmp_int32 didit);
2027 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2028 auto *CpyFnTy =
2029 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
Alexey Bataev66beaa92015-04-30 03:47:32 +00002030 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
Alexey Bataeva63048e2015-03-23 06:18:07 +00002031 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
2032 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002033 auto *FnTy =
Alexey Bataeva63048e2015-03-23 06:18:07 +00002034 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2035 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
2036 break;
2037 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002038 case OMPRTL__kmpc_reduce: {
2039 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
2040 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
2041 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
2042 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2043 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
2044 /*isVarArg=*/false);
2045 llvm::Type *TypeParams[] = {
2046 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
2047 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
2048 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002049 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002050 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2051 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
2052 break;
2053 }
2054 case OMPRTL__kmpc_reduce_nowait: {
2055 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
2056 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
2057 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
2058 // *lck);
2059 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2060 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
2061 /*isVarArg=*/false);
2062 llvm::Type *TypeParams[] = {
2063 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
2064 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
2065 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002066 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002067 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2068 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
2069 break;
2070 }
2071 case OMPRTL__kmpc_end_reduce: {
2072 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
2073 // kmp_critical_name *lck);
2074 llvm::Type *TypeParams[] = {
2075 getIdentTyPointerTy(), CGM.Int32Ty,
2076 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002077 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002078 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2079 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
2080 break;
2081 }
2082 case OMPRTL__kmpc_end_reduce_nowait: {
2083 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
2084 // kmp_critical_name *lck);
2085 llvm::Type *TypeParams[] = {
2086 getIdentTyPointerTy(), CGM.Int32Ty,
2087 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002088 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002089 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2090 RTLFn =
2091 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
2092 break;
2093 }
Alexey Bataev1d677132015-04-22 13:57:31 +00002094 case OMPRTL__kmpc_omp_task_begin_if0: {
2095 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2096 // *new_task);
2097 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2098 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002099 auto *FnTy =
Alexey Bataev1d677132015-04-22 13:57:31 +00002100 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2101 RTLFn =
2102 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
2103 break;
2104 }
2105 case OMPRTL__kmpc_omp_task_complete_if0: {
2106 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2107 // *new_task);
2108 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2109 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002110 auto *FnTy =
Alexey Bataev1d677132015-04-22 13:57:31 +00002111 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2112 RTLFn = CGM.CreateRuntimeFunction(FnTy,
2113 /*Name=*/"__kmpc_omp_task_complete_if0");
2114 break;
2115 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002116 case OMPRTL__kmpc_ordered: {
2117 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
2118 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002119 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002120 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2121 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
2122 break;
2123 }
2124 case OMPRTL__kmpc_end_ordered: {
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002125 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002126 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002127 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002128 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2129 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
2130 break;
2131 }
Alexey Bataev8b8e2022015-04-27 05:22:09 +00002132 case OMPRTL__kmpc_omp_taskwait: {
2133 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
2134 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002135 auto *FnTy =
Alexey Bataev8b8e2022015-04-27 05:22:09 +00002136 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2137 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
2138 break;
2139 }
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002140 case OMPRTL__kmpc_taskgroup: {
2141 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
2142 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002143 auto *FnTy =
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002144 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2145 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
2146 break;
2147 }
2148 case OMPRTL__kmpc_end_taskgroup: {
2149 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
2150 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002151 auto *FnTy =
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002152 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2153 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
2154 break;
2155 }
Alexey Bataev7f210c62015-06-18 13:40:03 +00002156 case OMPRTL__kmpc_push_proc_bind: {
2157 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
2158 // int proc_bind)
2159 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002160 auto *FnTy =
Alexey Bataev7f210c62015-06-18 13:40:03 +00002161 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2162 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
2163 break;
2164 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002165 case OMPRTL__kmpc_omp_task_with_deps: {
2166 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
2167 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
2168 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
2169 llvm::Type *TypeParams[] = {
2170 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
2171 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002172 auto *FnTy =
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002173 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2174 RTLFn =
2175 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
2176 break;
2177 }
2178 case OMPRTL__kmpc_omp_wait_deps: {
2179 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
2180 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
2181 // kmp_depend_info_t *noalias_dep_list);
2182 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2183 CGM.Int32Ty, CGM.VoidPtrTy,
2184 CGM.Int32Ty, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002185 auto *FnTy =
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002186 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2187 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
2188 break;
2189 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00002190 case OMPRTL__kmpc_cancellationpoint: {
2191 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
2192 // global_tid, kmp_int32 cncl_kind)
2193 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002194 auto *FnTy =
Alexey Bataev0f34da12015-07-02 04:17:07 +00002195 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2196 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
2197 break;
2198 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002199 case OMPRTL__kmpc_cancel: {
2200 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
2201 // kmp_int32 cncl_kind)
2202 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002203 auto *FnTy =
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002204 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2205 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
2206 break;
2207 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002208 case OMPRTL__kmpc_push_num_teams: {
2209 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid,
2210 // kmp_int32 num_teams, kmp_int32 num_threads)
2211 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
2212 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002213 auto *FnTy =
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002214 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2215 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams");
2216 break;
2217 }
2218 case OMPRTL__kmpc_fork_teams: {
2219 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
2220 // microtask, ...);
2221 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2222 getKmpc_MicroPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002223 auto *FnTy =
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002224 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
2225 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams");
James Y Knight9871db02019-02-05 16:42:33 +00002226 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) {
Johannes Doerfertac991bb2019-01-19 05:36:54 +00002227 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
2228 llvm::LLVMContext &Ctx = F->getContext();
2229 llvm::MDBuilder MDB(Ctx);
2230 // Annotate the callback behavior of the __kmpc_fork_teams:
2231 // - The callback callee is argument number 2 (microtask).
2232 // - The first two arguments of the callback callee are unknown (-1).
2233 // - All variadic arguments to the __kmpc_fork_teams are passed to the
2234 // callback callee.
2235 F->addMetadata(
2236 llvm::LLVMContext::MD_callback,
2237 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
2238 2, {-1, -1},
2239 /* VarArgsArePassed */ true)}));
2240 }
2241 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002242 break;
2243 }
Alexey Bataev7292c292016-04-25 12:22:29 +00002244 case OMPRTL__kmpc_taskloop: {
2245 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
2246 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
2247 // sched, kmp_uint64 grainsize, void *task_dup);
2248 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
2249 CGM.IntTy,
2250 CGM.VoidPtrTy,
2251 CGM.IntTy,
2252 CGM.Int64Ty->getPointerTo(),
2253 CGM.Int64Ty->getPointerTo(),
2254 CGM.Int64Ty,
2255 CGM.IntTy,
2256 CGM.IntTy,
2257 CGM.Int64Ty,
2258 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002259 auto *FnTy =
Alexey Bataev7292c292016-04-25 12:22:29 +00002260 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2261 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop");
2262 break;
2263 }
Alexey Bataev8b427062016-05-25 12:36:08 +00002264 case OMPRTL__kmpc_doacross_init: {
2265 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32
2266 // num_dims, struct kmp_dim *dims);
2267 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
2268 CGM.Int32Ty,
2269 CGM.Int32Ty,
2270 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002271 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002272 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2273 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init");
2274 break;
2275 }
2276 case OMPRTL__kmpc_doacross_fini: {
2277 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid);
2278 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002279 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002280 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2281 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini");
2282 break;
2283 }
2284 case OMPRTL__kmpc_doacross_post: {
2285 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64
2286 // *vec);
2287 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2288 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002289 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002290 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2291 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post");
2292 break;
2293 }
2294 case OMPRTL__kmpc_doacross_wait: {
2295 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64
2296 // *vec);
2297 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2298 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002299 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002300 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2301 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait");
2302 break;
2303 }
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002304 case OMPRTL__kmpc_task_reduction_init: {
2305 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void
2306 // *data);
2307 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002308 auto *FnTy =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002309 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2310 RTLFn =
2311 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init");
2312 break;
2313 }
2314 case OMPRTL__kmpc_task_reduction_get_th_data: {
2315 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
2316 // *d);
2317 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002318 auto *FnTy =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002319 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2320 RTLFn = CGM.CreateRuntimeFunction(
2321 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data");
2322 break;
2323 }
Alexey Bataev4f680db2019-03-19 16:41:16 +00002324 case OMPRTL__kmpc_alloc: {
Alexey Bataev6cf7b712019-04-08 19:06:42 +00002325 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t
2326 // al); omp_allocator_handle_t type is void *.
2327 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy};
Alexey Bataev4f680db2019-03-19 16:41:16 +00002328 auto *FnTy =
2329 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2330 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc");
2331 break;
2332 }
2333 case OMPRTL__kmpc_free: {
Alexey Bataev6cf7b712019-04-08 19:06:42 +00002334 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t
2335 // al); omp_allocator_handle_t type is void *.
2336 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataev4f680db2019-03-19 16:41:16 +00002337 auto *FnTy =
2338 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2339 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free");
2340 break;
2341 }
Alexey Bataev7bb33532019-01-07 21:30:43 +00002342 case OMPRTL__kmpc_push_target_tripcount: {
2343 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64
2344 // size);
2345 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty};
2346 llvm::FunctionType *FnTy =
2347 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2348 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount");
2349 break;
2350 }
Samuel Antaobed3c462015-10-02 16:14:20 +00002351 case OMPRTL__tgt_target: {
George Rokos63bc9d62017-11-21 18:25:12 +00002352 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002353 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Samuel Antaobed3c462015-10-02 16:14:20 +00002354 // *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002355 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaobed3c462015-10-02 16:14:20 +00002356 CGM.VoidPtrTy,
2357 CGM.Int32Ty,
2358 CGM.VoidPtrPtrTy,
2359 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002360 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002361 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002362 auto *FnTy =
Samuel Antaobed3c462015-10-02 16:14:20 +00002363 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2364 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
2365 break;
2366 }
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002367 case OMPRTL__tgt_target_nowait: {
2368 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002369 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes,
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002370 // int64_t *arg_types);
2371 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2372 CGM.VoidPtrTy,
2373 CGM.Int32Ty,
2374 CGM.VoidPtrPtrTy,
2375 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002376 CGM.Int64Ty->getPointerTo(),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002377 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002378 auto *FnTy =
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002379 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2380 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait");
2381 break;
2382 }
Samuel Antaob68e2db2016-03-03 16:20:23 +00002383 case OMPRTL__tgt_target_teams: {
George Rokos63bc9d62017-11-21 18:25:12 +00002384 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002385 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes,
George Rokos63bc9d62017-11-21 18:25:12 +00002386 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
2387 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaob68e2db2016-03-03 16:20:23 +00002388 CGM.VoidPtrTy,
2389 CGM.Int32Ty,
2390 CGM.VoidPtrPtrTy,
2391 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002392 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002393 CGM.Int64Ty->getPointerTo(),
Samuel Antaob68e2db2016-03-03 16:20:23 +00002394 CGM.Int32Ty,
2395 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002396 auto *FnTy =
Samuel Antaob68e2db2016-03-03 16:20:23 +00002397 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2398 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams");
2399 break;
2400 }
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002401 case OMPRTL__tgt_target_teams_nowait: {
2402 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void
Alexey Bataeva90fc662019-06-25 16:00:43 +00002403 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002404 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
2405 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2406 CGM.VoidPtrTy,
2407 CGM.Int32Ty,
2408 CGM.VoidPtrPtrTy,
2409 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002410 CGM.Int64Ty->getPointerTo(),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002411 CGM.Int64Ty->getPointerTo(),
2412 CGM.Int32Ty,
2413 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002414 auto *FnTy =
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002415 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2416 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait");
2417 break;
2418 }
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00002419 case OMPRTL__tgt_register_requires: {
2420 // Build void __tgt_register_requires(int64_t flags);
2421 llvm::Type *TypeParams[] = {CGM.Int64Ty};
2422 auto *FnTy =
2423 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2424 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires");
2425 break;
2426 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00002427 case OMPRTL__tgt_register_lib: {
2428 // Build void __tgt_register_lib(__tgt_bin_desc *desc);
2429 QualType ParamTy =
2430 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
2431 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002432 auto *FnTy =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002433 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2434 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib");
2435 break;
2436 }
2437 case OMPRTL__tgt_unregister_lib: {
2438 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc);
2439 QualType ParamTy =
2440 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
2441 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002442 auto *FnTy =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002443 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2444 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib");
2445 break;
2446 }
Samuel Antaodf158d52016-04-27 22:58:19 +00002447 case OMPRTL__tgt_target_data_begin: {
George Rokos63bc9d62017-11-21 18:25:12 +00002448 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002449 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002450 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaodf158d52016-04-27 22:58:19 +00002451 CGM.Int32Ty,
2452 CGM.VoidPtrPtrTy,
2453 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002454 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002455 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002456 auto *FnTy =
Samuel Antaodf158d52016-04-27 22:58:19 +00002457 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2458 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin");
2459 break;
2460 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002461 case OMPRTL__tgt_target_data_begin_nowait: {
2462 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002463 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002464 // *arg_types);
2465 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2466 CGM.Int32Ty,
2467 CGM.VoidPtrPtrTy,
2468 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002469 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002470 CGM.Int64Ty->getPointerTo()};
2471 auto *FnTy =
2472 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2473 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait");
2474 break;
2475 }
Samuel Antaodf158d52016-04-27 22:58:19 +00002476 case OMPRTL__tgt_target_data_end: {
George Rokos63bc9d62017-11-21 18:25:12 +00002477 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002478 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002479 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaodf158d52016-04-27 22:58:19 +00002480 CGM.Int32Ty,
2481 CGM.VoidPtrPtrTy,
2482 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002483 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002484 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002485 auto *FnTy =
Samuel Antaodf158d52016-04-27 22:58:19 +00002486 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2487 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end");
2488 break;
2489 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002490 case OMPRTL__tgt_target_data_end_nowait: {
2491 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002492 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002493 // *arg_types);
2494 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2495 CGM.Int32Ty,
2496 CGM.VoidPtrPtrTy,
2497 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002498 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002499 CGM.Int64Ty->getPointerTo()};
2500 auto *FnTy =
2501 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2502 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait");
2503 break;
2504 }
Samuel Antao8d2d7302016-05-26 18:30:22 +00002505 case OMPRTL__tgt_target_data_update: {
George Rokos63bc9d62017-11-21 18:25:12 +00002506 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002507 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002508 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antao8d2d7302016-05-26 18:30:22 +00002509 CGM.Int32Ty,
2510 CGM.VoidPtrPtrTy,
2511 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002512 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002513 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002514 auto *FnTy =
Samuel Antao8d2d7302016-05-26 18:30:22 +00002515 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2516 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update");
2517 break;
2518 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002519 case OMPRTL__tgt_target_data_update_nowait: {
2520 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002521 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002522 // *arg_types);
2523 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2524 CGM.Int32Ty,
2525 CGM.VoidPtrPtrTy,
2526 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002527 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002528 CGM.Int64Ty->getPointerTo()};
2529 auto *FnTy =
2530 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2531 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait");
2532 break;
2533 }
Michael Krused47b9432019-08-05 18:43:21 +00002534 case OMPRTL__tgt_mapper_num_components: {
2535 // Build int64_t __tgt_mapper_num_components(void *rt_mapper_handle);
2536 llvm::Type *TypeParams[] = {CGM.VoidPtrTy};
2537 auto *FnTy =
2538 llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false);
2539 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_mapper_num_components");
2540 break;
2541 }
2542 case OMPRTL__tgt_push_mapper_component: {
2543 // Build void __tgt_push_mapper_component(void *rt_mapper_handle, void
2544 // *base, void *begin, int64_t size, int64_t type);
2545 llvm::Type *TypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.VoidPtrTy,
2546 CGM.Int64Ty, CGM.Int64Ty};
2547 auto *FnTy =
2548 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2549 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_push_mapper_component");
2550 break;
2551 }
Alexey Bataev9959db52014-05-06 10:08:46 +00002552 }
Alexey Bataev50b3c952016-02-19 10:38:26 +00002553 assert(RTLFn && "Unable to find OpenMP runtime function");
Alexey Bataev9959db52014-05-06 10:08:46 +00002554 return RTLFn;
2555}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00002556
James Y Knight9871db02019-02-05 16:42:33 +00002557llvm::FunctionCallee
2558CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman21212e42015-03-13 10:38:23 +00002559 assert((IVSize == 32 || IVSize == 64) &&
2560 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002561 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
2562 : "__kmpc_for_static_init_4u")
2563 : (IVSigned ? "__kmpc_for_static_init_8"
2564 : "__kmpc_for_static_init_8u");
2565 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
2566 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
Alexander Musman21212e42015-03-13 10:38:23 +00002567 llvm::Type *TypeParams[] = {
2568 getIdentTyPointerTy(), // loc
2569 CGM.Int32Ty, // tid
2570 CGM.Int32Ty, // schedtype
2571 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
2572 PtrTy, // p_lower
2573 PtrTy, // p_upper
2574 PtrTy, // p_stride
2575 ITy, // incr
2576 ITy // chunk
2577 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002578 auto *FnTy =
Alexander Musman21212e42015-03-13 10:38:23 +00002579 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2580 return CGM.CreateRuntimeFunction(FnTy, Name);
2581}
2582
James Y Knight9871db02019-02-05 16:42:33 +00002583llvm::FunctionCallee
2584CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002585 assert((IVSize == 32 || IVSize == 64) &&
2586 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002587 StringRef Name =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002588 IVSize == 32
2589 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
2590 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002591 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
Alexander Musman92bdaab2015-03-12 13:37:50 +00002592 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
2593 CGM.Int32Ty, // tid
2594 CGM.Int32Ty, // schedtype
2595 ITy, // lower
2596 ITy, // upper
2597 ITy, // stride
2598 ITy // chunk
2599 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002600 auto *FnTy =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002601 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2602 return CGM.CreateRuntimeFunction(FnTy, Name);
2603}
2604
James Y Knight9871db02019-02-05 16:42:33 +00002605llvm::FunctionCallee
2606CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002607 assert((IVSize == 32 || IVSize == 64) &&
2608 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002609 StringRef Name =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002610 IVSize == 32
2611 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
2612 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
2613 llvm::Type *TypeParams[] = {
2614 getIdentTyPointerTy(), // loc
2615 CGM.Int32Ty, // tid
2616 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002617 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002618 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2619 return CGM.CreateRuntimeFunction(FnTy, Name);
2620}
2621
James Y Knight9871db02019-02-05 16:42:33 +00002622llvm::FunctionCallee
2623CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002624 assert((IVSize == 32 || IVSize == 64) &&
2625 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002626 StringRef Name =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002627 IVSize == 32
2628 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
2629 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002630 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
2631 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002632 llvm::Type *TypeParams[] = {
2633 getIdentTyPointerTy(), // loc
2634 CGM.Int32Ty, // tid
2635 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
2636 PtrTy, // p_lower
2637 PtrTy, // p_upper
2638 PtrTy // p_stride
2639 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002640 auto *FnTy =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002641 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2642 return CGM.CreateRuntimeFunction(FnTy, Name);
2643}
2644
Gheorghe-Teodor Bercea625f59d2019-08-01 21:15:58 +00002645/// Obtain information that uniquely identifies a target entry. This
2646/// consists of the file and device IDs as well as line number associated with
2647/// the relevant entry source location.
2648static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
2649 unsigned &DeviceID, unsigned &FileID,
2650 unsigned &LineNum) {
2651 SourceManager &SM = C.getSourceManager();
2652
2653 // The loc should be always valid and have a file ID (the user cannot use
2654 // #pragma directives in macros)
2655
2656 assert(Loc.isValid() && "Source location is expected to be always valid.");
2657
2658 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
2659 assert(PLoc.isValid() && "Source location is expected to be always valid.");
2660
2661 llvm::sys::fs::UniqueID ID;
2662 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
2663 SM.getDiagnostics().Report(diag::err_cannot_open_file)
2664 << PLoc.getFilename() << EC.message();
2665
2666 DeviceID = ID.getDevice();
2667 FileID = ID.getFile();
2668 LineNum = PLoc.getLine();
2669}
2670
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002671Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) {
Alexey Bataev03f270c2018-03-30 18:31:07 +00002672 if (CGM.getLangOpts().OpenMPSimd)
2673 return Address::invalid();
Alexey Bataev92327c52018-03-26 16:40:55 +00002674 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00002675 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002676 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link ||
2677 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
2678 HasRequiresUnifiedSharedMemory))) {
Alexey Bataev92327c52018-03-26 16:40:55 +00002679 SmallString<64> PtrName;
2680 {
2681 llvm::raw_svector_ostream OS(PtrName);
Gheorghe-Teodor Bercea625f59d2019-08-01 21:15:58 +00002682 OS << CGM.getMangledName(GlobalDecl(VD));
2683 if (!VD->isExternallyVisible()) {
2684 unsigned DeviceID, FileID, Line;
2685 getTargetEntryUniqueInfo(CGM.getContext(),
2686 VD->getCanonicalDecl()->getBeginLoc(),
2687 DeviceID, FileID, Line);
2688 OS << llvm::format("_%x", FileID);
2689 }
2690 OS << "_decl_tgt_ref_ptr";
Alexey Bataev92327c52018-03-26 16:40:55 +00002691 }
2692 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName);
2693 if (!Ptr) {
2694 QualType PtrTy = CGM.getContext().getPointerType(VD->getType());
2695 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy),
2696 PtrName);
Gheorghe-Teodor Bercea625f59d2019-08-01 21:15:58 +00002697
2698 auto *GV = cast<llvm::GlobalVariable>(Ptr);
2699 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
2700
2701 if (!CGM.getLangOpts().OpenMPIsDevice)
Alexey Bataev03f270c2018-03-30 18:31:07 +00002702 GV->setInitializer(CGM.GetAddrOfGlobal(VD));
Alexey Bataev03f270c2018-03-30 18:31:07 +00002703 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr));
Alexey Bataev92327c52018-03-26 16:40:55 +00002704 }
2705 return Address(Ptr, CGM.getContext().getDeclAlign(VD));
2706 }
2707 return Address::invalid();
2708}
2709
Alexey Bataev97720002014-11-11 04:05:39 +00002710llvm::Constant *
2711CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002712 assert(!CGM.getLangOpts().OpenMPUseTLS ||
2713 !CGM.getContext().getTargetInfo().isTLSSupported());
Alexey Bataev97720002014-11-11 04:05:39 +00002714 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev18fa2322018-05-02 14:20:50 +00002715 std::string Suffix = getName({"cache", ""});
2716 return getOrCreateInternalVariable(
2717 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix));
Alexey Bataev97720002014-11-11 04:05:39 +00002718}
2719
John McCall7f416cc2015-09-08 08:05:57 +00002720Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
2721 const VarDecl *VD,
2722 Address VDAddr,
2723 SourceLocation Loc) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002724 if (CGM.getLangOpts().OpenMPUseTLS &&
2725 CGM.getContext().getTargetInfo().isTLSSupported())
2726 return VDAddr;
2727
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002728 llvm::Type *VarTy = VDAddr.getElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002729 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00002730 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
2731 CGM.Int8PtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00002732 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
2733 getOrCreateThreadPrivateCache(VD)};
John McCall7f416cc2015-09-08 08:05:57 +00002734 return Address(CGF.EmitRuntimeCall(
2735 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
2736 VDAddr.getAlignment());
Alexey Bataev97720002014-11-11 04:05:39 +00002737}
2738
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002739void CGOpenMPRuntime::emitThreadPrivateVarInit(
John McCall7f416cc2015-09-08 08:05:57 +00002740 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
Alexey Bataev97720002014-11-11 04:05:39 +00002741 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
2742 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
2743 // library.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002744 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002745 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +00002746 OMPLoc);
2747 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
2748 // to register constructor/destructor for variable.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002749 llvm::Value *Args[] = {
2750 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy),
2751 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +00002752 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002753 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +00002754}
2755
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002756llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
John McCall7f416cc2015-09-08 08:05:57 +00002757 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
Alexey Bataev97720002014-11-11 04:05:39 +00002758 bool PerformInit, CodeGenFunction *CGF) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002759 if (CGM.getLangOpts().OpenMPUseTLS &&
2760 CGM.getContext().getTargetInfo().isTLSSupported())
2761 return nullptr;
2762
Alexey Bataev97720002014-11-11 04:05:39 +00002763 VD = VD->getDefinition(CGM.getContext());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00002764 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) {
Alexey Bataev97720002014-11-11 04:05:39 +00002765 QualType ASTTy = VD->getType();
2766
2767 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002768 const Expr *Init = VD->getAnyInitializer();
Alexey Bataev97720002014-11-11 04:05:39 +00002769 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
2770 // Generate function that re-emits the declaration's initializer into the
2771 // threadprivate copy of the variable VD
2772 CodeGenFunction CtorCGF(CGM);
2773 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002774 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
2775 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
Alexey Bataev56223232017-06-09 13:40:18 +00002776 ImplicitParamDecl::Other);
Alexey Bataev97720002014-11-11 04:05:39 +00002777 Args.push_back(&Dst);
2778
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002779 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
John McCallc56a8b32016-03-11 04:30:31 +00002780 CGM.getContext().VoidPtrTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002781 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002782 std::string Name = getName({"__kmpc_global_ctor_", ""});
2783 llvm::Function *Fn =
2784 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002785 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002786 Args, Loc, Loc);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002787 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002788 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00002789 CGM.getContext().VoidPtrTy, Dst.getLocation());
John McCall7f416cc2015-09-08 08:05:57 +00002790 Address Arg = Address(ArgVal, VDAddr.getAlignment());
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002791 Arg = CtorCGF.Builder.CreateElementBitCast(
2792 Arg, CtorCGF.ConvertTypeForMem(ASTTy));
Alexey Bataev97720002014-11-11 04:05:39 +00002793 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
2794 /*IsInitializer=*/true);
2795 ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002796 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00002797 CGM.getContext().VoidPtrTy, Dst.getLocation());
2798 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
2799 CtorCGF.FinishFunction();
2800 Ctor = Fn;
2801 }
2802 if (VD->getType().isDestructedType() != QualType::DK_none) {
2803 // Generate function that emits destructor call for the threadprivate copy
2804 // of the variable VD
2805 CodeGenFunction DtorCGF(CGM);
2806 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002807 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
2808 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
Alexey Bataev56223232017-06-09 13:40:18 +00002809 ImplicitParamDecl::Other);
Alexey Bataev97720002014-11-11 04:05:39 +00002810 Args.push_back(&Dst);
2811
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002812 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
John McCallc56a8b32016-03-11 04:30:31 +00002813 CGM.getContext().VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002814 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002815 std::string Name = getName({"__kmpc_global_dtor_", ""});
2816 llvm::Function *Fn =
2817 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
Adrian Prantl1858c662016-04-24 22:22:29 +00002818 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
Alexey Bataev97720002014-11-11 04:05:39 +00002819 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002820 Loc, Loc);
Adrian Prantl1858c662016-04-24 22:22:29 +00002821 // Create a scope with an artificial location for the body of this function.
2822 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002823 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar(
Alexey Bataev97720002014-11-11 04:05:39 +00002824 DtorCGF.GetAddrOfLocalVar(&Dst),
John McCall7f416cc2015-09-08 08:05:57 +00002825 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
2826 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
Alexey Bataev97720002014-11-11 04:05:39 +00002827 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
2828 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
2829 DtorCGF.FinishFunction();
2830 Dtor = Fn;
2831 }
2832 // Do not emit init function if it is not required.
2833 if (!Ctor && !Dtor)
2834 return nullptr;
2835
2836 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002837 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
2838 /*isVarArg=*/false)
2839 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002840 // Copying constructor for the threadprivate variable.
2841 // Must be NULL - reserved by runtime, but currently it requires that this
2842 // parameter is always NULL. Otherwise it fires assertion.
2843 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
2844 if (Ctor == nullptr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002845 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
2846 /*isVarArg=*/false)
2847 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002848 Ctor = llvm::Constant::getNullValue(CtorTy);
2849 }
2850 if (Dtor == nullptr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002851 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
2852 /*isVarArg=*/false)
2853 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002854 Dtor = llvm::Constant::getNullValue(DtorTy);
2855 }
2856 if (!CGF) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002857 auto *InitFunctionTy =
Alexey Bataev97720002014-11-11 04:05:39 +00002858 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002859 std::string Name = getName({"__omp_threadprivate_init_", ""});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002860 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction(
Alexey Bataev18fa2322018-05-02 14:20:50 +00002861 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction());
Alexey Bataev97720002014-11-11 04:05:39 +00002862 CodeGenFunction InitCGF(CGM);
2863 FunctionArgList ArgList;
2864 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
2865 CGM.getTypes().arrangeNullaryFunction(), ArgList,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002866 Loc, Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002867 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002868 InitCGF.FinishFunction();
2869 return InitFunction;
2870 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002871 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002872 }
2873 return nullptr;
2874}
2875
Alexey Bataev34f8a702018-03-28 14:28:54 +00002876bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD,
2877 llvm::GlobalVariable *Addr,
2878 bool PerformInit) {
Alexey Bataev36724b72019-10-03 16:46:49 +00002879 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
2880 !CGM.getLangOpts().OpenMPIsDevice)
Alexey Bataev4db9dc62019-09-23 15:53:51 +00002881 return false;
Alexey Bataev34f8a702018-03-28 14:28:54 +00002882 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00002883 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002884 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
2885 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
2886 HasRequiresUnifiedSharedMemory))
Alexey Bataevd01b7492018-08-15 19:45:12 +00002887 return CGM.getLangOpts().OpenMPIsDevice;
Alexey Bataev34f8a702018-03-28 14:28:54 +00002888 VD = VD->getDefinition(CGM.getContext());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00002889 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second)
Alexey Bataev34f8a702018-03-28 14:28:54 +00002890 return CGM.getLangOpts().OpenMPIsDevice;
2891
2892 QualType ASTTy = VD->getType();
2893
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002894 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc();
Alexey Bataev34f8a702018-03-28 14:28:54 +00002895 // Produce the unique prefix to identify the new target regions. We use
2896 // the source location of the variable declaration which we know to not
2897 // conflict with any target region.
2898 unsigned DeviceID;
2899 unsigned FileID;
2900 unsigned Line;
2901 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line);
2902 SmallString<128> Buffer, Out;
2903 {
2904 llvm::raw_svector_ostream OS(Buffer);
2905 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID)
2906 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
2907 }
2908
2909 const Expr *Init = VD->getAnyInitializer();
2910 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
2911 llvm::Constant *Ctor;
2912 llvm::Constant *ID;
2913 if (CGM.getLangOpts().OpenMPIsDevice) {
2914 // Generate function that re-emits the declaration's initializer into
2915 // the threadprivate copy of the variable VD
2916 CodeGenFunction CtorCGF(CGM);
2917
2918 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2919 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2920 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
2921 FTy, Twine(Buffer, "_ctor"), FI, Loc);
2922 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF);
2923 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
2924 FunctionArgList(), Loc, Loc);
2925 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF);
2926 CtorCGF.EmitAnyExprToMem(Init,
2927 Address(Addr, CGM.getContext().getDeclAlign(VD)),
2928 Init->getType().getQualifiers(),
2929 /*IsInitializer=*/true);
2930 CtorCGF.FinishFunction();
2931 Ctor = Fn;
2932 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
Alexey Bataeve253f2f2018-05-09 14:15:18 +00002933 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor));
Alexey Bataev34f8a702018-03-28 14:28:54 +00002934 } else {
2935 Ctor = new llvm::GlobalVariable(
2936 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
2937 llvm::GlobalValue::PrivateLinkage,
2938 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor"));
2939 ID = Ctor;
2940 }
2941
2942 // Register the information for the entry associated with the constructor.
2943 Out.clear();
2944 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
2945 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor,
Alexey Bataev03f270c2018-03-30 18:31:07 +00002946 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor);
Alexey Bataev34f8a702018-03-28 14:28:54 +00002947 }
2948 if (VD->getType().isDestructedType() != QualType::DK_none) {
2949 llvm::Constant *Dtor;
2950 llvm::Constant *ID;
2951 if (CGM.getLangOpts().OpenMPIsDevice) {
2952 // Generate function that emits destructor call for the threadprivate
2953 // copy of the variable VD
2954 CodeGenFunction DtorCGF(CGM);
2955
2956 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2957 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2958 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
2959 FTy, Twine(Buffer, "_dtor"), FI, Loc);
2960 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
2961 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
2962 FunctionArgList(), Loc, Loc);
2963 // Create a scope with an artificial location for the body of this
2964 // function.
2965 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
2966 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)),
2967 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()),
2968 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
2969 DtorCGF.FinishFunction();
2970 Dtor = Fn;
2971 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
Alexey Bataeve253f2f2018-05-09 14:15:18 +00002972 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor));
Alexey Bataev34f8a702018-03-28 14:28:54 +00002973 } else {
2974 Dtor = new llvm::GlobalVariable(
2975 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
2976 llvm::GlobalValue::PrivateLinkage,
2977 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor"));
2978 ID = Dtor;
2979 }
2980 // Register the information for the entry associated with the destructor.
2981 Out.clear();
2982 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
2983 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor,
Alexey Bataev03f270c2018-03-30 18:31:07 +00002984 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor);
Alexey Bataev34f8a702018-03-28 14:28:54 +00002985 }
2986 return CGM.getLangOpts().OpenMPIsDevice;
2987}
2988
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002989Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
2990 QualType VarType,
2991 StringRef Name) {
Alexey Bataev18fa2322018-05-02 14:20:50 +00002992 std::string Suffix = getName({"artificial", ""});
2993 std::string CacheSuffix = getName({"cache", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002994 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002995 llvm::Value *GAddr =
2996 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002997 llvm::Value *Args[] = {
2998 emitUpdateLocation(CGF, SourceLocation()),
2999 getThreadID(CGF, SourceLocation()),
3000 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy),
3001 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00003002 /*isSigned=*/false),
Alexey Bataev18fa2322018-05-02 14:20:50 +00003003 getOrCreateInternalVariable(
3004 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))};
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003005 return Address(
3006 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3007 CGF.EmitRuntimeCall(
3008 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
3009 VarLVType->getPointerTo(/*AddrSpace=*/0)),
3010 CGM.getPointerAlign());
3011}
3012
Alexey Bataev1d943ae2019-11-19 12:12:23 -05003013void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond,
3014 const RegionCodeGenTy &ThenGen,
3015 const RegionCodeGenTy &ElseGen) {
Alexey Bataev1d677132015-04-22 13:57:31 +00003016 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
3017
3018 // If the condition constant folds and can be elided, try to avoid emitting
3019 // the condition and the dead arm of the if/else.
3020 bool CondConstant;
3021 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003022 if (CondConstant)
Alexey Bataev1d677132015-04-22 13:57:31 +00003023 ThenGen(CGF);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003024 else
Alexey Bataev1d677132015-04-22 13:57:31 +00003025 ElseGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00003026 return;
3027 }
3028
3029 // Otherwise, the condition did not fold, or we couldn't elide it. Just
3030 // emit the conditional branch.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003031 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then");
3032 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else");
3033 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end");
Alexey Bataev1d677132015-04-22 13:57:31 +00003034 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
3035
3036 // Emit the 'then' code.
3037 CGF.EmitBlock(ThenBlock);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003038 ThenGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00003039 CGF.EmitBranch(ContBlock);
3040 // Emit the 'else' code if present.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003041 // There is no need to emit line number for unconditional branch.
3042 (void)ApplyDebugLocation::CreateEmpty(CGF);
3043 CGF.EmitBlock(ElseBlock);
3044 ElseGen(CGF);
3045 // There is no need to emit line number for unconditional branch.
3046 (void)ApplyDebugLocation::CreateEmpty(CGF);
3047 CGF.EmitBranch(ContBlock);
Alexey Bataev1d677132015-04-22 13:57:31 +00003048 // Emit the continuation block for code after the if.
3049 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003050}
3051
Alexey Bataev1d677132015-04-22 13:57:31 +00003052void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00003053 llvm::Function *OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00003054 ArrayRef<llvm::Value *> CapturedVars,
Alexey Bataev1d677132015-04-22 13:57:31 +00003055 const Expr *IfCond) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003056 if (!CGF.HaveInsertPoint())
3057 return;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003058 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003059 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF,
3060 PrePostActionTy &) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00003061 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003062 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev2377fe92015-09-10 08:12:02 +00003063 llvm::Value *Args[] = {
3064 RTLoc,
3065 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003066 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())};
Alexey Bataev2377fe92015-09-10 08:12:02 +00003067 llvm::SmallVector<llvm::Value *, 16> RealArgs;
3068 RealArgs.append(std::begin(Args), std::end(Args));
3069 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
3070
James Y Knight9871db02019-02-05 16:42:33 +00003071 llvm::FunctionCallee RTLFn =
3072 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call);
Alexey Bataev2377fe92015-09-10 08:12:02 +00003073 CGF.EmitRuntimeCall(RTLFn, RealArgs);
3074 };
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003075 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF,
3076 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003077 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
3078 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc);
Alexey Bataev1d677132015-04-22 13:57:31 +00003079 // Build calls:
3080 // __kmpc_serialized_parallel(&Loc, GTid);
3081 llvm::Value *Args[] = {RTLoc, ThreadID};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003082 CGF.EmitRuntimeCall(
3083 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +00003084
Alexey Bataev3e0f4f82019-10-17 14:36:43 +00003085 // OutlinedFn(&GTid, &zero_bound, CapturedStruct);
3086 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc);
Alexey Bataevf89cf212019-10-16 16:59:01 +00003087 Address ZeroAddrBound =
3088 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty,
3089 /*Name=*/".bound.zero.addr");
3090 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0));
Alexey Bataev2377fe92015-09-10 08:12:02 +00003091 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
Alexey Bataev8521ff62018-07-25 20:03:01 +00003092 // ThreadId for serialized parallels is 0.
Alexey Bataev3e0f4f82019-10-17 14:36:43 +00003093 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
Alexey Bataevf89cf212019-10-16 16:59:01 +00003094 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer());
Alexey Bataev2377fe92015-09-10 08:12:02 +00003095 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
Alexey Bataev3c595a62017-08-14 15:01:03 +00003096 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +00003097
Alexey Bataev1d677132015-04-22 13:57:31 +00003098 // __kmpc_end_serialized_parallel(&Loc, GTid);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003099 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID};
Alexey Bataev1d677132015-04-22 13:57:31 +00003100 CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003101 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel),
3102 EndArgs);
Alexey Bataev1d677132015-04-22 13:57:31 +00003103 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003104 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -05003105 emitIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003106 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003107 RegionCodeGenTy ThenRCG(ThenGen);
3108 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00003109 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00003110}
3111
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00003112// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +00003113// thread-ID variable (it is passed in a first argument of the outlined function
3114// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
3115// regular serial code region, get thread ID by calling kmp_int32
3116// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
3117// return the address of that temp.
John McCall7f416cc2015-09-08 08:05:57 +00003118Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
3119 SourceLocation Loc) {
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003120 if (auto *OMPRegionInfo =
Alexey Bataevd74d0602014-10-13 06:02:40 +00003121 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003122 if (OMPRegionInfo->getThreadIDVariable())
Akira Hatanakaf139ae32019-12-03 15:17:01 -08003123 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003124
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003125 llvm::Value *ThreadID = getThreadID(CGF, Loc);
3126 QualType Int32Ty =
Alexey Bataevd74d0602014-10-13 06:02:40 +00003127 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003128 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
Alexey Bataevd74d0602014-10-13 06:02:40 +00003129 CGF.EmitStoreOfScalar(ThreadID,
John McCall7f416cc2015-09-08 08:05:57 +00003130 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
Alexey Bataevd74d0602014-10-13 06:02:40 +00003131
3132 return ThreadIDTemp;
3133}
3134
Alexey Bataev1af5bd52019-03-05 17:47:18 +00003135llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable(
3136 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003137 SmallString<256> Buffer;
3138 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00003139 Out << Name;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003140 StringRef RuntimeName = Out.str();
Alexey Bataev43a919f2018-04-13 17:48:43 +00003141 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first;
David Blaikie13156b62014-11-19 03:06:06 +00003142 if (Elem.second) {
3143 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00003144 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00003145 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00003146 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003147
David Blaikie13156b62014-11-19 03:06:06 +00003148 return Elem.second = new llvm::GlobalVariable(
3149 CGM.getModule(), Ty, /*IsConstant*/ false,
3150 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
Alexey Bataev1af5bd52019-03-05 17:47:18 +00003151 Elem.first(), /*InsertBefore=*/nullptr,
3152 llvm::GlobalValue::NotThreadLocal, AddressSpace);
Alexey Bataev97720002014-11-11 04:05:39 +00003153}
3154
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003155llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev18fa2322018-05-02 14:20:50 +00003156 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str();
3157 std::string Name = getName({Prefix, "var"});
3158 return getOrCreateInternalVariable(KmpCriticalNameTy, Name);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003159}
3160
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003161namespace {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003162/// Common pre(post)-action for different OpenMP constructs.
3163class CommonActionTy final : public PrePostActionTy {
James Y Knight9871db02019-02-05 16:42:33 +00003164 llvm::FunctionCallee EnterCallee;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003165 ArrayRef<llvm::Value *> EnterArgs;
James Y Knight9871db02019-02-05 16:42:33 +00003166 llvm::FunctionCallee ExitCallee;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003167 ArrayRef<llvm::Value *> ExitArgs;
3168 bool Conditional;
3169 llvm::BasicBlock *ContBlock = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003170
3171public:
James Y Knight9871db02019-02-05 16:42:33 +00003172 CommonActionTy(llvm::FunctionCallee EnterCallee,
3173 ArrayRef<llvm::Value *> EnterArgs,
3174 llvm::FunctionCallee ExitCallee,
3175 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003176 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
3177 ExitArgs(ExitArgs), Conditional(Conditional) {}
3178 void Enter(CodeGenFunction &CGF) override {
3179 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs);
3180 if (Conditional) {
3181 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes);
3182 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
3183 ContBlock = CGF.createBasicBlock("omp_if.end");
3184 // Generate the branch (If-stmt)
3185 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
3186 CGF.EmitBlock(ThenBlock);
3187 }
Alexey Bataeva744ff52015-05-05 09:24:37 +00003188 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003189 void Done(CodeGenFunction &CGF) {
3190 // Emit the rest of blocks/branches
3191 CGF.EmitBranch(ContBlock);
3192 CGF.EmitBlock(ContBlock, true);
3193 }
3194 void Exit(CodeGenFunction &CGF) override {
3195 CGF.EmitRuntimeCall(ExitCallee, ExitArgs);
Alexey Bataev3e6124b2015-04-10 07:48:12 +00003196 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003197};
Hans Wennborg7eb54642015-09-10 17:07:54 +00003198} // anonymous namespace
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003199
3200void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
3201 StringRef CriticalName,
3202 const RegionCodeGenTy &CriticalOpGen,
Alexey Bataevfc57d162015-12-15 10:55:09 +00003203 SourceLocation Loc, const Expr *Hint) {
3204 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
Alexey Bataev75ddfab2014-12-01 11:32:38 +00003205 // CriticalOpGen();
3206 // __kmpc_end_critical(ident_t *, gtid, Lock);
3207 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev8ef31412015-12-18 07:58:25 +00003208 if (!CGF.HaveInsertPoint())
3209 return;
Alexey Bataevfc57d162015-12-15 10:55:09 +00003210 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3211 getCriticalRegionLock(CriticalName)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003212 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args),
3213 std::end(Args));
Alexey Bataevfc57d162015-12-15 10:55:09 +00003214 if (Hint) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003215 EnterArgs.push_back(CGF.Builder.CreateIntCast(
3216 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false));
3217 }
3218 CommonActionTy Action(
3219 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint
3220 : OMPRTL__kmpc_critical),
3221 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args);
3222 CriticalOpGen.setAction(Action);
Alexey Bataevfc57d162015-12-15 10:55:09 +00003223 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003224}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003225
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003226void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003227 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003228 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003229 if (!CGF.HaveInsertPoint())
3230 return;
Alexey Bataev8d690652014-12-04 07:23:53 +00003231 // if(__kmpc_master(ident_t *, gtid)) {
3232 // MasterOpGen();
3233 // __kmpc_end_master(ident_t *, gtid);
3234 // }
3235 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00003236 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003237 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args,
3238 createRuntimeFunction(OMPRTL__kmpc_end_master), Args,
3239 /*Conditional=*/true);
3240 MasterOpGen.setAction(Action);
3241 emitInlinedDirective(CGF, OMPD_master, MasterOpGen);
3242 Action.Done(CGF);
Alexey Bataev8d690652014-12-04 07:23:53 +00003243}
3244
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003245void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
3246 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003247 if (!CGF.HaveInsertPoint())
3248 return;
Alexey Bataev9f797f32015-02-05 05:57:51 +00003249 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
3250 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003251 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00003252 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003253 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00003254 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
3255 Region->emitUntiedSwitch(CGF);
Alexey Bataev9f797f32015-02-05 05:57:51 +00003256}
3257
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003258void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
3259 const RegionCodeGenTy &TaskgroupOpGen,
3260 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003261 if (!CGF.HaveInsertPoint())
3262 return;
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003263 // __kmpc_taskgroup(ident_t *, gtid);
3264 // TaskgroupOpGen();
3265 // __kmpc_end_taskgroup(ident_t *, gtid);
3266 // Prepare arguments and build a call to __kmpc_taskgroup
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003267 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
3268 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args,
3269 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
3270 Args);
3271 TaskgroupOpGen.setAction(Action);
3272 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003273}
3274
John McCall7f416cc2015-09-08 08:05:57 +00003275/// Given an array of pointers to variables, project the address of a
3276/// given variable.
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003277static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
3278 unsigned Index, const VarDecl *Var) {
John McCall7f416cc2015-09-08 08:05:57 +00003279 // Pull out the pointer to the variable.
James Y Knight751fe282019-02-09 22:22:28 +00003280 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index);
John McCall7f416cc2015-09-08 08:05:57 +00003281 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
3282
3283 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003284 Addr = CGF.Builder.CreateElementBitCast(
3285 Addr, CGF.ConvertTypeForMem(Var->getType()));
John McCall7f416cc2015-09-08 08:05:57 +00003286 return Addr;
3287}
3288
Alexey Bataeva63048e2015-03-23 06:18:07 +00003289static llvm::Value *emitCopyprivateCopyFunction(
Alexey Bataev420d45b2015-04-14 05:11:24 +00003290 CodeGenModule &CGM, llvm::Type *ArgsType,
3291 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003292 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps,
3293 SourceLocation Loc) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003294 ASTContext &C = CGM.getContext();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003295 // void copy_func(void *LHSArg, void *RHSArg);
3296 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003297 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3298 ImplicitParamDecl::Other);
3299 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3300 ImplicitParamDecl::Other);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003301 Args.push_back(&LHSArg);
3302 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003303 const auto &CGFI =
3304 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00003305 std::string Name =
3306 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"});
3307 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
3308 llvm::GlobalValue::InternalLinkage, Name,
3309 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00003310 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00003311 Fn->setDoesNotRecurse();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003312 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003313 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev420d45b2015-04-14 05:11:24 +00003314 // Dest = (void*[n])(LHSArg);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003315 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00003316 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3317 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
3318 ArgsType), CGF.getPointerAlign());
3319 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3320 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
3321 ArgsType), CGF.getPointerAlign());
Alexey Bataeva63048e2015-03-23 06:18:07 +00003322 // *(Type0*)Dst[0] = *(Type0*)Src[0];
3323 // *(Type1*)Dst[1] = *(Type1*)Src[1];
3324 // ...
3325 // *(Typen*)Dst[n] = *(Typen*)Src[n];
Alexey Bataeva63048e2015-03-23 06:18:07 +00003326 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003327 const auto *DestVar =
3328 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +00003329 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
3330
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003331 const auto *SrcVar =
3332 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +00003333 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
3334
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003335 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003336 QualType Type = VD->getType();
John McCall7f416cc2015-09-08 08:05:57 +00003337 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003338 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00003339 CGF.FinishFunction();
3340 return Fn;
3341}
3342
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003343void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003344 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00003345 SourceLocation Loc,
3346 ArrayRef<const Expr *> CopyprivateVars,
3347 ArrayRef<const Expr *> SrcExprs,
3348 ArrayRef<const Expr *> DstExprs,
3349 ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003350 if (!CGF.HaveInsertPoint())
3351 return;
Alexey Bataeva63048e2015-03-23 06:18:07 +00003352 assert(CopyprivateVars.size() == SrcExprs.size() &&
3353 CopyprivateVars.size() == DstExprs.size() &&
3354 CopyprivateVars.size() == AssignmentOps.size());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003355 ASTContext &C = CGM.getContext();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003356 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003357 // if(__kmpc_single(ident_t *, gtid)) {
3358 // SingleOpGen();
3359 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003360 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003361 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00003362 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3363 // <copy_func>, did_it);
3364
John McCall7f416cc2015-09-08 08:05:57 +00003365 Address DidIt = Address::invalid();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003366 if (!CopyprivateVars.empty()) {
3367 // int32 did_it = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003368 QualType KmpInt32Ty =
3369 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003370 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
John McCall7f416cc2015-09-08 08:05:57 +00003371 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003372 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003373 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00003374 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003375 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args,
3376 createRuntimeFunction(OMPRTL__kmpc_end_single), Args,
3377 /*Conditional=*/true);
3378 SingleOpGen.setAction(Action);
3379 emitInlinedDirective(CGF, OMPD_single, SingleOpGen);
3380 if (DidIt.isValid()) {
3381 // did_it = 1;
3382 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
3383 }
3384 Action.Done(CGF);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003385 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3386 // <copy_func>, did_it);
John McCall7f416cc2015-09-08 08:05:57 +00003387 if (DidIt.isValid()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00003388 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
Richard Smith772e2662019-10-04 01:25:59 +00003389 QualType CopyprivateArrayTy = C.getConstantArrayType(
3390 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
3391 /*IndexTypeQuals=*/0);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003392 // Create a list of all private variables for copyprivate.
John McCall7f416cc2015-09-08 08:05:57 +00003393 Address CopyprivateList =
Alexey Bataeva63048e2015-03-23 06:18:07 +00003394 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
3395 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +00003396 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I);
John McCall7f416cc2015-09-08 08:05:57 +00003397 CGF.Builder.CreateStore(
Alexey Bataeva63048e2015-03-23 06:18:07 +00003398 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08003399 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF),
3400 CGF.VoidPtrTy),
John McCall7f416cc2015-09-08 08:05:57 +00003401 Elem);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003402 }
3403 // Build function that copies private values from single region to all other
3404 // threads in the corresponding parallel region.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003405 llvm::Value *CpyFn = emitCopyprivateCopyFunction(
Alexey Bataeva63048e2015-03-23 06:18:07 +00003406 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003407 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003408 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00003409 Address CL =
3410 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
3411 CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003412 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003413 llvm::Value *Args[] = {
3414 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
3415 getThreadID(CGF, Loc), // i32 <gtid>
Alexey Bataev66beaa92015-04-30 03:47:32 +00003416 BufSize, // size_t <buf_size>
John McCall7f416cc2015-09-08 08:05:57 +00003417 CL.getPointer(), // void *<copyprivate list>
Alexey Bataeva63048e2015-03-23 06:18:07 +00003418 CpyFn, // void (*) (void *, void *) <copy_func>
3419 DidItVal // i32 did_it
3420 };
3421 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
3422 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003423}
3424
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003425void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
3426 const RegionCodeGenTy &OrderedOpGen,
Alexey Bataev5f600d62015-09-29 03:48:57 +00003427 SourceLocation Loc, bool IsThreads) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003428 if (!CGF.HaveInsertPoint())
3429 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003430 // __kmpc_ordered(ident_t *, gtid);
3431 // OrderedOpGen();
3432 // __kmpc_end_ordered(ident_t *, gtid);
3433 // Prepare arguments and build a call to __kmpc_ordered
Alexey Bataev5f600d62015-09-29 03:48:57 +00003434 if (IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003435 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003436 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args,
3437 createRuntimeFunction(OMPRTL__kmpc_end_ordered),
3438 Args);
3439 OrderedOpGen.setAction(Action);
3440 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
3441 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003442 }
Alexey Bataev5f600d62015-09-29 03:48:57 +00003443 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003444}
3445
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003446unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) {
Alexey Bataev50b3c952016-02-19 10:38:26 +00003447 unsigned Flags;
3448 if (Kind == OMPD_for)
3449 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
3450 else if (Kind == OMPD_sections)
3451 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
3452 else if (Kind == OMPD_single)
3453 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
3454 else if (Kind == OMPD_barrier)
3455 Flags = OMP_IDENT_BARRIER_EXPL;
3456 else
3457 Flags = OMP_IDENT_BARRIER_IMPL;
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003458 return Flags;
3459}
3460
Alexey Bataevf6a53d62019-03-18 18:40:00 +00003461void CGOpenMPRuntime::getDefaultScheduleAndChunk(
3462 CodeGenFunction &CGF, const OMPLoopDirective &S,
3463 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const {
3464 // Check if the loop directive is actually a doacross loop directive. In this
3465 // case choose static, 1 schedule.
3466 if (llvm::any_of(
3467 S.getClausesOfKind<OMPOrderedClause>(),
3468 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) {
3469 ScheduleKind = OMPC_SCHEDULE_static;
3470 // Chunk size is 1 in this case.
3471 llvm::APInt ChunkSize(32, 1);
3472 ChunkExpr = IntegerLiteral::Create(
3473 CGF.getContext(), ChunkSize,
3474 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
3475 SourceLocation());
3476 }
3477}
3478
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003479void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
3480 OpenMPDirectiveKind Kind, bool EmitChecks,
3481 bool ForceSimpleCall) {
3482 if (!CGF.HaveInsertPoint())
3483 return;
3484 // Build call __kmpc_cancel_barrier(loc, thread_id);
3485 // Build call __kmpc_barrier(loc, thread_id);
3486 unsigned Flags = getDefaultFlagsForBarriers(Kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003487 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
3488 // thread_id);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003489 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
3490 getThreadID(CGF, Loc)};
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003491 if (auto *OMPRegionInfo =
3492 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00003493 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003494 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003495 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev25e5b442015-09-15 12:52:43 +00003496 if (EmitChecks) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003497 // if (__kmpc_cancel_barrier()) {
3498 // exit from construct;
3499 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003500 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
3501 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
3502 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003503 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
3504 CGF.EmitBlock(ExitBB);
3505 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003506 CodeGenFunction::JumpDest CancelDestination =
Alexey Bataev25e5b442015-09-15 12:52:43 +00003507 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003508 CGF.EmitBranchThroughCleanup(CancelDestination);
3509 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
3510 }
3511 return;
3512 }
3513 }
3514 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003515}
3516
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003517/// Map the OpenMP loop schedule to the runtime enumeration.
Alexander Musmanc6388682014-12-15 07:07:06 +00003518static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003519 bool Chunked, bool Ordered) {
Alexander Musmanc6388682014-12-15 07:07:06 +00003520 switch (ScheduleKind) {
3521 case OMPC_SCHEDULE_static:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003522 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
3523 : (Ordered ? OMP_ord_static : OMP_sch_static);
Alexander Musmanc6388682014-12-15 07:07:06 +00003524 case OMPC_SCHEDULE_dynamic:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003525 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00003526 case OMPC_SCHEDULE_guided:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003527 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00003528 case OMPC_SCHEDULE_runtime:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003529 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
3530 case OMPC_SCHEDULE_auto:
3531 return Ordered ? OMP_ord_auto : OMP_sch_auto;
Alexander Musmanc6388682014-12-15 07:07:06 +00003532 case OMPC_SCHEDULE_unknown:
3533 assert(!Chunked && "chunk was specified but schedule kind not known");
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003534 return Ordered ? OMP_ord_static : OMP_sch_static;
Alexander Musmanc6388682014-12-15 07:07:06 +00003535 }
3536 llvm_unreachable("Unexpected runtime schedule");
3537}
3538
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003539/// Map the OpenMP distribute schedule to the runtime enumeration.
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003540static OpenMPSchedType
3541getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
3542 // only static is allowed for dist_schedule
3543 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
3544}
3545
Alexander Musmanc6388682014-12-15 07:07:06 +00003546bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
3547 bool Chunked) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003548 OpenMPSchedType Schedule =
3549 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
Alexander Musmanc6388682014-12-15 07:07:06 +00003550 return Schedule == OMP_sch_static;
3551}
3552
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003553bool CGOpenMPRuntime::isStaticNonchunked(
3554 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003555 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003556 return Schedule == OMP_dist_sch_static;
3557}
3558
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00003559bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind,
3560 bool Chunked) const {
3561 OpenMPSchedType Schedule =
3562 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
3563 return Schedule == OMP_sch_static_chunked;
3564}
3565
3566bool CGOpenMPRuntime::isStaticChunked(
3567 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
3568 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
3569 return Schedule == OMP_dist_sch_static_chunked;
3570}
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003571
Alexander Musmandf7a8e22015-01-22 08:49:35 +00003572bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003573 OpenMPSchedType Schedule =
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003574 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00003575 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
3576 return Schedule != OMP_sch_static;
3577}
3578
Alexey Bataev07a3b592019-08-23 19:52:05 +00003579static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003580 OpenMPScheduleClauseModifier M1,
3581 OpenMPScheduleClauseModifier M2) {
Alexey Bataev6cff6242016-05-30 13:05:14 +00003582 int Modifier = 0;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003583 switch (M1) {
3584 case OMPC_SCHEDULE_MODIFIER_monotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003585 Modifier = OMP_sch_modifier_monotonic;
3586 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003587 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003588 Modifier = OMP_sch_modifier_nonmonotonic;
3589 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003590 case OMPC_SCHEDULE_MODIFIER_simd:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003591 if (Schedule == OMP_sch_static_chunked)
3592 Schedule = OMP_sch_static_balanced_chunked;
3593 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003594 case OMPC_SCHEDULE_MODIFIER_last:
3595 case OMPC_SCHEDULE_MODIFIER_unknown:
3596 break;
3597 }
3598 switch (M2) {
3599 case OMPC_SCHEDULE_MODIFIER_monotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003600 Modifier = OMP_sch_modifier_monotonic;
3601 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003602 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003603 Modifier = OMP_sch_modifier_nonmonotonic;
3604 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003605 case OMPC_SCHEDULE_MODIFIER_simd:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003606 if (Schedule == OMP_sch_static_chunked)
3607 Schedule = OMP_sch_static_balanced_chunked;
3608 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003609 case OMPC_SCHEDULE_MODIFIER_last:
3610 case OMPC_SCHEDULE_MODIFIER_unknown:
3611 break;
3612 }
Alexey Bataev07a3b592019-08-23 19:52:05 +00003613 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription.
3614 // If the static schedule kind is specified or if the ordered clause is
3615 // specified, and if the nonmonotonic modifier is not specified, the effect is
3616 // as if the monotonic modifier is specified. Otherwise, unless the monotonic
3617 // modifier is specified, the effect is as if the nonmonotonic modifier is
3618 // specified.
3619 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) {
3620 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
3621 Schedule == OMP_sch_static_balanced_chunked ||
Alexey Bataevc3eded02019-11-18 11:13:08 -05003622 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
3623 Schedule == OMP_dist_sch_static_chunked ||
3624 Schedule == OMP_dist_sch_static))
Alexey Bataev07a3b592019-08-23 19:52:05 +00003625 Modifier = OMP_sch_modifier_nonmonotonic;
3626 }
Alexey Bataev6cff6242016-05-30 13:05:14 +00003627 return Schedule | Modifier;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003628}
3629
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003630void CGOpenMPRuntime::emitForDispatchInit(
3631 CodeGenFunction &CGF, SourceLocation Loc,
3632 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
3633 bool Ordered, const DispatchRTInput &DispatchValues) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003634 if (!CGF.HaveInsertPoint())
3635 return;
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003636 OpenMPSchedType Schedule = getRuntimeSchedule(
3637 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered);
John McCall7f416cc2015-09-08 08:05:57 +00003638 assert(Ordered ||
3639 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
Alexey Bataev6cff6242016-05-30 13:05:14 +00003640 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
3641 Schedule != OMP_sch_static_balanced_chunked));
John McCall7f416cc2015-09-08 08:05:57 +00003642 // Call __kmpc_dispatch_init(
3643 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
3644 // kmp_int[32|64] lower, kmp_int[32|64] upper,
3645 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00003646
John McCall7f416cc2015-09-08 08:05:57 +00003647 // If the Chunk was not specified in the clause - use default value 1.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003648 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk
3649 : CGF.Builder.getIntN(IVSize, 1);
John McCall7f416cc2015-09-08 08:05:57 +00003650 llvm::Value *Args[] = {
Alexey Bataev07a3b592019-08-23 19:52:05 +00003651 emitUpdateLocation(CGF, Loc),
3652 getThreadID(CGF, Loc),
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003653 CGF.Builder.getInt32(addMonoNonMonoModifier(
Alexey Bataev07a3b592019-08-23 19:52:05 +00003654 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type
3655 DispatchValues.LB, // Lower
3656 DispatchValues.UB, // Upper
3657 CGF.Builder.getIntN(IVSize, 1), // Stride
3658 Chunk // Chunk
John McCall7f416cc2015-09-08 08:05:57 +00003659 };
3660 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
3661}
3662
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003663static void emitForStaticInitCall(
3664 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
James Y Knight9871db02019-02-05 16:42:33 +00003665 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003666 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003667 const CGOpenMPRuntime::StaticRTInput &Values) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003668 if (!CGF.HaveInsertPoint())
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003669 return;
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003670
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003671 assert(!Values.Ordered);
3672 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
3673 Schedule == OMP_sch_static_balanced_chunked ||
3674 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
3675 Schedule == OMP_dist_sch_static ||
3676 Schedule == OMP_dist_sch_static_chunked);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003677
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003678 // Call __kmpc_for_static_init(
3679 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
3680 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
3681 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
3682 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
3683 llvm::Value *Chunk = Values.Chunk;
3684 if (Chunk == nullptr) {
3685 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
3686 Schedule == OMP_dist_sch_static) &&
3687 "expected static non-chunked schedule");
3688 // If the Chunk was not specified in the clause - use default value 1.
3689 Chunk = CGF.Builder.getIntN(Values.IVSize, 1);
3690 } else {
3691 assert((Schedule == OMP_sch_static_chunked ||
3692 Schedule == OMP_sch_static_balanced_chunked ||
3693 Schedule == OMP_ord_static_chunked ||
3694 Schedule == OMP_dist_sch_static_chunked) &&
3695 "expected static chunked schedule");
3696 }
3697 llvm::Value *Args[] = {
3698 UpdateLocation,
3699 ThreadId,
Alexey Bataev07a3b592019-08-23 19:52:05 +00003700 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003701 M2)), // Schedule type
3702 Values.IL.getPointer(), // &isLastIter
3703 Values.LB.getPointer(), // &LB
3704 Values.UB.getPointer(), // &UB
3705 Values.ST.getPointer(), // &Stride
3706 CGF.Builder.getIntN(Values.IVSize, 1), // Incr
3707 Chunk // Chunk
3708 };
3709 CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003710}
3711
John McCall7f416cc2015-09-08 08:05:57 +00003712void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
3713 SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003714 OpenMPDirectiveKind DKind,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003715 const OpenMPScheduleTy &ScheduleKind,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003716 const StaticRTInput &Values) {
3717 OpenMPSchedType ScheduleNum = getRuntimeSchedule(
3718 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered);
3719 assert(isOpenMPWorksharingDirective(DKind) &&
3720 "Expected loop-based or sections-based directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003721 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003722 isOpenMPLoopDirective(DKind)
3723 ? OMP_IDENT_WORK_LOOP
3724 : OMP_IDENT_WORK_SECTIONS);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003725 llvm::Value *ThreadId = getThreadID(CGF, Loc);
James Y Knight9871db02019-02-05 16:42:33 +00003726 llvm::FunctionCallee StaticInitFunction =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003727 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003728 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003729 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003730}
John McCall7f416cc2015-09-08 08:05:57 +00003731
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003732void CGOpenMPRuntime::emitDistributeStaticInit(
3733 CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003734 OpenMPDistScheduleClauseKind SchedKind,
3735 const CGOpenMPRuntime::StaticRTInput &Values) {
3736 OpenMPSchedType ScheduleNum =
3737 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003738 llvm::Value *UpdatedLocation =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003739 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003740 llvm::Value *ThreadId = getThreadID(CGF, Loc);
James Y Knight9871db02019-02-05 16:42:33 +00003741 llvm::FunctionCallee StaticInitFunction =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003742 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003743 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
3744 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003745 OMPC_SCHEDULE_MODIFIER_unknown, Values);
Alexander Musmanc6388682014-12-15 07:07:06 +00003746}
3747
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003748void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
Alexey Bataevf43f7142017-09-06 16:17:35 +00003749 SourceLocation Loc,
3750 OpenMPDirectiveKind DKind) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003751 if (!CGF.HaveInsertPoint())
3752 return;
Alexander Musmanc6388682014-12-15 07:07:06 +00003753 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataevf43f7142017-09-06 16:17:35 +00003754 llvm::Value *Args[] = {
3755 emitUpdateLocation(CGF, Loc,
3756 isOpenMPDistributeDirective(DKind)
3757 ? OMP_IDENT_WORK_DISTRIBUTE
3758 : isOpenMPLoopDirective(DKind)
3759 ? OMP_IDENT_WORK_LOOP
3760 : OMP_IDENT_WORK_SECTIONS),
3761 getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003762 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
3763 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00003764}
3765
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003766void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
3767 SourceLocation Loc,
3768 unsigned IVSize,
3769 bool IVSigned) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003770 if (!CGF.HaveInsertPoint())
3771 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003772 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00003773 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003774 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
3775}
3776
Alexander Musman92bdaab2015-03-12 13:37:50 +00003777llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
3778 SourceLocation Loc, unsigned IVSize,
John McCall7f416cc2015-09-08 08:05:57 +00003779 bool IVSigned, Address IL,
3780 Address LB, Address UB,
3781 Address ST) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00003782 // Call __kmpc_dispatch_next(
3783 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
3784 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
3785 // kmp_int[32|64] *p_stride);
3786 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00003787 emitUpdateLocation(CGF, Loc),
3788 getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00003789 IL.getPointer(), // &isLastIter
3790 LB.getPointer(), // &Lower
3791 UB.getPointer(), // &Upper
3792 ST.getPointer() // &Stride
Alexander Musman92bdaab2015-03-12 13:37:50 +00003793 };
3794 llvm::Value *Call =
3795 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
3796 return CGF.EmitScalarConversion(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003797 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00003798 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00003799}
3800
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003801void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
3802 llvm::Value *NumThreads,
3803 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003804 if (!CGF.HaveInsertPoint())
3805 return;
Alexey Bataevb2059782014-10-13 08:23:51 +00003806 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
3807 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003808 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00003809 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003810 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
3811 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00003812}
3813
Alexey Bataev7f210c62015-06-18 13:40:03 +00003814void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
3815 OpenMPProcBindClauseKind ProcBind,
3816 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003817 if (!CGF.HaveInsertPoint())
3818 return;
Alexey Bataev7f210c62015-06-18 13:40:03 +00003819 // Constants for proc bind value accepted by the runtime.
3820 enum ProcBindTy {
3821 ProcBindFalse = 0,
3822 ProcBindTrue,
3823 ProcBindMaster,
3824 ProcBindClose,
3825 ProcBindSpread,
3826 ProcBindIntel,
3827 ProcBindDefault
3828 } RuntimeProcBind;
3829 switch (ProcBind) {
3830 case OMPC_PROC_BIND_master:
3831 RuntimeProcBind = ProcBindMaster;
3832 break;
3833 case OMPC_PROC_BIND_close:
3834 RuntimeProcBind = ProcBindClose;
3835 break;
3836 case OMPC_PROC_BIND_spread:
3837 RuntimeProcBind = ProcBindSpread;
3838 break;
3839 case OMPC_PROC_BIND_unknown:
3840 llvm_unreachable("Unsupported proc_bind value.");
3841 }
3842 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
3843 llvm::Value *Args[] = {
3844 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3845 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
3846 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
3847}
3848
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003849void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
3850 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003851 if (!CGF.HaveInsertPoint())
3852 return;
Alexey Bataevd76df6d2015-02-24 12:55:09 +00003853 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003854 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
3855 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00003856}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003857
Alexey Bataev62b63b12015-03-10 07:28:44 +00003858namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003859/// Indexes of fields for type kmp_task_t.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003860enum KmpTaskTFields {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003861 /// List of shared variables.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003862 KmpTaskTShareds,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003863 /// Task routine.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003864 KmpTaskTRoutine,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003865 /// Partition id for the untied tasks.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003866 KmpTaskTPartId,
Alexey Bataevad537bb2016-05-30 09:06:50 +00003867 /// Function with call of destructors for private variables.
3868 Data1,
3869 /// Task priority.
3870 Data2,
Alexey Bataev7292c292016-04-25 12:22:29 +00003871 /// (Taskloops only) Lower bound.
3872 KmpTaskTLowerBound,
3873 /// (Taskloops only) Upper bound.
3874 KmpTaskTUpperBound,
3875 /// (Taskloops only) Stride.
3876 KmpTaskTStride,
3877 /// (Taskloops only) Is last iteration flag.
3878 KmpTaskTLastIter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003879 /// (Taskloops only) Reduction data.
3880 KmpTaskTReductions,
Alexey Bataev62b63b12015-03-10 07:28:44 +00003881};
Hans Wennborg7eb54642015-09-10 17:07:54 +00003882} // anonymous namespace
Alexey Bataev62b63b12015-03-10 07:28:44 +00003883
Samuel Antaoee8fb302016-01-06 13:42:12 +00003884bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003885 return OffloadEntriesTargetRegion.empty() &&
3886 OffloadEntriesDeviceGlobalVar.empty();
Samuel Antaoee8fb302016-01-06 13:42:12 +00003887}
3888
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003889/// Initialize target region entry.
Samuel Antaoee8fb302016-01-06 13:42:12 +00003890void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3891 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3892 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00003893 unsigned Order) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003894 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
3895 "only required for the device "
3896 "code generation.");
Samuel Antao2de62b02016-02-13 23:35:10 +00003897 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
Samuel Antaof83efdb2017-01-05 16:02:49 +00003898 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003899 OMPTargetRegionEntryTargetRegion);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003900 ++OffloadingEntriesNum;
3901}
3902
3903void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3904 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3905 StringRef ParentName, unsigned LineNum,
Samuel Antaof83efdb2017-01-05 16:02:49 +00003906 llvm::Constant *Addr, llvm::Constant *ID,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003907 OMPTargetRegionEntryKind Flags) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003908 // If we are emitting code for a target, the entry is already initialized,
3909 // only has to be registered.
3910 if (CGM.getLangOpts().OpenMPIsDevice) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00003911 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) {
3912 unsigned DiagID = CGM.getDiags().getCustomDiagID(
3913 DiagnosticsEngine::Error,
3914 "Unable to find target region on line '%0' in the device code.");
3915 CGM.getDiags().Report(DiagID) << LineNum;
3916 return;
3917 }
Samuel Antao2de62b02016-02-13 23:35:10 +00003918 auto &Entry =
3919 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
Samuel Antaoee8fb302016-01-06 13:42:12 +00003920 assert(Entry.isValid() && "Entry not initialized!");
3921 Entry.setAddress(Addr);
3922 Entry.setID(ID);
Samuel Antaof83efdb2017-01-05 16:02:49 +00003923 Entry.setFlags(Flags);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003924 } else {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003925 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags);
Samuel Antao2de62b02016-02-13 23:35:10 +00003926 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00003927 ++OffloadingEntriesNum;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003928 }
3929}
3930
3931bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00003932 unsigned DeviceID, unsigned FileID, StringRef ParentName,
3933 unsigned LineNum) const {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003934 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
3935 if (PerDevice == OffloadEntriesTargetRegion.end())
3936 return false;
3937 auto PerFile = PerDevice->second.find(FileID);
3938 if (PerFile == PerDevice->second.end())
3939 return false;
3940 auto PerParentName = PerFile->second.find(ParentName);
3941 if (PerParentName == PerFile->second.end())
3942 return false;
3943 auto PerLine = PerParentName->second.find(LineNum);
3944 if (PerLine == PerParentName->second.end())
3945 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003946 // Fail if this entry is already registered.
Samuel Antao2de62b02016-02-13 23:35:10 +00003947 if (PerLine->second.getAddress() || PerLine->second.getID())
Samuel Antaoee8fb302016-01-06 13:42:12 +00003948 return false;
3949 return true;
3950}
3951
3952void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
3953 const OffloadTargetRegionEntryInfoActTy &Action) {
3954 // Scan all target region entries and perform the provided action.
Alexey Bataev03f270c2018-03-30 18:31:07 +00003955 for (const auto &D : OffloadEntriesTargetRegion)
3956 for (const auto &F : D.second)
3957 for (const auto &P : F.second)
3958 for (const auto &L : P.second)
Samuel Antao2de62b02016-02-13 23:35:10 +00003959 Action(D.first, F.first, P.first(), L.first, L.second);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003960}
3961
Alexey Bataev03f270c2018-03-30 18:31:07 +00003962void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3963 initializeDeviceGlobalVarEntryInfo(StringRef Name,
3964 OMPTargetGlobalVarEntryKind Flags,
3965 unsigned Order) {
3966 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
3967 "only required for the device "
3968 "code generation.");
3969 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
3970 ++OffloadingEntriesNum;
3971}
Samuel Antaoee8fb302016-01-06 13:42:12 +00003972
Alexey Bataev03f270c2018-03-30 18:31:07 +00003973void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3974 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr,
3975 CharUnits VarSize,
3976 OMPTargetGlobalVarEntryKind Flags,
3977 llvm::GlobalValue::LinkageTypes Linkage) {
3978 if (CGM.getLangOpts().OpenMPIsDevice) {
3979 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3980 assert(Entry.isValid() && Entry.getFlags() == Flags &&
3981 "Entry not initialized!");
3982 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
3983 "Resetting with the new address.");
Alexey Bataev8259cc32019-03-12 20:05:17 +00003984 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) {
3985 if (Entry.getVarSize().isZero()) {
3986 Entry.setVarSize(VarSize);
3987 Entry.setLinkage(Linkage);
3988 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003989 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00003990 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003991 Entry.setVarSize(VarSize);
3992 Entry.setLinkage(Linkage);
Alexey Bataev8259cc32019-03-12 20:05:17 +00003993 Entry.setAddress(Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00003994 } else {
Alexey Bataev8259cc32019-03-12 20:05:17 +00003995 if (hasDeviceGlobalVarEntryInfo(VarName)) {
3996 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3997 assert(Entry.isValid() && Entry.getFlags() == Flags &&
3998 "Entry not initialized!");
3999 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
4000 "Resetting with the new address.");
4001 if (Entry.getVarSize().isZero()) {
4002 Entry.setVarSize(VarSize);
4003 Entry.setLinkage(Linkage);
4004 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004005 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00004006 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004007 OffloadEntriesDeviceGlobalVar.try_emplace(
4008 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage);
4009 ++OffloadingEntriesNum;
4010 }
4011}
4012
4013void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
4014 actOnDeviceGlobalVarEntriesInfo(
4015 const OffloadDeviceGlobalVarEntryInfoActTy &Action) {
4016 // Scan all target region entries and perform the provided action.
4017 for (const auto &E : OffloadEntriesDeviceGlobalVar)
4018 Action(E.getKey(), E.getValue());
Samuel Antaoee8fb302016-01-06 13:42:12 +00004019}
4020
Alexey Bataev03f270c2018-03-30 18:31:07 +00004021void CGOpenMPRuntime::createOffloadEntry(
4022 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags,
4023 llvm::GlobalValue::LinkageTypes Linkage) {
Samuel Antao2de62b02016-02-13 23:35:10 +00004024 StringRef Name = Addr->getName();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004025 llvm::Module &M = CGM.getModule();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004026 llvm::LLVMContext &C = M.getContext();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004027
4028 // Create constant string with the name.
4029 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
4030
Alexey Bataev18fa2322018-05-02 14:20:50 +00004031 std::string StringName = getName({"omp_offloading", "entry_name"});
4032 auto *Str = new llvm::GlobalVariable(
4033 M, StrPtrInit->getType(), /*isConstant=*/true,
4034 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00004035 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004036
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004037 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy),
4038 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy),
4039 llvm::ConstantInt::get(CGM.SizeTy, Size),
4040 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
4041 llvm::ConstantInt::get(CGM.Int32Ty, 0)};
Alexey Bataev18fa2322018-05-02 14:20:50 +00004042 std::string EntryName = getName({"omp_offloading", "entry", ""});
Mike Ricee1ca7b62018-08-29 15:45:11 +00004043 llvm::GlobalVariable *Entry = createGlobalStruct(
4044 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data,
4045 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004046
4047 // The entry has to be created in the section the linker expects it to be.
Sergey Dmitriev4b343fd2019-09-27 20:00:51 +00004048 Entry->setSection("omp_offloading_entries");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004049}
4050
4051void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
4052 // Emit the offloading entries and metadata so that the device codegen side
Samuel Antao4c8035b2016-12-12 18:00:20 +00004053 // can easily figure out what to emit. The produced metadata looks like
4054 // this:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004055 //
4056 // !omp_offload.info = !{!1, ...}
4057 //
4058 // Right now we only generate metadata for function that contain target
4059 // regions.
4060
Sergey Dmitriev5836c352019-10-15 18:42:47 +00004061 // If we are in simd mode or there are no entries, we don't need to do
4062 // anything.
4063 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty())
Samuel Antaoee8fb302016-01-06 13:42:12 +00004064 return;
4065
4066 llvm::Module &M = CGM.getModule();
4067 llvm::LLVMContext &C = M.getContext();
Alexey Bataevba643691d2019-10-03 16:20:34 +00004068 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *,
4069 SourceLocation, StringRef>,
4070 16>
Samuel Antaoee8fb302016-01-06 13:42:12 +00004071 OrderedEntries(OffloadEntriesInfoManager.size());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004072 llvm::SmallVector<StringRef, 16> ParentFunctions(
4073 OffloadEntriesInfoManager.size());
Samuel Antaoee8fb302016-01-06 13:42:12 +00004074
Simon Pilgrim2c518802017-03-30 14:13:19 +00004075 // Auxiliary methods to create metadata values and strings.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004076 auto &&GetMDInt = [this](unsigned V) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004077 return llvm::ConstantAsMetadata::get(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004078 llvm::ConstantInt::get(CGM.Int32Ty, V));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004079 };
4080
Alexey Bataev03f270c2018-03-30 18:31:07 +00004081 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); };
4082
4083 // Create the offloading info metadata node.
4084 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004085
4086 // Create function that emits metadata for each target region entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00004087 auto &&TargetRegionMetadataEmitter =
Alexey Bataevba643691d2019-10-03 16:20:34 +00004088 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt,
4089 &GetMDString](
Alexey Bataev03f270c2018-03-30 18:31:07 +00004090 unsigned DeviceID, unsigned FileID, StringRef ParentName,
4091 unsigned Line,
4092 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
4093 // Generate metadata for target regions. Each entry of this metadata
4094 // contains:
4095 // - Entry 0 -> Kind of this type of metadata (0).
4096 // - Entry 1 -> Device ID of the file where the entry was identified.
4097 // - Entry 2 -> File ID of the file where the entry was identified.
4098 // - Entry 3 -> Mangled name of the function where the entry was
4099 // identified.
4100 // - Entry 4 -> Line in the file where the entry was identified.
4101 // - Entry 5 -> Order the entry was created.
4102 // The first element of the metadata node is the kind.
4103 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID),
4104 GetMDInt(FileID), GetMDString(ParentName),
4105 GetMDInt(Line), GetMDInt(E.getOrder())};
Samuel Antaoee8fb302016-01-06 13:42:12 +00004106
Alexey Bataevba643691d2019-10-03 16:20:34 +00004107 SourceLocation Loc;
4108 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(),
4109 E = CGM.getContext().getSourceManager().fileinfo_end();
4110 I != E; ++I) {
4111 if (I->getFirst()->getUniqueID().getDevice() == DeviceID &&
4112 I->getFirst()->getUniqueID().getFile() == FileID) {
4113 Loc = CGM.getContext().getSourceManager().translateFileLineCol(
4114 I->getFirst(), Line, 1);
4115 break;
4116 }
4117 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004118 // Save this entry in the right position of the ordered entries array.
Alexey Bataevba643691d2019-10-03 16:20:34 +00004119 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName);
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004120 ParentFunctions[E.getOrder()] = ParentName;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004121
Alexey Bataev03f270c2018-03-30 18:31:07 +00004122 // Add metadata to the named metadata node.
4123 MD->addOperand(llvm::MDNode::get(C, Ops));
4124 };
Samuel Antaoee8fb302016-01-06 13:42:12 +00004125
4126 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
4127 TargetRegionMetadataEmitter);
4128
Alexey Bataev03f270c2018-03-30 18:31:07 +00004129 // Create function that emits metadata for each device global variable entry;
4130 auto &&DeviceGlobalVarMetadataEmitter =
4131 [&C, &OrderedEntries, &GetMDInt, &GetMDString,
4132 MD](StringRef MangledName,
4133 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar
4134 &E) {
4135 // Generate metadata for global variables. Each entry of this metadata
4136 // contains:
4137 // - Entry 0 -> Kind of this type of metadata (1).
4138 // - Entry 1 -> Mangled name of the variable.
4139 // - Entry 2 -> Declare target kind.
4140 // - Entry 3 -> Order the entry was created.
4141 // The first element of the metadata node is the kind.
4142 llvm::Metadata *Ops[] = {
4143 GetMDInt(E.getKind()), GetMDString(MangledName),
4144 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
4145
4146 // Save this entry in the right position of the ordered entries array.
Alexey Bataevba643691d2019-10-03 16:20:34 +00004147 OrderedEntries[E.getOrder()] =
4148 std::make_tuple(&E, SourceLocation(), MangledName);
Alexey Bataev03f270c2018-03-30 18:31:07 +00004149
4150 // Add metadata to the named metadata node.
4151 MD->addOperand(llvm::MDNode::get(C, Ops));
4152 };
4153
4154 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo(
4155 DeviceGlobalVarMetadataEmitter);
4156
Alexey Bataevba643691d2019-10-03 16:20:34 +00004157 for (const auto &E : OrderedEntries) {
4158 assert(std::get<0>(E) && "All ordered entries must exist!");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004159 if (const auto *CE =
Samuel Antaoee8fb302016-01-06 13:42:12 +00004160 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
Alexey Bataevba643691d2019-10-03 16:20:34 +00004161 std::get<0>(E))) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004162 if (!CE->getID() || !CE->getAddress()) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004163 // Do not blame the entry if the parent funtion is not emitted.
4164 StringRef FnName = ParentFunctions[CE->getOrder()];
4165 if (!CGM.GetGlobalValue(FnName))
4166 continue;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004167 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4168 DiagnosticsEngine::Error,
Alexey Bataevba643691d2019-10-03 16:20:34 +00004169 "Offloading entry for target region in %0 is incorrect: either the "
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004170 "address or the ID is invalid.");
Alexey Bataevba643691d2019-10-03 16:20:34 +00004171 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004172 continue;
4173 }
Alexey Bataev34f8a702018-03-28 14:28:54 +00004174 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004175 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage);
Alexey Bataevba643691d2019-10-03 16:20:34 +00004176 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy::
4177 OffloadEntryInfoDeviceGlobalVar>(
4178 std::get<0>(E))) {
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004179 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags =
4180 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4181 CE->getFlags());
4182 switch (Flags) {
4183 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00004184 if (CGM.getLangOpts().OpenMPIsDevice &&
4185 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())
4186 continue;
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004187 if (!CE->getAddress()) {
4188 unsigned DiagID = CGM.getDiags().getCustomDiagID(
Alexey Bataevba643691d2019-10-03 16:20:34 +00004189 DiagnosticsEngine::Error, "Offloading entry for declare target "
4190 "variable %0 is incorrect: the "
4191 "address is invalid.");
4192 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E);
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004193 continue;
4194 }
Alexey Bataevb4dd6d22018-08-29 20:41:37 +00004195 // The vaiable has no definition - no need to add the entry.
4196 if (CE->getVarSize().isZero())
4197 continue;
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004198 break;
4199 }
4200 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink:
4201 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) ||
4202 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) &&
4203 "Declaret target link address is set.");
4204 if (CGM.getLangOpts().OpenMPIsDevice)
4205 continue;
4206 if (!CE->getAddress()) {
4207 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4208 DiagnosticsEngine::Error,
4209 "Offloading entry for declare target variable is incorrect: the "
4210 "address is invalid.");
4211 CGM.getDiags().Report(DiagID);
4212 continue;
4213 }
4214 break;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004215 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004216 createOffloadEntry(CE->getAddress(), CE->getAddress(),
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004217 CE->getVarSize().getQuantity(), Flags,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004218 CE->getLinkage());
4219 } else {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004220 llvm_unreachable("Unsupported entry kind.");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004221 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004222 }
4223}
4224
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004225/// Loads all the offload entries information from the host IR
Samuel Antaoee8fb302016-01-06 13:42:12 +00004226/// metadata.
4227void CGOpenMPRuntime::loadOffloadInfoMetadata() {
4228 // If we are in target mode, load the metadata from the host IR. This code has
4229 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
4230
4231 if (!CGM.getLangOpts().OpenMPIsDevice)
4232 return;
4233
4234 if (CGM.getLangOpts().OMPHostIRFile.empty())
4235 return;
4236
4237 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004238 if (auto EC = Buf.getError()) {
4239 CGM.getDiags().Report(diag::err_cannot_open_file)
4240 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004241 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004242 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004243
4244 llvm::LLVMContext C;
Peter Collingbourned9445c42016-11-13 07:00:17 +00004245 auto ME = expectedToErrorOrAndEmitErrors(
4246 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004247
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004248 if (auto EC = ME.getError()) {
4249 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4250 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'");
4251 CGM.getDiags().Report(DiagID)
4252 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004253 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004254 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004255
4256 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
4257 if (!MD)
4258 return;
4259
George Burgess IV00f70bd2018-03-01 05:43:23 +00004260 for (llvm::MDNode *MN : MD->operands()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004261 auto &&GetMDInt = [MN](unsigned Idx) {
4262 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004263 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
4264 };
4265
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004266 auto &&GetMDString = [MN](unsigned Idx) {
4267 auto *V = cast<llvm::MDString>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004268 return V->getString();
4269 };
4270
Alexey Bataev03f270c2018-03-30 18:31:07 +00004271 switch (GetMDInt(0)) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004272 default:
4273 llvm_unreachable("Unexpected metadata!");
4274 break;
4275 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
Alexey Bataev34f8a702018-03-28 14:28:54 +00004276 OffloadingEntryInfoTargetRegion:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004277 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
Alexey Bataev03f270c2018-03-30 18:31:07 +00004278 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2),
4279 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4),
4280 /*Order=*/GetMDInt(5));
4281 break;
4282 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
4283 OffloadingEntryInfoDeviceGlobalVar:
4284 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo(
4285 /*MangledName=*/GetMDString(1),
4286 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4287 /*Flags=*/GetMDInt(2)),
4288 /*Order=*/GetMDInt(3));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004289 break;
4290 }
4291 }
4292}
4293
Alexey Bataev62b63b12015-03-10 07:28:44 +00004294void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
4295 if (!KmpRoutineEntryPtrTy) {
4296 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004297 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004298 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
4299 FunctionProtoType::ExtProtoInfo EPI;
4300 KmpRoutineEntryPtrQTy = C.getPointerType(
4301 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
4302 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
4303 }
4304}
4305
Samuel Antaoee8fb302016-01-06 13:42:12 +00004306QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004307 // Make sure the type of the entry is already created. This is the type we
4308 // have to create:
4309 // struct __tgt_offload_entry{
4310 // void *addr; // Pointer to the offload entry info.
4311 // // (function or global)
4312 // char *name; // Name of the function or global.
4313 // size_t size; // Size of the entry info (0 if it a function).
Samuel Antaof83efdb2017-01-05 16:02:49 +00004314 // int32_t flags; // Flags associated with the entry, e.g. 'link'.
4315 // int32_t reserved; // Reserved, to use by the runtime library.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004316 // };
4317 if (TgtOffloadEntryQTy.isNull()) {
4318 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004319 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004320 RD->startDefinition();
4321 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4322 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
4323 addFieldToRecordDecl(C, RD, C.getSizeType());
Samuel Antaof83efdb2017-01-05 16:02:49 +00004324 addFieldToRecordDecl(
4325 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4326 addFieldToRecordDecl(
4327 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004328 RD->completeDefinition();
Jonas Hahnfeld5e4df282018-01-18 15:38:03 +00004329 RD->addAttr(PackedAttr::CreateImplicit(C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004330 TgtOffloadEntryQTy = C.getRecordType(RD);
4331 }
4332 return TgtOffloadEntryQTy;
4333}
4334
4335QualType CGOpenMPRuntime::getTgtDeviceImageQTy() {
4336 // These are the types we need to build:
4337 // struct __tgt_device_image{
4338 // void *ImageStart; // Pointer to the target code start.
4339 // void *ImageEnd; // Pointer to the target code end.
4340 // // We also add the host entries to the device image, as it may be useful
4341 // // for the target runtime to have access to that information.
4342 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all
4343 // // the entries.
4344 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
4345 // // entries (non inclusive).
4346 // };
4347 if (TgtDeviceImageQTy.isNull()) {
4348 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004349 RecordDecl *RD = C.buildImplicitRecord("__tgt_device_image");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004350 RD->startDefinition();
4351 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4352 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4353 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4354 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4355 RD->completeDefinition();
4356 TgtDeviceImageQTy = C.getRecordType(RD);
4357 }
4358 return TgtDeviceImageQTy;
4359}
4360
4361QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() {
4362 // struct __tgt_bin_desc{
4363 // int32_t NumDevices; // Number of devices supported.
4364 // __tgt_device_image *DeviceImages; // Arrays of device images
4365 // // (one per device).
4366 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the
4367 // // entries.
4368 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
4369 // // entries (non inclusive).
4370 // };
4371 if (TgtBinaryDescriptorQTy.isNull()) {
4372 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004373 RecordDecl *RD = C.buildImplicitRecord("__tgt_bin_desc");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004374 RD->startDefinition();
4375 addFieldToRecordDecl(
4376 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4377 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy()));
4378 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4379 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4380 RD->completeDefinition();
4381 TgtBinaryDescriptorQTy = C.getRecordType(RD);
4382 }
4383 return TgtBinaryDescriptorQTy;
4384}
4385
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004386namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00004387struct PrivateHelpersTy {
4388 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
4389 const VarDecl *PrivateElemInit)
4390 : Original(Original), PrivateCopy(PrivateCopy),
4391 PrivateElemInit(PrivateElemInit) {}
4392 const VarDecl *Original;
4393 const VarDecl *PrivateCopy;
4394 const VarDecl *PrivateElemInit;
4395};
4396typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Hans Wennborg7eb54642015-09-10 17:07:54 +00004397} // anonymous namespace
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004398
Alexey Bataev9e034042015-05-05 04:05:12 +00004399static RecordDecl *
Craig Topper8674c5c2015-09-29 04:30:07 +00004400createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004401 if (!Privates.empty()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004402 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004403 // Build struct .kmp_privates_t. {
4404 // /* private vars */
4405 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004406 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t");
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004407 RD->startDefinition();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004408 for (const auto &Pair : Privates) {
4409 const VarDecl *VD = Pair.second.Original;
4410 QualType Type = VD->getType().getNonReferenceType();
4411 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type);
Alexey Bataevc71a4092015-09-11 10:29:41 +00004412 if (VD->hasAttrs()) {
4413 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
4414 E(VD->getAttrs().end());
4415 I != E; ++I)
4416 FD->addAttr(*I);
4417 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004418 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004419 RD->completeDefinition();
4420 return RD;
4421 }
4422 return nullptr;
4423}
4424
Alexey Bataev9e034042015-05-05 04:05:12 +00004425static RecordDecl *
Alexey Bataev7292c292016-04-25 12:22:29 +00004426createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind,
4427 QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004428 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004429 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004430 // Build struct kmp_task_t {
4431 // void * shareds;
4432 // kmp_routine_entry_t routine;
4433 // kmp_int32 part_id;
Alexey Bataevad537bb2016-05-30 09:06:50 +00004434 // kmp_cmplrdata_t data1;
4435 // kmp_cmplrdata_t data2;
Alexey Bataev7292c292016-04-25 12:22:29 +00004436 // For taskloops additional fields:
4437 // kmp_uint64 lb;
4438 // kmp_uint64 ub;
4439 // kmp_int64 st;
4440 // kmp_int32 liter;
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004441 // void * reductions;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004442 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004443 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004444 UD->startDefinition();
4445 addFieldToRecordDecl(C, UD, KmpInt32Ty);
4446 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy);
4447 UD->completeDefinition();
4448 QualType KmpCmplrdataTy = C.getRecordType(UD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004449 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t");
Alexey Bataev62b63b12015-03-10 07:28:44 +00004450 RD->startDefinition();
4451 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4452 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
4453 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004454 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
4455 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004456 if (isOpenMPTaskLoopDirective(Kind)) {
4457 QualType KmpUInt64Ty =
4458 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
4459 QualType KmpInt64Ty =
4460 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
4461 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4462 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4463 addFieldToRecordDecl(C, RD, KmpInt64Ty);
4464 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004465 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004466 }
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004467 RD->completeDefinition();
4468 return RD;
4469}
4470
4471static RecordDecl *
4472createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004473 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004474 ASTContext &C = CGM.getContext();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004475 // Build struct kmp_task_t_with_privates {
4476 // kmp_task_t task_data;
4477 // .kmp_privates_t. privates;
4478 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004479 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004480 RD->startDefinition();
4481 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004482 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates))
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004483 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004484 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004485 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004486}
4487
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004488/// Emit a proxy function which accepts kmp_task_t as the second
Alexey Bataev62b63b12015-03-10 07:28:44 +00004489/// argument.
4490/// \code
4491/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00004492/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt,
Alexey Bataev7292c292016-04-25 12:22:29 +00004493/// For taskloops:
4494/// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004495/// tt->reductions, tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004496/// return 0;
4497/// }
4498/// \endcode
James Y Knight9871db02019-02-05 16:42:33 +00004499static llvm::Function *
Alexey Bataev62b63b12015-03-10 07:28:44 +00004500emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev7292c292016-04-25 12:22:29 +00004501 OpenMPDirectiveKind Kind, QualType KmpInt32Ty,
4502 QualType KmpTaskTWithPrivatesPtrQTy,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004503 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
James Y Knight9871db02019-02-05 16:42:33 +00004504 QualType SharedsPtrTy, llvm::Function *TaskFunction,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004505 llvm::Value *TaskPrivatesMap) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004506 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004507 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004508 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4509 ImplicitParamDecl::Other);
4510 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4511 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4512 ImplicitParamDecl::Other);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004513 Args.push_back(&GtidArg);
4514 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004515 const auto &TaskEntryFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004516 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004517 llvm::FunctionType *TaskEntryTy =
4518 CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004519 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""});
4520 auto *TaskEntry = llvm::Function::Create(
4521 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004522 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004523 TaskEntry->setDoesNotRecurse();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004524 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004525 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args,
4526 Loc, Loc);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004527
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004528 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
Alexey Bataev7292c292016-04-25 12:22:29 +00004529 // tt,
4530 // For taskloops:
4531 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
4532 // tt->task_data.shareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004533 llvm::Value *GtidParam = CGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00004534 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
Alexey Bataev31300ed2016-02-04 11:27:03 +00004535 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4536 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4537 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004538 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004539 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004540 LValue Base =
4541 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004542 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004543 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004544 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004545 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004546
4547 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004548 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
4549 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev1e491372018-01-23 18:44:14 +00004550 CGF.EmitLoadOfScalar(SharedsLVal, Loc),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004551 CGF.ConvertTypeForMem(SharedsPtrTy));
4552
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004553 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4554 llvm::Value *PrivatesParam;
4555 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004556 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004557 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004558 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004559 } else {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004560 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004561 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004562
Alexey Bataev7292c292016-04-25 12:22:29 +00004563 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam,
4564 TaskPrivatesMap,
4565 CGF.Builder
4566 .CreatePointerBitCastOrAddrSpaceCast(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004567 TDBase.getAddress(CGF), CGF.VoidPtrTy)
Alexey Bataev7292c292016-04-25 12:22:29 +00004568 .getPointer()};
4569 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs),
4570 std::end(CommonArgs));
4571 if (isOpenMPTaskLoopDirective(Kind)) {
4572 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004573 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI);
4574 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004575 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004576 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI);
4577 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004578 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004579 LValue StLVal = CGF.EmitLValueForField(Base, *StFI);
4580 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004581 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004582 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4583 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004584 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004585 LValue RLVal = CGF.EmitLValueForField(Base, *RFI);
4586 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004587 CallArgs.push_back(LBParam);
4588 CallArgs.push_back(UBParam);
4589 CallArgs.push_back(StParam);
4590 CallArgs.push_back(LIParam);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004591 CallArgs.push_back(RParam);
Alexey Bataev7292c292016-04-25 12:22:29 +00004592 }
4593 CallArgs.push_back(SharedsParam);
4594
Alexey Bataev3c595a62017-08-14 15:01:03 +00004595 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction,
4596 CallArgs);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004597 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)),
4598 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004599 CGF.FinishFunction();
4600 return TaskEntry;
4601}
4602
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004603static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
4604 SourceLocation Loc,
4605 QualType KmpInt32Ty,
4606 QualType KmpTaskTWithPrivatesPtrQTy,
4607 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004608 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004609 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004610 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4611 ImplicitParamDecl::Other);
4612 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4613 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4614 ImplicitParamDecl::Other);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004615 Args.push_back(&GtidArg);
4616 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004617 const auto &DestructorFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004618 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004619 llvm::FunctionType *DestructorFnTy =
4620 CGM.getTypes().GetFunctionType(DestructorFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004621 std::string Name =
4622 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""});
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004623 auto *DestructorFn =
4624 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00004625 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004626 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004627 DestructorFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004628 DestructorFn->setDoesNotRecurse();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004629 CodeGenFunction CGF(CGM);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004630 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004631 Args, Loc, Loc);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004632
Alexey Bataev31300ed2016-02-04 11:27:03 +00004633 LValue Base = CGF.EmitLoadOfPointerLValue(
4634 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4635 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004636 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004637 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
4638 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004639 Base = CGF.EmitLValueForField(Base, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004640 for (const auto *Field :
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004641 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004642 if (QualType::DestructionKind DtorKind =
4643 Field->getType().isDestructedType()) {
4644 LValue FieldLValue = CGF.EmitLValueForField(Base, Field);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004645 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004646 }
4647 }
4648 CGF.FinishFunction();
4649 return DestructorFn;
4650}
4651
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004652/// Emit a privates mapping function for correct handling of private and
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004653/// firstprivate variables.
4654/// \code
4655/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
4656/// **noalias priv1,..., <tyn> **noalias privn) {
4657/// *priv1 = &.privates.priv1;
4658/// ...;
4659/// *privn = &.privates.privn;
4660/// }
4661/// \endcode
4662static llvm::Value *
4663emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Craig Topper8674c5c2015-09-29 04:30:07 +00004664 ArrayRef<const Expr *> PrivateVars,
4665 ArrayRef<const Expr *> FirstprivateVars,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004666 ArrayRef<const Expr *> LastprivateVars,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004667 QualType PrivatesQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004668 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004669 ASTContext &C = CGM.getContext();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004670 FunctionArgList Args;
4671 ImplicitParamDecl TaskPrivatesArg(
4672 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
Alexey Bataev56223232017-06-09 13:40:18 +00004673 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
4674 ImplicitParamDecl::Other);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004675 Args.push_back(&TaskPrivatesArg);
4676 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
4677 unsigned Counter = 1;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004678 for (const Expr *E : PrivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004679 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004680 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4681 C.getPointerType(C.getPointerType(E->getType()))
4682 .withConst()
4683 .withRestrict(),
4684 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004685 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004686 PrivateVarsPos[VD] = Counter;
4687 ++Counter;
4688 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004689 for (const Expr *E : FirstprivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004690 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004691 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4692 C.getPointerType(C.getPointerType(E->getType()))
4693 .withConst()
4694 .withRestrict(),
4695 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004696 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004697 PrivateVarsPos[VD] = Counter;
4698 ++Counter;
4699 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004700 for (const Expr *E : LastprivateVars) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004701 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004702 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4703 C.getPointerType(C.getPointerType(E->getType()))
4704 .withConst()
4705 .withRestrict(),
4706 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004707 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataevf93095a2016-05-05 08:46:22 +00004708 PrivateVarsPos[VD] = Counter;
4709 ++Counter;
4710 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004711 const auto &TaskPrivatesMapFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004712 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004713 llvm::FunctionType *TaskPrivatesMapTy =
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004714 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004715 std::string Name =
4716 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""});
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004717 auto *TaskPrivatesMap = llvm::Function::Create(
Alexey Bataev18fa2322018-05-02 14:20:50 +00004718 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
4719 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004720 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004721 TaskPrivatesMapFnInfo);
Alexey Bataev8c5555c2019-05-21 15:11:58 +00004722 if (CGM.getLangOpts().Optimize) {
4723 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
4724 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
4725 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
4726 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004727 CodeGenFunction CGF(CGM);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004728 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004729 TaskPrivatesMapFnInfo, Args, Loc, Loc);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004730
4731 // *privi = &.privates.privi;
Alexey Bataev31300ed2016-02-04 11:27:03 +00004732 LValue Base = CGF.EmitLoadOfPointerLValue(
4733 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
4734 TaskPrivatesArg.getType()->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004735 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004736 Counter = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004737 for (const FieldDecl *Field : PrivatesQTyRD->fields()) {
4738 LValue FieldLVal = CGF.EmitLValueForField(Base, Field);
4739 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
4740 LValue RefLVal =
4741 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
4742 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004743 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>());
4744 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004745 ++Counter;
4746 }
4747 CGF.FinishFunction();
4748 return TaskPrivatesMap;
4749}
4750
Alexey Bataevf93095a2016-05-05 08:46:22 +00004751/// Emit initialization for private variables in task-based directives.
Alexey Bataev8a831592016-05-10 10:36:51 +00004752static void emitPrivatesInit(CodeGenFunction &CGF,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004753 const OMPExecutableDirective &D,
4754 Address KmpTaskSharedsPtr, LValue TDBase,
4755 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4756 QualType SharedsTy, QualType SharedsPtrTy,
4757 const OMPTaskDataTy &Data,
4758 ArrayRef<PrivateDataTy> Privates, bool ForDup) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004759 ASTContext &C = CGF.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004760 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
4761 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004762 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind())
4763 ? OMPD_taskloop
4764 : OMPD_task;
4765 const CapturedStmt &CS = *D.getCapturedStmt(Kind);
4766 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004767 LValue SrcBase;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004768 bool IsTargetTask =
4769 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) ||
4770 isOpenMPTargetExecutionDirective(D.getDirectiveKind());
4771 // For target-based directives skip 3 firstprivate arrays BasePointersArray,
4772 // PointersArray and SizesArray. The original variables for these arrays are
4773 // not captured and we get their addresses explicitly.
4774 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) ||
Alexey Bataev8451efa2018-01-15 19:06:12 +00004775 (IsTargetTask && KmpTaskSharedsPtr.isValid())) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004776 SrcBase = CGF.MakeAddrLValue(
4777 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4778 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
4779 SharedsTy);
4780 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004781 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004782 for (const PrivateDataTy &Pair : Privates) {
4783 const VarDecl *VD = Pair.second.PrivateCopy;
4784 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004785 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) &&
4786 !CGF.isTrivialInitializer(Init)))) {
Alexey Bataev8a831592016-05-10 10:36:51 +00004787 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004788 if (const VarDecl *Elem = Pair.second.PrivateElemInit) {
4789 const VarDecl *OriginalVD = Pair.second.Original;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004790 // Check if the variable is the target-based BasePointersArray,
4791 // PointersArray or SizesArray.
4792 LValue SharedRefLValue;
Alexey Bataevab41ea62019-03-13 20:46:28 +00004793 QualType Type = PrivateLValue.getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004794 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004795 if (IsTargetTask && !SharedField) {
4796 assert(isa<ImplicitParamDecl>(OriginalVD) &&
4797 isa<CapturedDecl>(OriginalVD->getDeclContext()) &&
4798 cast<CapturedDecl>(OriginalVD->getDeclContext())
4799 ->getNumParams() == 0 &&
4800 isa<TranslationUnitDecl>(
4801 cast<CapturedDecl>(OriginalVD->getDeclContext())
4802 ->getDeclContext()) &&
4803 "Expected artificial target data variable.");
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004804 SharedRefLValue =
4805 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type);
4806 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004807 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField);
4808 SharedRefLValue = CGF.MakeAddrLValue(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004809 Address(SharedRefLValue.getPointer(CGF),
4810 C.getDeclAlign(OriginalVD)),
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004811 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl),
4812 SharedRefLValue.getTBAAInfo());
4813 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004814 if (Type->isArrayType()) {
4815 // Initialize firstprivate array.
4816 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) {
4817 // Perform simple memcpy.
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00004818 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004819 } else {
4820 // Initialize firstprivate array using element-by-element
Simon Pilgrim2c518802017-03-30 14:13:19 +00004821 // initialization.
Alexey Bataevf93095a2016-05-05 08:46:22 +00004822 CGF.EmitOMPAggregateAssign(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004823 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF),
4824 Type,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004825 [&CGF, Elem, Init, &CapturesInfo](Address DestElement,
4826 Address SrcElement) {
4827 // Clean up any temporaries needed by the initialization.
4828 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4829 InitScope.addPrivate(
4830 Elem, [SrcElement]() -> Address { return SrcElement; });
4831 (void)InitScope.Privatize();
4832 // Emit initialization for single element.
4833 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
4834 CGF, &CapturesInfo);
4835 CGF.EmitAnyExprToMem(Init, DestElement,
4836 Init->getType().getQualifiers(),
4837 /*IsInitializer=*/false);
4838 });
4839 }
4840 } else {
4841 CodeGenFunction::OMPPrivateScope InitScope(CGF);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004842 InitScope.addPrivate(Elem, [SharedRefLValue, &CGF]() -> Address {
4843 return SharedRefLValue.getAddress(CGF);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004844 });
4845 (void)InitScope.Privatize();
4846 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
4847 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
4848 /*capturedByInit=*/false);
4849 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004850 } else {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004851 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004852 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004853 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004854 ++FI;
4855 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004856}
4857
4858/// Check if duplication function is required for taskloops.
4859static bool checkInitIsRequired(CodeGenFunction &CGF,
4860 ArrayRef<PrivateDataTy> Privates) {
4861 bool InitRequired = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004862 for (const PrivateDataTy &Pair : Privates) {
4863 const VarDecl *VD = Pair.second.PrivateCopy;
4864 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004865 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) &&
4866 !CGF.isTrivialInitializer(Init));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004867 if (InitRequired)
4868 break;
Alexey Bataevf93095a2016-05-05 08:46:22 +00004869 }
4870 return InitRequired;
4871}
4872
4873
4874/// Emit task_dup function (for initialization of
4875/// private/firstprivate/lastprivate vars and last_iter flag)
4876/// \code
4877/// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int
4878/// lastpriv) {
4879/// // setup lastprivate flag
4880/// task_dst->last = lastpriv;
4881/// // could be constructor calls here...
4882/// }
4883/// \endcode
4884static llvm::Value *
4885emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
4886 const OMPExecutableDirective &D,
4887 QualType KmpTaskTWithPrivatesPtrQTy,
4888 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4889 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy,
4890 QualType SharedsPtrTy, const OMPTaskDataTy &Data,
4891 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004892 ASTContext &C = CGM.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004893 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004894 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4895 KmpTaskTWithPrivatesPtrQTy,
4896 ImplicitParamDecl::Other);
4897 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4898 KmpTaskTWithPrivatesPtrQTy,
4899 ImplicitParamDecl::Other);
4900 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy,
4901 ImplicitParamDecl::Other);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004902 Args.push_back(&DstArg);
4903 Args.push_back(&SrcArg);
4904 Args.push_back(&LastprivArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004905 const auto &TaskDupFnInfo =
Alexey Bataevf93095a2016-05-05 08:46:22 +00004906 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004907 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004908 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""});
4909 auto *TaskDup = llvm::Function::Create(
4910 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004911 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004912 TaskDup->setDoesNotRecurse();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004913 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004914 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc,
4915 Loc);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004916
4917 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4918 CGF.GetAddrOfLocalVar(&DstArg),
4919 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4920 // task_dst->liter = lastpriv;
4921 if (WithLastIter) {
4922 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
4923 LValue Base = CGF.EmitLValueForField(
4924 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4925 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4926 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar(
4927 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc);
4928 CGF.EmitStoreOfScalar(Lastpriv, LILVal);
4929 }
4930
4931 // Emit initial values for private copies (if any).
4932 assert(!Privates.empty());
4933 Address KmpTaskSharedsPtr = Address::invalid();
4934 if (!Data.FirstprivateVars.empty()) {
4935 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4936 CGF.GetAddrOfLocalVar(&SrcArg),
4937 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4938 LValue Base = CGF.EmitLValueForField(
4939 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4940 KmpTaskSharedsPtr = Address(
4941 CGF.EmitLoadOfScalar(CGF.EmitLValueForField(
4942 Base, *std::next(KmpTaskTQTyRD->field_begin(),
4943 KmpTaskTShareds)),
4944 Loc),
4945 CGF.getNaturalTypeAlignment(SharedsTy));
4946 }
Alexey Bataev8a831592016-05-10 10:36:51 +00004947 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
4948 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004949 CGF.FinishFunction();
4950 return TaskDup;
4951}
4952
Alexey Bataev8a831592016-05-10 10:36:51 +00004953/// Checks if destructor function is required to be generated.
4954/// \return true if cleanups are required, false otherwise.
4955static bool
4956checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) {
4957 bool NeedsCleanup = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004958 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4959 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl());
4960 for (const FieldDecl *FD : PrivateRD->fields()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00004961 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType();
4962 if (NeedsCleanup)
4963 break;
4964 }
4965 return NeedsCleanup;
4966}
4967
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004968CGOpenMPRuntime::TaskResultTy
4969CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
4970 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00004971 llvm::Function *TaskFunction, QualType SharedsTy,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004972 Address Shareds, const OMPTaskDataTy &Data) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004973 ASTContext &C = CGM.getContext();
Alexey Bataev7292c292016-04-25 12:22:29 +00004974 llvm::SmallVector<PrivateDataTy, 4> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004975 // Aggregate privates and sort them by the alignment.
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004976 auto I = Data.PrivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004977 for (const Expr *E : Data.PrivateVars) {
4978 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00004979 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00004980 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00004981 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00004982 /*PrivateElemInit=*/nullptr));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004983 ++I;
4984 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004985 I = Data.FirstprivateCopies.begin();
4986 auto IElemInitRef = Data.FirstprivateInits.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004987 for (const Expr *E : Data.FirstprivateVars) {
4988 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00004989 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00004990 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00004991 PrivateHelpersTy(
4992 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00004993 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())));
Richard Trieucc3949d2016-02-18 22:34:54 +00004994 ++I;
4995 ++IElemInitRef;
Alexey Bataev9e034042015-05-05 04:05:12 +00004996 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004997 I = Data.LastprivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004998 for (const Expr *E : Data.LastprivateVars) {
4999 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00005000 Privates.emplace_back(
Alexey Bataevf93095a2016-05-05 08:46:22 +00005001 C.getDeclAlign(VD),
5002 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00005003 /*PrivateElemInit=*/nullptr));
Alexey Bataevf93095a2016-05-05 08:46:22 +00005004 ++I;
5005 }
Fangrui Song899d1392019-04-24 14:43:05 +00005006 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) {
5007 return L.first > R.first;
5008 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005009 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005010 // Build type kmp_routine_entry_t (if not built yet).
5011 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005012 // Build type kmp_task_t (if not built yet).
Alexey Bataeve213f3e2017-10-11 15:29:40 +00005013 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) {
5014 if (SavedKmpTaskloopTQTy.isNull()) {
5015 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5016 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5017 }
5018 KmpTaskTQTy = SavedKmpTaskloopTQTy;
Alexey Bataev3a03a7f2017-10-11 15:56:38 +00005019 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00005020 assert((D.getDirectiveKind() == OMPD_task ||
5021 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) ||
5022 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) &&
5023 "Expected taskloop, task or target directive");
Alexey Bataeve213f3e2017-10-11 15:29:40 +00005024 if (SavedKmpTaskTQTy.isNull()) {
5025 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5026 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5027 }
5028 KmpTaskTQTy = SavedKmpTaskTQTy;
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005029 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005030 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005031 // Build particular struct kmp_task_t for the given task.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005032 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005033 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005034 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005035 QualType KmpTaskTWithPrivatesPtrQTy =
5036 C.getPointerType(KmpTaskTWithPrivatesQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005037 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
5038 llvm::Type *KmpTaskTWithPrivatesPtrTy =
5039 KmpTaskTWithPrivatesTy->getPointerTo();
5040 llvm::Value *KmpTaskTWithPrivatesTySize =
5041 CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005042 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
5043
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005044 // Emit initial values for private copies (if any).
5045 llvm::Value *TaskPrivatesMap = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005046 llvm::Type *TaskPrivatesMapTy =
James Y Knight9871db02019-02-05 16:42:33 +00005047 std::next(TaskFunction->arg_begin(), 3)->getType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005048 if (!Privates.empty()) {
5049 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataevf93095a2016-05-05 08:46:22 +00005050 TaskPrivatesMap = emitTaskPrivateMappingFunction(
5051 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars,
5052 FI->getType(), Privates);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005053 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5054 TaskPrivatesMap, TaskPrivatesMapTy);
5055 } else {
5056 TaskPrivatesMap = llvm::ConstantPointerNull::get(
5057 cast<llvm::PointerType>(TaskPrivatesMapTy));
5058 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005059 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
5060 // kmp_task_t *tt);
James Y Knight9871db02019-02-05 16:42:33 +00005061 llvm::Function *TaskEntry = emitProxyTaskFunction(
Alexey Bataev7292c292016-04-25 12:22:29 +00005062 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5063 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction,
5064 TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005065
5066 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
5067 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
5068 // kmp_routine_entry_t *task_entry);
5069 // Task flags. Format is taken from
James Y Knight5d71fc52019-01-29 16:37:27 +00005070 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h,
Alexey Bataev62b63b12015-03-10 07:28:44 +00005071 // description of kmp_tasking_flags struct.
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005072 enum {
5073 TiedFlag = 0x1,
5074 FinalFlag = 0x2,
5075 DestructorsFlag = 0x8,
5076 PriorityFlag = 0x20
5077 };
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005078 unsigned Flags = Data.Tied ? TiedFlag : 0;
Alexey Bataev8a831592016-05-10 10:36:51 +00005079 bool NeedsCleanup = false;
5080 if (!Privates.empty()) {
5081 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD);
5082 if (NeedsCleanup)
5083 Flags = Flags | DestructorsFlag;
5084 }
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005085 if (Data.Priority.getInt())
5086 Flags = Flags | PriorityFlag;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005087 llvm::Value *TaskFlags =
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005088 Data.Final.getPointer()
5089 ? CGF.Builder.CreateSelect(Data.Final.getPointer(),
Alexey Bataev62b63b12015-03-10 07:28:44 +00005090 CGF.Builder.getInt32(FinalFlag),
5091 CGF.Builder.getInt32(/*C=*/0))
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005092 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005093 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005094 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00005095 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc),
5096 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
5097 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5098 TaskEntry, KmpRoutineEntryPtrTy)};
5099 llvm::Value *NewTask;
5100 if (D.hasClausesOfKind<OMPNowaitClause>()) {
5101 // Check if we have any device clause associated with the directive.
5102 const Expr *Device = nullptr;
5103 if (auto *C = D.getSingleClause<OMPDeviceClause>())
5104 Device = C->getDevice();
5105 // Emit device ID if any otherwise use default value.
5106 llvm::Value *DeviceID;
5107 if (Device)
5108 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
5109 CGF.Int64Ty, /*isSigned=*/true);
5110 else
5111 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
5112 AllocArgs.push_back(DeviceID);
5113 NewTask = CGF.EmitRuntimeCall(
5114 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs);
5115 } else {
5116 NewTask = CGF.EmitRuntimeCall(
Alexey Bataev62b63b12015-03-10 07:28:44 +00005117 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00005118 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005119 llvm::Value *NewTaskNewTaskTTy =
5120 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5121 NewTask, KmpTaskTWithPrivatesPtrTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005122 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
5123 KmpTaskTWithPrivatesQTy);
5124 LValue TDBase =
5125 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005126 // Fill the data in the resulting kmp_task_t record.
5127 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00005128 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005129 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00005130 KmpTaskSharedsPtr =
5131 Address(CGF.EmitLoadOfScalar(
5132 CGF.EmitLValueForField(
5133 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
5134 KmpTaskTShareds)),
5135 Loc),
5136 CGF.getNaturalTypeAlignment(SharedsTy));
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00005137 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy);
5138 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy);
Richard Smithe78fac52018-04-05 20:52:58 +00005139 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005140 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005141 // Emit initial values for private copies (if any).
Alexey Bataevf93095a2016-05-05 08:46:22 +00005142 TaskResultTy Result;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005143 if (!Privates.empty()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00005144 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD,
5145 SharedsTy, SharedsPtrTy, Data, Privates,
5146 /*ForDup=*/false);
Alexey Bataevf93095a2016-05-05 08:46:22 +00005147 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
5148 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) {
5149 Result.TaskDupFn = emitTaskDupFunction(
5150 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
5151 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates,
5152 /*WithLastIter=*/!Data.LastprivateVars.empty());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005153 }
5154 }
Alexey Bataevad537bb2016-05-30 09:06:50 +00005155 // Fields of union "kmp_cmplrdata_t" for destructors and priority.
5156 enum { Priority = 0, Destructors = 1 };
Alexey Bataev62b63b12015-03-10 07:28:44 +00005157 // Provide pointer to function with destructors for privates.
Alexey Bataevad537bb2016-05-30 09:06:50 +00005158 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005159 const RecordDecl *KmpCmplrdataUD =
5160 (*FI)->getType()->getAsUnionType()->getDecl();
Alexey Bataevad537bb2016-05-30 09:06:50 +00005161 if (NeedsCleanup) {
5162 llvm::Value *DestructorFn = emitDestructorsFunction(
5163 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5164 KmpTaskTWithPrivatesQTy);
5165 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI);
5166 LValue DestructorsLV = CGF.EmitLValueForField(
5167 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
5168 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5169 DestructorFn, KmpRoutineEntryPtrTy),
5170 DestructorsLV);
5171 }
5172 // Set priority.
5173 if (Data.Priority.getInt()) {
5174 LValue Data2LV = CGF.EmitLValueForField(
5175 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
5176 LValue PriorityLV = CGF.EmitLValueForField(
5177 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
5178 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV);
5179 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005180 Result.NewTask = NewTask;
5181 Result.TaskEntry = TaskEntry;
5182 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
5183 Result.TDBase = TDBase;
5184 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
5185 return Result;
Alexey Bataev7292c292016-04-25 12:22:29 +00005186}
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005187
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005188void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
5189 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005190 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005191 QualType SharedsTy, Address Shareds,
5192 const Expr *IfCond,
5193 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005194 if (!CGF.HaveInsertPoint())
5195 return;
5196
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005197 TaskResultTy Result =
5198 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
5199 llvm::Value *NewTask = Result.NewTask;
James Y Knight9871db02019-02-05 16:42:33 +00005200 llvm::Function *TaskEntry = Result.TaskEntry;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005201 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy;
5202 LValue TDBase = Result.TDBase;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005203 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD;
5204 ASTContext &C = CGM.getContext();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005205 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00005206 Address DependenciesArray = Address::invalid();
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005207 unsigned NumDependencies = Data.Dependences.size();
John McCall7f416cc2015-09-08 08:05:57 +00005208 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005209 // Dependence kind for RTL.
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005210 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 };
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005211 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
5212 RecordDecl *KmpDependInfoRD;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005213 QualType FlagsTy =
5214 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005215 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
5216 if (KmpDependInfoTy.isNull()) {
5217 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
5218 KmpDependInfoRD->startDefinition();
5219 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
5220 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
5221 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
5222 KmpDependInfoRD->completeDefinition();
5223 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005224 } else {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005225 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005226 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005227 // Define type kmp_depend_info[<Dependences.size()>];
5228 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00005229 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Richard Smith772e2662019-10-04 01:25:59 +00005230 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005231 // kmp_depend_info[<Dependences.size()>] deps;
Alexey Bataev48591dd2016-04-20 04:01:36 +00005232 DependenciesArray =
5233 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005234 for (unsigned I = 0; I < NumDependencies; ++I) {
5235 const Expr *E = Data.Dependences[I].second;
5236 LValue Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005237 llvm::Value *Size;
5238 QualType Ty = E->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005239 if (const auto *ASE =
5240 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005241 LValue UpAddrLVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005242 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005243 llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32(
5244 UpAddrLVal.getPointer(CGF), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005245 llvm::Value *LowIntPtr =
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005246 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005247 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
5248 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005249 } else {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005250 Size = CGF.getTypeSize(Ty);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005251 }
5252 LValue Base = CGF.MakeAddrLValue(
James Y Knight751fe282019-02-09 22:22:28 +00005253 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005254 KmpDependInfoTy);
5255 // deps[i].base_addr = &<Dependences[i].second>;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005256 LValue BaseAddrLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005257 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00005258 CGF.EmitStoreOfScalar(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005259 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGF.IntPtrTy),
John McCall7f416cc2015-09-08 08:05:57 +00005260 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005261 // deps[i].len = sizeof(<Dependences[i].second>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005262 LValue LenLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005263 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
5264 CGF.EmitStoreOfScalar(Size, LenLVal);
5265 // deps[i].flags = <Dependences[i].first>;
5266 RTLDependenceKindTy DepKind;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005267 switch (Data.Dependences[I].first) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005268 case OMPC_DEPEND_in:
5269 DepKind = DepIn;
5270 break;
Alexey Bataev92e82f92015-11-23 13:33:42 +00005271 // Out and InOut dependencies must use the same code.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005272 case OMPC_DEPEND_out:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005273 case OMPC_DEPEND_inout:
5274 DepKind = DepInOut;
5275 break;
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005276 case OMPC_DEPEND_mutexinoutset:
5277 DepKind = DepMutexInOutSet;
5278 break;
Alexey Bataeveb482352015-12-18 05:05:56 +00005279 case OMPC_DEPEND_source:
Alexey Bataeva636c7f2015-12-23 10:27:45 +00005280 case OMPC_DEPEND_sink:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005281 case OMPC_DEPEND_unknown:
5282 llvm_unreachable("Unknown task dependence type");
5283 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005284 LValue FlagsLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005285 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
5286 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
5287 FlagsLVal);
5288 }
John McCall7f416cc2015-09-08 08:05:57 +00005289 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knightf5f1b0e2019-02-08 15:34:12 +00005290 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005291 }
5292
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005293 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev62b63b12015-03-10 07:28:44 +00005294 // libcall.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005295 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
5296 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
5297 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
5298 // list is not empty
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005299 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5300 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00005301 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
5302 llvm::Value *DepTaskArgs[7];
5303 if (NumDependencies) {
5304 DepTaskArgs[0] = UpLoc;
5305 DepTaskArgs[1] = ThreadID;
5306 DepTaskArgs[2] = NewTask;
5307 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
5308 DepTaskArgs[4] = DependenciesArray.getPointer();
5309 DepTaskArgs[5] = CGF.Builder.getInt32(0);
5310 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5311 }
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005312 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies,
5313 &TaskArgs,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005314 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005315 if (!Data.Tied) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005316 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005317 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
Alexey Bataev48591dd2016-04-20 04:01:36 +00005318 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
5319 }
John McCall7f416cc2015-09-08 08:05:57 +00005320 if (NumDependencies) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005321 CGF.EmitRuntimeCall(
Alexey Bataev48591dd2016-04-20 04:01:36 +00005322 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs);
John McCall7f416cc2015-09-08 08:05:57 +00005323 } else {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005324 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
John McCall7f416cc2015-09-08 08:05:57 +00005325 TaskArgs);
5326 }
Alexey Bataev48591dd2016-04-20 04:01:36 +00005327 // Check if parent region is untied and build return for untied task;
5328 if (auto *Region =
5329 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
5330 Region->emitUntiedSwitch(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00005331 };
John McCall7f416cc2015-09-08 08:05:57 +00005332
5333 llvm::Value *DepWaitTaskArgs[6];
5334 if (NumDependencies) {
5335 DepWaitTaskArgs[0] = UpLoc;
5336 DepWaitTaskArgs[1] = ThreadID;
5337 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
5338 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
5339 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
5340 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5341 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005342 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
Alexey Bataev3c595a62017-08-14 15:01:03 +00005343 NumDependencies, &DepWaitTaskArgs,
5344 Loc](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005345 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005346 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
5347 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
5348 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
5349 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
5350 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00005351 if (NumDependencies)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005352 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005353 DepWaitTaskArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005354 // Call proxy_task_entry(gtid, new_task);
Alexey Bataev3c595a62017-08-14 15:01:03 +00005355 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
5356 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005357 Action.Enter(CGF);
5358 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
Alexey Bataev3c595a62017-08-14 15:01:03 +00005359 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
Alexey Bataev2c7eee52017-08-04 19:10:54 +00005360 OutlinedFnArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005361 };
5362
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005363 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
5364 // kmp_task_t *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005365 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
5366 // kmp_task_t *new_task);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005367 RegionCodeGenTy RCG(CodeGen);
5368 CommonActionTy Action(
5369 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs,
5370 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs);
5371 RCG.setAction(Action);
5372 RCG(CGF);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005373 };
John McCall7f416cc2015-09-08 08:05:57 +00005374
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005375 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -05005376 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005377 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005378 RegionCodeGenTy ThenRCG(ThenCodeGen);
5379 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00005380 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005381}
5382
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005383void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
5384 const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005385 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005386 QualType SharedsTy, Address Shareds,
5387 const Expr *IfCond,
5388 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005389 if (!CGF.HaveInsertPoint())
5390 return;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005391 TaskResultTy Result =
5392 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005393 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev7292c292016-04-25 12:22:29 +00005394 // libcall.
5395 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
5396 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
5397 // sched, kmp_uint64 grainsize, void *task_dup);
5398 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5399 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
5400 llvm::Value *IfVal;
5401 if (IfCond) {
5402 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy,
5403 /*isSigned=*/true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005404 } else {
Alexey Bataev7292c292016-04-25 12:22:29 +00005405 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005406 }
Alexey Bataev7292c292016-04-25 12:22:29 +00005407
5408 LValue LBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005409 Result.TDBase,
5410 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005411 const auto *LBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005412 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005413 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF),
5414 LBLVal.getQuals(),
Alexey Bataev7292c292016-04-25 12:22:29 +00005415 /*IsInitializer=*/true);
5416 LValue UBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005417 Result.TDBase,
5418 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005419 const auto *UBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005420 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005421 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF),
5422 UBLVal.getQuals(),
Alexey Bataev7292c292016-04-25 12:22:29 +00005423 /*IsInitializer=*/true);
5424 LValue StLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005425 Result.TDBase,
5426 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005427 const auto *StVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005428 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005429 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF),
5430 StLVal.getQuals(),
Alexey Bataev7292c292016-04-25 12:22:29 +00005431 /*IsInitializer=*/true);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005432 // Store reductions address.
5433 LValue RedLVal = CGF.EmitLValueForField(
5434 Result.TDBase,
5435 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005436 if (Data.Reductions) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005437 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005438 } else {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005439 CGF.EmitNullInitialization(RedLVal.getAddress(CGF),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005440 CGF.getContext().VoidPtrTy);
5441 }
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005442 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
Alexey Bataev7292c292016-04-25 12:22:29 +00005443 llvm::Value *TaskArgs[] = {
Alexey Bataev33446032017-07-12 18:09:32 +00005444 UpLoc,
5445 ThreadID,
5446 Result.NewTask,
5447 IfVal,
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005448 LBLVal.getPointer(CGF),
5449 UBLVal.getPointer(CGF),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00005450 CGF.EmitLoadOfScalar(StLVal, Loc),
Alexey Bataevac6e4de2018-10-24 19:06:37 +00005451 llvm::ConstantInt::getSigned(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005452 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005453 llvm::ConstantInt::getSigned(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005454 CGF.IntTy, Data.Schedule.getPointer()
5455 ? Data.Schedule.getInt() ? NumTasks : Grainsize
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005456 : NoSchedule),
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005457 Data.Schedule.getPointer()
5458 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty,
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005459 /*isSigned=*/false)
5460 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0),
Alexey Bataev33446032017-07-12 18:09:32 +00005461 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5462 Result.TaskDupFn, CGF.VoidPtrTy)
5463 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)};
Alexey Bataev7292c292016-04-25 12:22:29 +00005464 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs);
5465}
5466
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005467/// Emit reduction operation for each element of array (required for
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005468/// array sections) LHS op = RHS.
5469/// \param Type Type of array.
5470/// \param LHSVar Variable on the left side of the reduction operation
5471/// (references element of array in original variable).
5472/// \param RHSVar Variable on the right side of the reduction operation
5473/// (references element of array in original variable).
5474/// \param RedOpGen Generator of reduction operation with use of LHSVar and
5475/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00005476static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005477 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
5478 const VarDecl *RHSVar,
5479 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
5480 const Expr *, const Expr *)> &RedOpGen,
5481 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
5482 const Expr *UpExpr = nullptr) {
5483 // Perform element-by-element initialization.
5484 QualType ElementTy;
5485 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
5486 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
5487
5488 // Drill down to the base element type on both arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005489 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
5490 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005491
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005492 llvm::Value *RHSBegin = RHSAddr.getPointer();
5493 llvm::Value *LHSBegin = LHSAddr.getPointer();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005494 // Cast from pointer to array type to pointer to single element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005495 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005496 // The basic structure here is a while-do loop.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005497 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
5498 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
5499 llvm::Value *IsEmpty =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005500 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
5501 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
5502
5503 // Enter the loop body, making that address the current address.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005504 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005505 CGF.EmitBlock(BodyBB);
5506
5507 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
5508
5509 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
5510 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
5511 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
5512 Address RHSElementCurrent =
5513 Address(RHSElementPHI,
5514 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5515
5516 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
5517 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
5518 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
5519 Address LHSElementCurrent =
5520 Address(LHSElementPHI,
5521 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5522
5523 // Emit copy.
5524 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005525 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; });
5526 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005527 Scope.Privatize();
5528 RedOpGen(CGF, XExpr, EExpr, UpExpr);
5529 Scope.ForceCleanup();
5530
5531 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005532 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005533 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005534 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005535 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
5536 // Check whether we've reached the end.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005537 llvm::Value *Done =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005538 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
5539 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
5540 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
5541 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
5542
5543 // Done.
5544 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
5545}
5546
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005547/// Emit reduction combiner. If the combiner is a simple expression emit it as
5548/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
5549/// UDR combiner function.
5550static void emitReductionCombiner(CodeGenFunction &CGF,
5551 const Expr *ReductionOp) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005552 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
5553 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
5554 if (const auto *DRE =
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005555 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005556 if (const auto *DRD =
5557 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005558 std::pair<llvm::Function *, llvm::Function *> Reduction =
5559 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
5560 RValue Func = RValue::get(Reduction.first);
5561 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
5562 CGF.EmitIgnoredExpr(ReductionOp);
5563 return;
5564 }
5565 CGF.EmitIgnoredExpr(ReductionOp);
5566}
5567
James Y Knight9871db02019-02-05 16:42:33 +00005568llvm::Function *CGOpenMPRuntime::emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005569 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates,
5570 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
5571 ArrayRef<const Expr *> ReductionOps) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005572 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005573
5574 // void reduction_func(void *LHSArg, void *RHSArg);
5575 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005576 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5577 ImplicitParamDecl::Other);
5578 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5579 ImplicitParamDecl::Other);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005580 Args.push_back(&LHSArg);
5581 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005582 const auto &CGFI =
5583 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00005584 std::string Name = getName({"omp", "reduction", "reduction_func"});
5585 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
5586 llvm::GlobalValue::InternalLinkage, Name,
5587 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00005588 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00005589 Fn->setDoesNotRecurse();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005590 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005591 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005592
5593 // Dst = (void*[n])(LHSArg);
5594 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00005595 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5596 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
5597 ArgsType), CGF.getPointerAlign());
5598 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5599 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
5600 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005601
5602 // ...
5603 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
5604 // ...
5605 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005606 auto IPriv = Privates.begin();
5607 unsigned Idx = 0;
5608 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005609 const auto *RHSVar =
5610 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
5611 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005612 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005613 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005614 const auto *LHSVar =
5615 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
5616 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005617 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005618 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005619 QualType PrivTy = (*IPriv)->getType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00005620 if (PrivTy->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005621 // Get array size and emit VLA type.
5622 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005623 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005624 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005625 const VariableArrayType *VLA =
5626 CGF.getContext().getAsVariableArrayType(PrivTy);
5627 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005628 CodeGenFunction::OpaqueValueMapping OpaqueMap(
Alexey Bataev1189bd02016-01-26 12:20:39 +00005629 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005630 CGF.EmitVariablyModifiedType(PrivTy);
5631 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005632 }
5633 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005634 IPriv = Privates.begin();
5635 auto ILHS = LHSExprs.begin();
5636 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005637 for (const Expr *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005638 if ((*IPriv)->getType()->isArrayType()) {
5639 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005640 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5641 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005642 EmitOMPAggregateReduction(
5643 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5644 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5645 emitReductionCombiner(CGF, E);
5646 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005647 } else {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005648 // Emit reduction for array subscript or single variable.
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005649 emitReductionCombiner(CGF, E);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005650 }
Richard Trieucc3949d2016-02-18 22:34:54 +00005651 ++IPriv;
5652 ++ILHS;
5653 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005654 }
5655 Scope.ForceCleanup();
5656 CGF.FinishFunction();
5657 return Fn;
5658}
5659
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005660void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF,
5661 const Expr *ReductionOp,
5662 const Expr *PrivateRef,
5663 const DeclRefExpr *LHS,
5664 const DeclRefExpr *RHS) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005665 if (PrivateRef->getType()->isArrayType()) {
5666 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005667 const auto *LHSVar = cast<VarDecl>(LHS->getDecl());
5668 const auto *RHSVar = cast<VarDecl>(RHS->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005669 EmitOMPAggregateReduction(
5670 CGF, PrivateRef->getType(), LHSVar, RHSVar,
5671 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5672 emitReductionCombiner(CGF, ReductionOp);
5673 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005674 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005675 // Emit reduction for array subscript or single variable.
5676 emitReductionCombiner(CGF, ReductionOp);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005677 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005678}
5679
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005680void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005681 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005682 ArrayRef<const Expr *> LHSExprs,
5683 ArrayRef<const Expr *> RHSExprs,
5684 ArrayRef<const Expr *> ReductionOps,
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005685 ReductionOptionsTy Options) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00005686 if (!CGF.HaveInsertPoint())
5687 return;
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005688
5689 bool WithNowait = Options.WithNowait;
5690 bool SimpleReduction = Options.SimpleReduction;
5691
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005692 // Next code should be emitted for reduction:
5693 //
5694 // static kmp_critical_name lock = { 0 };
5695 //
5696 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
5697 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
5698 // ...
5699 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
5700 // *(Type<n>-1*)rhs[<n>-1]);
5701 // }
5702 //
5703 // ...
5704 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
5705 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5706 // RedList, reduce_func, &<lock>)) {
5707 // case 1:
5708 // ...
5709 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5710 // ...
5711 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5712 // break;
5713 // case 2:
5714 // ...
5715 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5716 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00005717 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005718 // break;
5719 // default:;
5720 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005721 //
5722 // if SimpleReduction is true, only the next code is generated:
5723 // ...
5724 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5725 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005726
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005727 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005728
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005729 if (SimpleReduction) {
5730 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005731 auto IPriv = Privates.begin();
5732 auto ILHS = LHSExprs.begin();
5733 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005734 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005735 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5736 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005737 ++IPriv;
5738 ++ILHS;
5739 ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005740 }
5741 return;
5742 }
5743
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005744 // 1. Build a list of reduction variables.
5745 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005746 auto Size = RHSExprs.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005747 for (const Expr *E : Privates) {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005748 if (E->getType()->isVariablyModifiedType())
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005749 // Reserve place for array size.
5750 ++Size;
5751 }
5752 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005753 QualType ReductionArrayTy =
Richard Smith772e2662019-10-04 01:25:59 +00005754 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005755 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00005756 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005757 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005758 auto IPriv = Privates.begin();
5759 unsigned Idx = 0;
5760 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
James Y Knight751fe282019-02-09 22:22:28 +00005761 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
John McCall7f416cc2015-09-08 08:05:57 +00005762 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005763 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005764 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy),
John McCall7f416cc2015-09-08 08:05:57 +00005765 Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005766 if ((*IPriv)->getType()->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005767 // Store array size.
5768 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005769 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005770 llvm::Value *Size = CGF.Builder.CreateIntCast(
5771 CGF.getVLASize(
5772 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
Sander de Smalen891af03a2018-02-03 13:55:59 +00005773 .NumElts,
Alexey Bataev1189bd02016-01-26 12:20:39 +00005774 CGF.SizeTy, /*isSigned=*/false);
5775 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
5776 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005777 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005778 }
5779
5780 // 2. Emit reduce_func().
James Y Knight9871db02019-02-05 16:42:33 +00005781 llvm::Function *ReductionFn = emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005782 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
5783 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005784
5785 // 3. Create static kmp_critical_name lock = { 0 };
Alexey Bataev18fa2322018-05-02 14:20:50 +00005786 std::string Name = getName({"reduction"});
5787 llvm::Value *Lock = getCriticalRegionLock(Name);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005788
5789 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5790 // RedList, reduce_func, &<lock>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005791 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
5792 llvm::Value *ThreadId = getThreadID(CGF, Loc);
5793 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
5794 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Samuel Antao4c8035b2016-12-12 18:00:20 +00005795 ReductionList.getPointer(), CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005796 llvm::Value *Args[] = {
5797 IdentTLoc, // ident_t *<loc>
5798 ThreadId, // i32 <gtid>
5799 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
5800 ReductionArrayTySize, // size_type sizeof(RedList)
5801 RL, // void *RedList
5802 ReductionFn, // void (*) (void *, void *) <reduce_func>
5803 Lock // kmp_critical_name *&<lock>
5804 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005805 llvm::Value *Res = CGF.EmitRuntimeCall(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005806 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
5807 : OMPRTL__kmpc_reduce),
5808 Args);
5809
5810 // 5. Build switch(res)
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005811 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
5812 llvm::SwitchInst *SwInst =
5813 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005814
5815 // 6. Build case 1:
5816 // ...
5817 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5818 // ...
5819 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5820 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005821 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005822 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
5823 CGF.EmitBlock(Case1BB);
5824
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005825 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5826 llvm::Value *EndArgs[] = {
5827 IdentTLoc, // ident_t *<loc>
5828 ThreadId, // i32 <gtid>
5829 Lock // kmp_critical_name *&<lock>
5830 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005831 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5832 CodeGenFunction &CGF, PrePostActionTy &Action) {
5833 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005834 auto IPriv = Privates.begin();
5835 auto ILHS = LHSExprs.begin();
5836 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005837 for (const Expr *E : ReductionOps) {
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005838 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5839 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005840 ++IPriv;
5841 ++ILHS;
5842 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005843 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005844 };
5845 RegionCodeGenTy RCG(CodeGen);
5846 CommonActionTy Action(
5847 nullptr, llvm::None,
5848 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
5849 : OMPRTL__kmpc_end_reduce),
5850 EndArgs);
5851 RCG.setAction(Action);
5852 RCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005853
5854 CGF.EmitBranch(DefaultBB);
5855
5856 // 7. Build case 2:
5857 // ...
5858 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5859 // ...
5860 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005861 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005862 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
5863 CGF.EmitBlock(Case2BB);
5864
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005865 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
5866 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005867 auto ILHS = LHSExprs.begin();
5868 auto IRHS = RHSExprs.begin();
5869 auto IPriv = Privates.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005870 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005871 const Expr *XExpr = nullptr;
5872 const Expr *EExpr = nullptr;
5873 const Expr *UpExpr = nullptr;
5874 BinaryOperatorKind BO = BO_Comma;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005875 if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005876 if (BO->getOpcode() == BO_Assign) {
5877 XExpr = BO->getLHS();
5878 UpExpr = BO->getRHS();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005879 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005880 }
5881 // Try to emit update expression as a simple atomic.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005882 const Expr *RHSExpr = UpExpr;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005883 if (RHSExpr) {
5884 // Analyze RHS part of the whole expression.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005885 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005886 RHSExpr->IgnoreParenImpCasts())) {
5887 // If this is a conditional operator, analyze its condition for
5888 // min/max reduction operator.
5889 RHSExpr = ACO->getCond();
Alexey Bataev69a47792015-05-07 03:54:03 +00005890 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005891 if (const auto *BORHS =
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005892 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
5893 EExpr = BORHS->getRHS();
5894 BO = BORHS->getOpcode();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005895 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005896 }
5897 if (XExpr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005898 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005899 auto &&AtomicRedGen = [BO, VD,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005900 Loc](CodeGenFunction &CGF, const Expr *XExpr,
5901 const Expr *EExpr, const Expr *UpExpr) {
5902 LValue X = CGF.EmitLValue(XExpr);
5903 RValue E;
5904 if (EExpr)
5905 E = CGF.EmitAnyExpr(EExpr);
5906 CGF.EmitOMPAtomicSimpleUpdateExpr(
JF Bastien92f4ef12016-04-06 17:26:42 +00005907 X, E, BO, /*IsXLHSInRHSPart=*/true,
5908 llvm::AtomicOrdering::Monotonic, Loc,
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005909 [&CGF, UpExpr, VD, Loc](RValue XRValue) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005910 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5911 PrivateScope.addPrivate(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005912 VD, [&CGF, VD, XRValue, Loc]() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005913 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5914 CGF.emitOMPSimpleStore(
5915 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
5916 VD->getType().getNonReferenceType(), Loc);
5917 return LHSTemp;
5918 });
5919 (void)PrivateScope.Privatize();
5920 return CGF.EmitAnyExpr(UpExpr);
5921 });
5922 };
5923 if ((*IPriv)->getType()->isArrayType()) {
5924 // Emit atomic reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005925 const auto *RHSVar =
5926 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005927 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
5928 AtomicRedGen, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005929 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005930 // Emit atomic reduction for array subscript or single variable.
5931 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005932 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005933 } else {
5934 // Emit as a critical region.
5935 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
Alexey Bataev18fa2322018-05-02 14:20:50 +00005936 const Expr *, const Expr *) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005937 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev18fa2322018-05-02 14:20:50 +00005938 std::string Name = RT.getName({"atomic_reduction"});
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005939 RT.emitCriticalRegion(
Alexey Bataev18fa2322018-05-02 14:20:50 +00005940 CGF, Name,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005941 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
5942 Action.Enter(CGF);
5943 emitReductionCombiner(CGF, E);
5944 },
5945 Loc);
5946 };
5947 if ((*IPriv)->getType()->isArrayType()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005948 const auto *LHSVar =
5949 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5950 const auto *RHSVar =
5951 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005952 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5953 CritRedGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005954 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005955 CritRedGen(CGF, nullptr, nullptr, nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005956 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005957 }
Richard Trieucc3949d2016-02-18 22:34:54 +00005958 ++ILHS;
5959 ++IRHS;
5960 ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005961 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005962 };
5963 RegionCodeGenTy AtomicRCG(AtomicCodeGen);
5964 if (!WithNowait) {
5965 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
5966 llvm::Value *EndArgs[] = {
5967 IdentTLoc, // ident_t *<loc>
5968 ThreadId, // i32 <gtid>
5969 Lock // kmp_critical_name *&<lock>
5970 };
5971 CommonActionTy Action(nullptr, llvm::None,
5972 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
5973 EndArgs);
5974 AtomicRCG.setAction(Action);
5975 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005976 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005977 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005978 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005979
5980 CGF.EmitBranch(DefaultBB);
5981 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
5982}
5983
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005984/// Generates unique name for artificial threadprivate variables.
Alexey Bataev1c44e152018-03-06 18:59:43 +00005985/// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>"
5986static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix,
5987 const Expr *Ref) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005988 SmallString<256> Buffer;
5989 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev1c44e152018-03-06 18:59:43 +00005990 const clang::DeclRefExpr *DE;
5991 const VarDecl *D = ::getBaseDecl(Ref, DE);
5992 if (!D)
5993 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl());
5994 D = D->getCanonicalDecl();
Alexey Bataev18fa2322018-05-02 14:20:50 +00005995 std::string Name = CGM.getOpenMPRuntime().getName(
5996 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)});
5997 Out << Prefix << Name << "_"
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005998 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005999 return Out.str();
6000}
6001
6002/// Emits reduction initializer function:
6003/// \code
6004/// void @.red_init(void* %arg) {
6005/// %0 = bitcast void* %arg to <type>*
6006/// store <type> <init>, <type>* %0
6007/// ret void
6008/// }
6009/// \endcode
6010static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM,
6011 SourceLocation Loc,
6012 ReductionCodeGen &RCG, unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006013 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006014 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006015 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6016 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006017 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006018 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006019 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006020 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006021 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006022 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006023 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006024 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006025 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006026 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006027 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006028 Address PrivateAddr = CGF.EmitLoadOfPointer(
6029 CGF.GetAddrOfLocalVar(&Param),
6030 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6031 llvm::Value *Size = nullptr;
6032 // If the size of the reduction item is non-constant, load it from global
6033 // threadprivate variable.
6034 if (RCG.getSizes(N).second) {
6035 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6036 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006037 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006038 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6039 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006040 }
6041 RCG.emitAggregateType(CGF, N, Size);
6042 LValue SharedLVal;
6043 // If initializer uses initializer from declare reduction construct, emit a
6044 // pointer to the address of the original reduction item (reuired by reduction
6045 // initializer)
6046 if (RCG.usesReductionInitializer(N)) {
6047 Address SharedAddr =
6048 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6049 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006050 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataev21dab122018-03-09 15:20:30 +00006051 SharedAddr = CGF.EmitLoadOfPointer(
6052 SharedAddr,
6053 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006054 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy);
6055 } else {
6056 SharedLVal = CGF.MakeNaturalAlignAddrLValue(
6057 llvm::ConstantPointerNull::get(CGM.VoidPtrTy),
6058 CGM.getContext().VoidPtrTy);
6059 }
6060 // Emit the initializer:
6061 // %0 = bitcast void* %arg to <type>*
6062 // store <type> <init>, <type>* %0
6063 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal,
6064 [](CodeGenFunction &) { return false; });
6065 CGF.FinishFunction();
6066 return Fn;
6067}
6068
6069/// Emits reduction combiner function:
6070/// \code
6071/// void @.red_comb(void* %arg0, void* %arg1) {
6072/// %lhs = bitcast void* %arg0 to <type>*
6073/// %rhs = bitcast void* %arg1 to <type>*
6074/// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs)
6075/// store <type> %2, <type>* %lhs
6076/// ret void
6077/// }
6078/// \endcode
6079static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM,
6080 SourceLocation Loc,
6081 ReductionCodeGen &RCG, unsigned N,
6082 const Expr *ReductionOp,
6083 const Expr *LHS, const Expr *RHS,
6084 const Expr *PrivateRef) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006085 ASTContext &C = CGM.getContext();
6086 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl());
6087 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006088 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006089 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
6090 C.VoidPtrTy, ImplicitParamDecl::Other);
6091 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6092 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006093 Args.emplace_back(&ParamInOut);
6094 Args.emplace_back(&ParamIn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006095 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006096 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006097 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006098 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006099 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006100 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006101 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006102 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006103 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006104 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006105 llvm::Value *Size = nullptr;
6106 // If the size of the reduction item is non-constant, load it from global
6107 // threadprivate variable.
6108 if (RCG.getSizes(N).second) {
6109 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6110 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006111 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006112 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6113 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006114 }
6115 RCG.emitAggregateType(CGF, N, Size);
6116 // Remap lhs and rhs variables to the addresses of the function arguments.
6117 // %lhs = bitcast void* %arg0 to <type>*
6118 // %rhs = bitcast void* %arg1 to <type>*
6119 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006120 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006121 // Pull out the pointer to the variable.
6122 Address PtrAddr = CGF.EmitLoadOfPointer(
6123 CGF.GetAddrOfLocalVar(&ParamInOut),
6124 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6125 return CGF.Builder.CreateElementBitCast(
6126 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType()));
6127 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006128 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006129 // Pull out the pointer to the variable.
6130 Address PtrAddr = CGF.EmitLoadOfPointer(
6131 CGF.GetAddrOfLocalVar(&ParamIn),
6132 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6133 return CGF.Builder.CreateElementBitCast(
6134 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType()));
6135 });
6136 PrivateScope.Privatize();
6137 // Emit the combiner body:
6138 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs)
6139 // store <type> %2, <type>* %lhs
6140 CGM.getOpenMPRuntime().emitSingleReductionCombiner(
6141 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS),
6142 cast<DeclRefExpr>(RHS));
6143 CGF.FinishFunction();
6144 return Fn;
6145}
6146
6147/// Emits reduction finalizer function:
6148/// \code
6149/// void @.red_fini(void* %arg) {
6150/// %0 = bitcast void* %arg to <type>*
6151/// <destroy>(<type>* %0)
6152/// ret void
6153/// }
6154/// \endcode
6155static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM,
6156 SourceLocation Loc,
6157 ReductionCodeGen &RCG, unsigned N) {
6158 if (!RCG.needCleanups(N))
6159 return nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006160 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006161 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006162 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6163 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006164 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006165 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006166 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006167 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006168 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006169 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006170 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006171 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006172 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006173 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006174 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006175 Address PrivateAddr = CGF.EmitLoadOfPointer(
6176 CGF.GetAddrOfLocalVar(&Param),
6177 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6178 llvm::Value *Size = nullptr;
6179 // If the size of the reduction item is non-constant, load it from global
6180 // threadprivate variable.
6181 if (RCG.getSizes(N).second) {
6182 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6183 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006184 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006185 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6186 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006187 }
6188 RCG.emitAggregateType(CGF, N, Size);
6189 // Emit the finalizer body:
6190 // <destroy>(<type>* %0)
6191 RCG.emitCleanups(CGF, N, PrivateAddr);
6192 CGF.FinishFunction();
6193 return Fn;
6194}
6195
6196llvm::Value *CGOpenMPRuntime::emitTaskReductionInit(
6197 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
6198 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
6199 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty())
6200 return nullptr;
6201
6202 // Build typedef struct:
6203 // kmp_task_red_input {
6204 // void *reduce_shar; // shared reduction item
6205 // size_t reduce_size; // size of data item
6206 // void *reduce_init; // data initialization routine
6207 // void *reduce_fini; // data finalization routine
6208 // void *reduce_comb; // data combiner routine
6209 // kmp_task_red_flags_t flags; // flags for additional info from compiler
6210 // } kmp_task_red_input_t;
6211 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006212 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t");
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006213 RD->startDefinition();
6214 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6215 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType());
6216 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6217 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6218 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6219 const FieldDecl *FlagsFD = addFieldToRecordDecl(
6220 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false));
6221 RD->completeDefinition();
6222 QualType RDType = C.getRecordType(RD);
6223 unsigned Size = Data.ReductionVars.size();
6224 llvm::APInt ArraySize(/*numBits=*/64, Size);
6225 QualType ArrayRDType = C.getConstantArrayType(
Richard Smith772e2662019-10-04 01:25:59 +00006226 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006227 // kmp_task_red_input_t .rd_input.[Size];
6228 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input.");
6229 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies,
6230 Data.ReductionOps);
6231 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) {
6232 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt];
6233 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0),
6234 llvm::ConstantInt::get(CGM.SizeTy, Cnt)};
6235 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP(
6236 TaskRedInput.getPointer(), Idxs,
6237 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc,
6238 ".rd_input.gep.");
6239 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType);
6240 // ElemLVal.reduce_shar = &Shareds[Cnt];
6241 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD);
6242 RCG.emitSharedLValue(CGF, Cnt);
6243 llvm::Value *CastedShared =
Akira Hatanakaf139ae32019-12-03 15:17:01 -08006244 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006245 CGF.EmitStoreOfScalar(CastedShared, SharedLVal);
6246 RCG.emitAggregateType(CGF, Cnt);
6247 llvm::Value *SizeValInChars;
6248 llvm::Value *SizeVal;
6249 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt);
6250 // We use delayed creation/initialization for VLAs, array sections and
6251 // custom reduction initializations. It is required because runtime does not
6252 // provide the way to pass the sizes of VLAs/array sections to
6253 // initializer/combiner/finalizer functions and does not pass the pointer to
6254 // original reduction item to the initializer. Instead threadprivate global
6255 // variables are used to store these values and use them in the functions.
6256 bool DelayedCreation = !!SizeVal;
6257 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy,
6258 /*isSigned=*/false);
6259 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD);
6260 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal);
6261 // ElemLVal.reduce_init = init;
6262 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD);
6263 llvm::Value *InitAddr =
6264 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt));
6265 CGF.EmitStoreOfScalar(InitAddr, InitLVal);
6266 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt);
6267 // ElemLVal.reduce_fini = fini;
6268 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD);
6269 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt);
6270 llvm::Value *FiniAddr = Fini
6271 ? CGF.EmitCastToVoidPtr(Fini)
6272 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy);
6273 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal);
6274 // ElemLVal.reduce_comb = comb;
6275 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD);
6276 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction(
6277 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt],
6278 RHSExprs[Cnt], Data.ReductionCopies[Cnt]));
6279 CGF.EmitStoreOfScalar(CombAddr, CombLVal);
6280 // ElemLVal.flags = 0;
6281 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD);
6282 if (DelayedCreation) {
6283 CGF.EmitStoreOfScalar(
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006284 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006285 FlagsLVal);
6286 } else
Akira Hatanakaf139ae32019-12-03 15:17:01 -08006287 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF),
6288 FlagsLVal.getType());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006289 }
6290 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void
6291 // *data);
6292 llvm::Value *Args[] = {
6293 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6294 /*isSigned=*/true),
6295 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true),
6296 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(),
6297 CGM.VoidPtrTy)};
6298 return CGF.EmitRuntimeCall(
6299 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args);
6300}
6301
6302void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
6303 SourceLocation Loc,
6304 ReductionCodeGen &RCG,
6305 unsigned N) {
6306 auto Sizes = RCG.getSizes(N);
6307 // Emit threadprivate global variable if the type is non-constant
6308 // (Sizes.second = nullptr).
6309 if (Sizes.second) {
6310 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy,
6311 /*isSigned=*/false);
6312 Address SizeAddr = getAddrOfArtificialThreadPrivate(
6313 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006314 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006315 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false);
6316 }
6317 // Store address of the original reduction item if custom initializer is used.
6318 if (RCG.usesReductionInitializer(N)) {
6319 Address SharedAddr = getAddrOfArtificialThreadPrivate(
6320 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006321 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006322 CGF.Builder.CreateStore(
6323 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08006324 RCG.getSharedLValue(N).getPointer(CGF), CGM.VoidPtrTy),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006325 SharedAddr, /*IsVolatile=*/false);
6326 }
6327}
6328
6329Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF,
6330 SourceLocation Loc,
6331 llvm::Value *ReductionsPtr,
6332 LValue SharedLVal) {
6333 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
6334 // *d);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08006335 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc),
6336 CGM.IntTy,
6337 /*isSigned=*/true),
6338 ReductionsPtr,
6339 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6340 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)};
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006341 return Address(
6342 CGF.EmitRuntimeCall(
6343 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args),
6344 SharedLVal.getAlignment());
6345}
6346
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006347void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
6348 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006349 if (!CGF.HaveInsertPoint())
6350 return;
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006351 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
6352 // global_tid);
6353 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
6354 // Ignore return result until untied tasks are supported.
6355 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00006356 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
6357 Region->emitUntiedSwitch(CGF);
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006358}
6359
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006360void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006361 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00006362 const RegionCodeGenTy &CodeGen,
6363 bool HasCancel) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006364 if (!CGF.HaveInsertPoint())
6365 return;
Alexey Bataev25e5b442015-09-15 12:52:43 +00006366 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006367 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00006368}
6369
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006370namespace {
6371enum RTCancelKind {
6372 CancelNoreq = 0,
6373 CancelParallel = 1,
6374 CancelLoop = 2,
6375 CancelSections = 3,
6376 CancelTaskgroup = 4
6377};
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00006378} // anonymous namespace
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006379
6380static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
6381 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00006382 if (CancelRegion == OMPD_parallel)
6383 CancelKind = CancelParallel;
6384 else if (CancelRegion == OMPD_for)
6385 CancelKind = CancelLoop;
6386 else if (CancelRegion == OMPD_sections)
6387 CancelKind = CancelSections;
6388 else {
6389 assert(CancelRegion == OMPD_taskgroup);
6390 CancelKind = CancelTaskgroup;
6391 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006392 return CancelKind;
6393}
6394
6395void CGOpenMPRuntime::emitCancellationPointCall(
6396 CodeGenFunction &CGF, SourceLocation Loc,
6397 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006398 if (!CGF.HaveInsertPoint())
6399 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006400 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
6401 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006402 if (auto *OMPRegionInfo =
6403 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Jonas Hahnfeldb07931f2017-02-17 18:32:58 +00006404 // For 'cancellation point taskgroup', the task region info may not have a
6405 // cancel. This may instead happen in another adjacent task.
6406 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006407 llvm::Value *Args[] = {
6408 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
6409 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006410 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006411 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006412 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
6413 // if (__kmpc_cancellationpoint()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006414 // exit from construct;
6415 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006416 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6417 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6418 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006419 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6420 CGF.EmitBlock(ExitBB);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006421 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006422 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev25e5b442015-09-15 12:52:43 +00006423 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006424 CGF.EmitBranchThroughCleanup(CancelDest);
6425 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6426 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006427 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006428}
6429
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006430void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00006431 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006432 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006433 if (!CGF.HaveInsertPoint())
6434 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006435 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
6436 // kmp_int32 cncl_kind);
6437 if (auto *OMPRegionInfo =
6438 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006439 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF,
6440 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006441 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev87933c72015-09-18 08:07:34 +00006442 llvm::Value *Args[] = {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006443 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
Alexey Bataev87933c72015-09-18 08:07:34 +00006444 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
6445 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006446 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006447 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
Alexey Bataev87933c72015-09-18 08:07:34 +00006448 // if (__kmpc_cancel()) {
Alexey Bataev87933c72015-09-18 08:07:34 +00006449 // exit from construct;
6450 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006451 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6452 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6453 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev87933c72015-09-18 08:07:34 +00006454 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6455 CGF.EmitBlock(ExitBB);
Alexey Bataev87933c72015-09-18 08:07:34 +00006456 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006457 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev87933c72015-09-18 08:07:34 +00006458 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6459 CGF.EmitBranchThroughCleanup(CancelDest);
6460 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6461 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006462 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -05006463 emitIfClause(CGF, IfCond, ThenGen,
6464 [](CodeGenFunction &, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006465 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006466 RegionCodeGenTy ThenRCG(ThenGen);
6467 ThenRCG(CGF);
6468 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006469 }
6470}
Samuel Antaobed3c462015-10-02 16:14:20 +00006471
Samuel Antaoee8fb302016-01-06 13:42:12 +00006472void CGOpenMPRuntime::emitTargetOutlinedFunction(
6473 const OMPExecutableDirective &D, StringRef ParentName,
6474 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006475 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00006476 assert(!ParentName.empty() && "Invalid target region parent name!");
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00006477 HasEmittedTargetRegion = true;
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006478 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
6479 IsOffloadEntry, CodeGen);
6480}
6481
6482void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
6483 const OMPExecutableDirective &D, StringRef ParentName,
6484 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6485 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antao2de62b02016-02-13 23:35:10 +00006486 // Create a unique name for the entry function using the source location
6487 // information of the current target region. The name will be something like:
Samuel Antaoee8fb302016-01-06 13:42:12 +00006488 //
Samuel Antao2de62b02016-02-13 23:35:10 +00006489 // __omp_offloading_DD_FFFF_PP_lBB
Samuel Antaoee8fb302016-01-06 13:42:12 +00006490 //
6491 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
Samuel Antao2de62b02016-02-13 23:35:10 +00006492 // mangled name of the function that encloses the target region and BB is the
6493 // line number of the target region.
Samuel Antaoee8fb302016-01-06 13:42:12 +00006494
6495 unsigned DeviceID;
6496 unsigned FileID;
6497 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00006498 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00006499 Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006500 SmallString<64> EntryFnName;
6501 {
6502 llvm::raw_svector_ostream OS(EntryFnName);
Samuel Antao2de62b02016-02-13 23:35:10 +00006503 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
6504 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00006505 }
6506
Alexey Bataev475a7442018-01-12 19:39:11 +00006507 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006508
Samuel Antaobed3c462015-10-02 16:14:20 +00006509 CodeGenFunction CGF(CGM, true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006510 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
Samuel Antaobed3c462015-10-02 16:14:20 +00006511 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006512
Samuel Antao6d004262016-06-16 18:39:34 +00006513 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006514
6515 // If this target outline function is not an offload entry, we don't need to
6516 // register it.
6517 if (!IsOffloadEntry)
6518 return;
6519
6520 // The target region ID is used by the runtime library to identify the current
6521 // target region, so it only has to be unique and not necessarily point to
6522 // anything. It could be the pointer to the outlined function that implements
6523 // the target region, but we aren't using that so that the compiler doesn't
6524 // need to keep that, and could therefore inline the host function if proven
6525 // worthwhile during optimization. In the other hand, if emitting code for the
6526 // device, the ID has to be the function address so that it can retrieved from
6527 // the offloading entry and launched by the runtime library. We also mark the
6528 // outlined function to have external linkage in case we are emitting code for
6529 // the device, because these functions will be entry points to the device.
6530
6531 if (CGM.getLangOpts().OpenMPIsDevice) {
6532 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
Alexey Bataev9a700172018-05-08 14:16:57 +00006533 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Rafael Espindolacbca4872018-01-11 22:15:12 +00006534 OutlinedFn->setDSOLocal(false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006535 } else {
Alexey Bataevc15ea702018-05-09 18:02:37 +00006536 std::string Name = getName({EntryFnName, "region_id"});
Samuel Antaoee8fb302016-01-06 13:42:12 +00006537 OutlinedFnID = new llvm::GlobalVariable(
6538 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
Alexey Bataev9a700172018-05-08 14:16:57 +00006539 llvm::GlobalValue::WeakAnyLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006540 llvm::Constant::getNullValue(CGM.Int8Ty), Name);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006541 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00006542
6543 // Register the information for the entry associated with this target region.
6544 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
Samuel Antaof83efdb2017-01-05 16:02:49 +00006545 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID,
Alexey Bataev03f270c2018-03-30 18:31:07 +00006546 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion);
Samuel Antaobed3c462015-10-02 16:14:20 +00006547}
6548
Alexey Bataev5c427362019-04-10 19:11:33 +00006549/// Checks if the expression is constant or does not have non-trivial function
6550/// calls.
6551static bool isTrivial(ASTContext &Ctx, const Expr * E) {
6552 // We can skip constant expressions.
6553 // We can skip expressions with trivial calls or simple expressions.
6554 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) ||
6555 !E->hasNonTrivialCall(Ctx)) &&
6556 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true);
6557}
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006558
Alexey Bataev5c427362019-04-10 19:11:33 +00006559const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx,
6560 const Stmt *Body) {
6561 const Stmt *Child = Body->IgnoreContainers();
6562 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) {
6563 Child = nullptr;
6564 for (const Stmt *S : C->body()) {
6565 if (const auto *E = dyn_cast<Expr>(S)) {
6566 if (isTrivial(Ctx, E))
6567 continue;
6568 }
6569 // Some of the statements can be ignored.
6570 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) ||
6571 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S))
6572 continue;
6573 // Analyze declarations.
6574 if (const auto *DS = dyn_cast<DeclStmt>(S)) {
6575 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) {
6576 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6577 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6578 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6579 isa<UsingDirectiveDecl>(D) ||
6580 isa<OMPDeclareReductionDecl>(D) ||
6581 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6582 return true;
6583 const auto *VD = dyn_cast<VarDecl>(D);
6584 if (!VD)
6585 return false;
6586 return VD->isConstexpr() ||
6587 ((VD->getType().isTrivialType(Ctx) ||
6588 VD->getType()->isReferenceType()) &&
6589 (!VD->hasInit() || isTrivial(Ctx, VD->getInit())));
6590 }))
6591 continue;
6592 }
6593 // Found multiple children - cannot get the one child only.
6594 if (Child)
6595 return nullptr;
6596 Child = S;
6597 }
6598 if (Child)
6599 Child = Child->IgnoreContainers();
6600 }
6601 return Child;
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006602}
6603
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006604/// Emit the number of teams for a target directive. Inspect the num_teams
6605/// clause associated with a teams construct combined or closely nested
6606/// with the target directive.
6607///
6608/// Emit a team of size one for directives such as 'target parallel' that
6609/// have no associated teams construct.
6610///
6611/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006612static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006613emitNumTeamsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006614 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006615 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6616 "Clauses associated with the teams directive expected to be emitted "
6617 "only for the host!");
6618 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6619 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6620 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006621 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006622 switch (DirectiveKind) {
6623 case OMPD_target: {
6624 const auto *CS = D.getInnermostCapturedStmt();
6625 const auto *Body =
6626 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
6627 const Stmt *ChildStmt =
6628 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body);
6629 if (const auto *NestedDir =
6630 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6631 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) {
6632 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) {
6633 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6634 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6635 const Expr *NumTeams =
6636 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6637 llvm::Value *NumTeamsVal =
6638 CGF.EmitScalarExpr(NumTeams,
6639 /*IgnoreResultAssign*/ true);
6640 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006641 /*isSigned=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00006642 }
6643 return Bld.getInt32(0);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006644 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006645 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) ||
6646 isOpenMPSimdDirective(NestedDir->getDirectiveKind()))
6647 return Bld.getInt32(1);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006648 return Bld.getInt32(0);
6649 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006650 return nullptr;
Samuel Antaob68e2db2016-03-03 16:20:23 +00006651 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006652 case OMPD_target_teams:
6653 case OMPD_target_teams_distribute:
6654 case OMPD_target_teams_distribute_simd:
6655 case OMPD_target_teams_distribute_parallel_for:
6656 case OMPD_target_teams_distribute_parallel_for_simd: {
6657 if (D.hasClausesOfKind<OMPNumTeamsClause>()) {
6658 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF);
6659 const Expr *NumTeams =
6660 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6661 llvm::Value *NumTeamsVal =
6662 CGF.EmitScalarExpr(NumTeams,
6663 /*IgnoreResultAssign*/ true);
6664 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006665 /*isSigned=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00006666 }
6667 return Bld.getInt32(0);
6668 }
6669 case OMPD_target_parallel:
6670 case OMPD_target_parallel_for:
6671 case OMPD_target_parallel_for_simd:
6672 case OMPD_target_simd:
6673 return Bld.getInt32(1);
6674 case OMPD_parallel:
6675 case OMPD_for:
6676 case OMPD_parallel_for:
6677 case OMPD_parallel_sections:
6678 case OMPD_for_simd:
6679 case OMPD_parallel_for_simd:
6680 case OMPD_cancel:
6681 case OMPD_cancellation_point:
6682 case OMPD_ordered:
6683 case OMPD_threadprivate:
6684 case OMPD_allocate:
6685 case OMPD_task:
6686 case OMPD_simd:
6687 case OMPD_sections:
6688 case OMPD_section:
6689 case OMPD_single:
6690 case OMPD_master:
6691 case OMPD_critical:
6692 case OMPD_taskyield:
6693 case OMPD_barrier:
6694 case OMPD_taskwait:
6695 case OMPD_taskgroup:
6696 case OMPD_atomic:
6697 case OMPD_flush:
6698 case OMPD_teams:
6699 case OMPD_target_data:
6700 case OMPD_target_exit_data:
6701 case OMPD_target_enter_data:
6702 case OMPD_distribute:
6703 case OMPD_distribute_simd:
6704 case OMPD_distribute_parallel_for:
6705 case OMPD_distribute_parallel_for_simd:
6706 case OMPD_teams_distribute:
6707 case OMPD_teams_distribute_simd:
6708 case OMPD_teams_distribute_parallel_for:
6709 case OMPD_teams_distribute_parallel_for_simd:
6710 case OMPD_target_update:
6711 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00006712 case OMPD_declare_variant:
Alexey Bataev5c427362019-04-10 19:11:33 +00006713 case OMPD_declare_target:
6714 case OMPD_end_declare_target:
6715 case OMPD_declare_reduction:
6716 case OMPD_declare_mapper:
6717 case OMPD_taskloop:
6718 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00006719 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00006720 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00006721 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04006722 case OMPD_parallel_master_taskloop_simd:
Alexey Bataev5c427362019-04-10 19:11:33 +00006723 case OMPD_requires:
6724 case OMPD_unknown:
6725 break;
6726 }
6727 llvm_unreachable("Unexpected directive kind.");
6728}
Samuel Antaob68e2db2016-03-03 16:20:23 +00006729
Alexey Bataev5c427362019-04-10 19:11:33 +00006730static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS,
6731 llvm::Value *DefaultThreadLimitVal) {
6732 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6733 CGF.getContext(), CS->getCapturedStmt());
6734 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6735 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) {
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006736 llvm::Value *NumThreads = nullptr;
6737 llvm::Value *CondVal = nullptr;
6738 // Handle if clause. If if clause present, the number of threads is
6739 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6740 if (Dir->hasClausesOfKind<OMPIfClause>()) {
6741 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6742 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6743 const OMPIfClause *IfClause = nullptr;
6744 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) {
6745 if (C->getNameModifier() == OMPD_unknown ||
6746 C->getNameModifier() == OMPD_parallel) {
6747 IfClause = C;
6748 break;
6749 }
6750 }
6751 if (IfClause) {
6752 const Expr *Cond = IfClause->getCondition();
6753 bool Result;
6754 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6755 if (!Result)
6756 return CGF.Builder.getInt32(1);
6757 } else {
6758 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange());
6759 if (const auto *PreInit =
6760 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) {
6761 for (const auto *I : PreInit->decls()) {
6762 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6763 CGF.EmitVarDecl(cast<VarDecl>(*I));
6764 } else {
6765 CodeGenFunction::AutoVarEmission Emission =
6766 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6767 CGF.EmitAutoVarCleanups(Emission);
6768 }
6769 }
6770 }
6771 CondVal = CGF.EvaluateExprAsBool(Cond);
6772 }
6773 }
6774 }
6775 // Check the value of num_threads clause iff if clause was not specified
6776 // or is not evaluated to false.
Alexey Bataev5c427362019-04-10 19:11:33 +00006777 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) {
6778 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6779 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6780 const auto *NumThreadsClause =
6781 Dir->getSingleClause<OMPNumThreadsClause>();
6782 CodeGenFunction::LexicalScope Scope(
6783 CGF, NumThreadsClause->getNumThreads()->getSourceRange());
6784 if (const auto *PreInit =
6785 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6786 for (const auto *I : PreInit->decls()) {
6787 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6788 CGF.EmitVarDecl(cast<VarDecl>(*I));
6789 } else {
6790 CodeGenFunction::AutoVarEmission Emission =
6791 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6792 CGF.EmitAutoVarCleanups(Emission);
6793 }
6794 }
6795 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006796 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads());
Alexey Bataev5c427362019-04-10 19:11:33 +00006797 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006798 /*isSigned=*/false);
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006799 if (DefaultThreadLimitVal)
6800 NumThreads = CGF.Builder.CreateSelect(
6801 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads),
6802 DefaultThreadLimitVal, NumThreads);
6803 } else {
6804 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal
6805 : CGF.Builder.getInt32(0);
Alexey Bataev5c427362019-04-10 19:11:33 +00006806 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006807 // Process condition of the if clause.
6808 if (CondVal) {
6809 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads,
6810 CGF.Builder.getInt32(1));
6811 }
6812 return NumThreads;
Alexey Bataev5c427362019-04-10 19:11:33 +00006813 }
6814 if (isOpenMPSimdDirective(Dir->getDirectiveKind()))
6815 return CGF.Builder.getInt32(1);
6816 return DefaultThreadLimitVal;
6817 }
6818 return DefaultThreadLimitVal ? DefaultThreadLimitVal
6819 : CGF.Builder.getInt32(0);
Samuel Antaob68e2db2016-03-03 16:20:23 +00006820}
6821
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006822/// Emit the number of threads for a target directive. Inspect the
6823/// thread_limit clause associated with a teams construct combined or closely
6824/// nested with the target directive.
6825///
6826/// Emit the num_threads clause for directives such as 'target parallel' that
6827/// have no associated teams construct.
6828///
6829/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006830static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006831emitNumThreadsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006832 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006833 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6834 "Clauses associated with the teams directive expected to be emitted "
6835 "only for the host!");
6836 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6837 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6838 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006839 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006840 llvm::Value *ThreadLimitVal = nullptr;
6841 llvm::Value *NumThreadsVal = nullptr;
6842 switch (DirectiveKind) {
6843 case OMPD_target: {
6844 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6845 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6846 return NumThreads;
6847 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6848 CGF.getContext(), CS->getCapturedStmt());
6849 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6850 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) {
6851 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6852 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6853 const auto *ThreadLimitClause =
6854 Dir->getSingleClause<OMPThreadLimitClause>();
6855 CodeGenFunction::LexicalScope Scope(
6856 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange());
6857 if (const auto *PreInit =
6858 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6859 for (const auto *I : PreInit->decls()) {
6860 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6861 CGF.EmitVarDecl(cast<VarDecl>(*I));
6862 } else {
6863 CodeGenFunction::AutoVarEmission Emission =
6864 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6865 CGF.EmitAutoVarCleanups(Emission);
6866 }
6867 }
6868 }
6869 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6870 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6871 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006872 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006873 }
6874 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) &&
6875 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) {
6876 CS = Dir->getInnermostCapturedStmt();
6877 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6878 CGF.getContext(), CS->getCapturedStmt());
6879 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6880 }
6881 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) &&
6882 !isOpenMPSimdDirective(Dir->getDirectiveKind())) {
6883 CS = Dir->getInnermostCapturedStmt();
6884 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6885 return NumThreads;
6886 }
6887 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind()))
6888 return Bld.getInt32(1);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006889 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006890 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6891 }
6892 case OMPD_target_teams: {
6893 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6894 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6895 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6896 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6897 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6898 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006899 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006900 }
6901 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6902 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6903 return NumThreads;
6904 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6905 CGF.getContext(), CS->getCapturedStmt());
6906 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6907 if (Dir->getDirectiveKind() == OMPD_distribute) {
6908 CS = Dir->getInnermostCapturedStmt();
6909 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6910 return NumThreads;
6911 }
6912 }
6913 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6914 }
6915 case OMPD_target_teams_distribute:
6916 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6917 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6918 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6919 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6920 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6921 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006922 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006923 }
6924 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal);
6925 case OMPD_target_parallel:
6926 case OMPD_target_parallel_for:
6927 case OMPD_target_parallel_for_simd:
6928 case OMPD_target_teams_distribute_parallel_for:
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006929 case OMPD_target_teams_distribute_parallel_for_simd: {
6930 llvm::Value *CondVal = nullptr;
6931 // Handle if clause. If if clause present, the number of threads is
6932 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6933 if (D.hasClausesOfKind<OMPIfClause>()) {
6934 const OMPIfClause *IfClause = nullptr;
6935 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) {
6936 if (C->getNameModifier() == OMPD_unknown ||
6937 C->getNameModifier() == OMPD_parallel) {
6938 IfClause = C;
6939 break;
6940 }
6941 }
6942 if (IfClause) {
6943 const Expr *Cond = IfClause->getCondition();
6944 bool Result;
6945 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6946 if (!Result)
6947 return Bld.getInt32(1);
6948 } else {
6949 CodeGenFunction::RunCleanupsScope Scope(CGF);
6950 CondVal = CGF.EvaluateExprAsBool(Cond);
6951 }
6952 }
6953 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006954 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6955 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6956 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6957 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6958 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6959 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006960 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006961 }
6962 if (D.hasClausesOfKind<OMPNumThreadsClause>()) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006963 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
Alexey Bataev5c427362019-04-10 19:11:33 +00006964 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>();
6965 llvm::Value *NumThreads = CGF.EmitScalarExpr(
6966 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true);
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006967 NumThreadsVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006968 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006969 ThreadLimitVal = ThreadLimitVal
Alexey Bataev5c427362019-04-10 19:11:33 +00006970 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal,
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006971 ThreadLimitVal),
6972 NumThreadsVal, ThreadLimitVal)
6973 : NumThreadsVal;
Alexey Bataev50a1c782017-12-01 21:31:08 +00006974 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006975 if (!ThreadLimitVal)
6976 ThreadLimitVal = Bld.getInt32(0);
6977 if (CondVal)
6978 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1));
6979 return ThreadLimitVal;
6980 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006981 case OMPD_target_teams_distribute_simd:
6982 case OMPD_target_simd:
6983 return Bld.getInt32(1);
6984 case OMPD_parallel:
6985 case OMPD_for:
6986 case OMPD_parallel_for:
6987 case OMPD_parallel_sections:
6988 case OMPD_for_simd:
6989 case OMPD_parallel_for_simd:
6990 case OMPD_cancel:
6991 case OMPD_cancellation_point:
6992 case OMPD_ordered:
6993 case OMPD_threadprivate:
6994 case OMPD_allocate:
6995 case OMPD_task:
6996 case OMPD_simd:
6997 case OMPD_sections:
6998 case OMPD_section:
6999 case OMPD_single:
7000 case OMPD_master:
7001 case OMPD_critical:
7002 case OMPD_taskyield:
7003 case OMPD_barrier:
7004 case OMPD_taskwait:
7005 case OMPD_taskgroup:
7006 case OMPD_atomic:
7007 case OMPD_flush:
7008 case OMPD_teams:
7009 case OMPD_target_data:
7010 case OMPD_target_exit_data:
7011 case OMPD_target_enter_data:
7012 case OMPD_distribute:
7013 case OMPD_distribute_simd:
7014 case OMPD_distribute_parallel_for:
7015 case OMPD_distribute_parallel_for_simd:
7016 case OMPD_teams_distribute:
7017 case OMPD_teams_distribute_simd:
7018 case OMPD_teams_distribute_parallel_for:
7019 case OMPD_teams_distribute_parallel_for_simd:
7020 case OMPD_target_update:
7021 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00007022 case OMPD_declare_variant:
Alexey Bataev5c427362019-04-10 19:11:33 +00007023 case OMPD_declare_target:
7024 case OMPD_end_declare_target:
7025 case OMPD_declare_reduction:
7026 case OMPD_declare_mapper:
7027 case OMPD_taskloop:
7028 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00007029 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00007030 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00007031 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04007032 case OMPD_parallel_master_taskloop_simd:
Alexey Bataev5c427362019-04-10 19:11:33 +00007033 case OMPD_requires:
7034 case OMPD_unknown:
7035 break;
Samuel Antaob68e2db2016-03-03 16:20:23 +00007036 }
Alexey Bataev5c427362019-04-10 19:11:33 +00007037 llvm_unreachable("Unsupported directive kind.");
Samuel Antaob68e2db2016-03-03 16:20:23 +00007038}
7039
Samuel Antao86ace552016-04-27 22:40:57 +00007040namespace {
Alexey Bataevb3638132018-07-19 16:34:13 +00007041LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
7042
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007043// Utility to handle information from clauses associated with a given
Samuel Antao86ace552016-04-27 22:40:57 +00007044// construct that use mappable expressions (e.g. 'map' clause, 'to' clause).
7045// It provides a convenient interface to obtain the information and generate
7046// code for that information.
7047class MappableExprsHandler {
7048public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007049 /// Values for bit flags used to specify the mapping type for
Samuel Antao86ace552016-04-27 22:40:57 +00007050 /// offloading.
Alexey Bataevb3638132018-07-19 16:34:13 +00007051 enum OpenMPOffloadMappingFlags : uint64_t {
7052 /// No flags
7053 OMP_MAP_NONE = 0x0,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007054 /// Allocate memory on the device and move data from host to device.
Samuel Antao86ace552016-04-27 22:40:57 +00007055 OMP_MAP_TO = 0x01,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007056 /// Allocate memory on the device and move data from device to host.
Samuel Antao86ace552016-04-27 22:40:57 +00007057 OMP_MAP_FROM = 0x02,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007058 /// Always perform the requested mapping action on the element, even
Samuel Antao86ace552016-04-27 22:40:57 +00007059 /// if it was already mapped before.
7060 OMP_MAP_ALWAYS = 0x04,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007061 /// Delete the element from the device environment, ignoring the
Samuel Antao86ace552016-04-27 22:40:57 +00007062 /// current reference count associated with the element.
Samuel Antao6782e942016-05-26 16:48:10 +00007063 OMP_MAP_DELETE = 0x08,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007064 /// The element being mapped is a pointer-pointee pair; both the
George Rokos065755d2017-11-07 18:27:04 +00007065 /// pointer and the pointee should be mapped.
7066 OMP_MAP_PTR_AND_OBJ = 0x10,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007067 /// This flags signals that the base address of an entry should be
George Rokos065755d2017-11-07 18:27:04 +00007068 /// passed to the target kernel as an argument.
7069 OMP_MAP_TARGET_PARAM = 0x20,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007070 /// Signal that the runtime library has to return the device pointer
George Rokos065755d2017-11-07 18:27:04 +00007071 /// in the current position for the data being mapped. Used when we have the
7072 /// use_device_ptr clause.
7073 OMP_MAP_RETURN_PARAM = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007074 /// This flag signals that the reference being passed is a pointer to
Samuel Antaod486f842016-05-26 16:53:38 +00007075 /// private data.
George Rokos065755d2017-11-07 18:27:04 +00007076 OMP_MAP_PRIVATE = 0x80,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007077 /// Pass the element to the device by value.
George Rokos065755d2017-11-07 18:27:04 +00007078 OMP_MAP_LITERAL = 0x100,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007079 /// Implicit map
7080 OMP_MAP_IMPLICIT = 0x200,
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007081 /// Close is a hint to the runtime to allocate memory close to
7082 /// the target device.
7083 OMP_MAP_CLOSE = 0x400,
Alexey Bataevb3638132018-07-19 16:34:13 +00007084 /// The 16 MSBs of the flags indicate whether the entry is member of some
7085 /// struct/class.
7086 OMP_MAP_MEMBER_OF = 0xffff000000000000,
7087 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF),
Samuel Antao86ace552016-04-27 22:40:57 +00007088 };
7089
Michael Krused47b9432019-08-05 18:43:21 +00007090 /// Get the offset of the OMP_MAP_MEMBER_OF field.
7091 static unsigned getFlagMemberOffset() {
7092 unsigned Offset = 0;
7093 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1);
7094 Remain = Remain >> 1)
7095 Offset++;
7096 return Offset;
7097 }
7098
Samuel Antaocc10b852016-07-28 14:23:26 +00007099 /// Class that associates information with a base pointer to be passed to the
7100 /// runtime library.
7101 class BasePointerInfo {
7102 /// The base pointer.
7103 llvm::Value *Ptr = nullptr;
7104 /// The base declaration that refers to this device pointer, or null if
7105 /// there is none.
7106 const ValueDecl *DevPtrDecl = nullptr;
7107
7108 public:
7109 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr)
7110 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {}
7111 llvm::Value *operator*() const { return Ptr; }
7112 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; }
7113 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; }
7114 };
7115
Alexey Bataevb3638132018-07-19 16:34:13 +00007116 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>;
7117 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>;
7118 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>;
7119
7120 /// Map between a struct and the its lowest & highest elements which have been
7121 /// mapped.
7122 /// [ValueDecl *] --> {LE(FieldIndex, Pointer),
7123 /// HE(FieldIndex, Pointer)}
7124 struct StructRangeInfoTy {
7125 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = {
7126 0, Address::invalid()};
7127 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = {
7128 0, Address::invalid()};
7129 Address Base = Address::invalid();
7130 };
Samuel Antao86ace552016-04-27 22:40:57 +00007131
7132private:
Alexey Bataevb3638132018-07-19 16:34:13 +00007133 /// Kind that defines how a device pointer has to be returned.
7134 struct MapInfo {
7135 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
7136 OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
Kelvin Lief579432018-12-18 22:18:41 +00007137 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataevb3638132018-07-19 16:34:13 +00007138 bool ReturnDevicePointer = false;
7139 bool IsImplicit = false;
7140
7141 MapInfo() = default;
7142 MapInfo(
7143 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Kelvin Lief579432018-12-18 22:18:41 +00007144 OpenMPMapClauseKind MapType,
7145 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007146 bool ReturnDevicePointer, bool IsImplicit)
Kelvin Lief579432018-12-18 22:18:41 +00007147 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
Alexey Bataevb3638132018-07-19 16:34:13 +00007148 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {}
7149 };
7150
7151 /// If use_device_ptr is used on a pointer which is a struct member and there
7152 /// is no map information about it, then emission of that entry is deferred
7153 /// until the whole struct has been processed.
7154 struct DeferredDevicePtrEntryTy {
7155 const Expr *IE = nullptr;
7156 const ValueDecl *VD = nullptr;
7157
7158 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD)
7159 : IE(IE), VD(VD) {}
7160 };
7161
Michael Krused47b9432019-08-05 18:43:21 +00007162 /// The target directive from where the mappable clauses were extracted. It
7163 /// is either a executable directive or a user-defined mapper directive.
7164 llvm::PointerUnion<const OMPExecutableDirective *,
7165 const OMPDeclareMapperDecl *>
7166 CurDir;
Samuel Antao86ace552016-04-27 22:40:57 +00007167
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007168 /// Function the directive is being generated for.
Samuel Antao86ace552016-04-27 22:40:57 +00007169 CodeGenFunction &CGF;
7170
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007171 /// Set of all first private variables in the current directive.
Alexey Bataevf288cf92019-06-27 18:53:07 +00007172 /// bool data is set to true if the variable is implicitly marked as
7173 /// firstprivate, false otherwise.
7174 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls;
Samuel Antaod486f842016-05-26 16:53:38 +00007175
Samuel Antao6890b092016-07-28 14:25:09 +00007176 /// Map between device pointer declarations and their expression components.
7177 /// The key value for declarations in 'this' is null.
7178 llvm::DenseMap<
7179 const ValueDecl *,
7180 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7181 DevPointersMap;
7182
Samuel Antao86ace552016-04-27 22:40:57 +00007183 llvm::Value *getExprTypeSize(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007184 QualType ExprTy = E->getType().getCanonicalType();
Samuel Antao86ace552016-04-27 22:40:57 +00007185
7186 // Reference types are ignored for mapping purposes.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007187 if (const auto *RefTy = ExprTy->getAs<ReferenceType>())
Samuel Antao86ace552016-04-27 22:40:57 +00007188 ExprTy = RefTy->getPointeeType().getCanonicalType();
7189
7190 // Given that an array section is considered a built-in type, we need to
7191 // do the calculation based on the length of the section instead of relying
7192 // on CGF.getTypeSize(E->getType()).
7193 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) {
7194 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType(
7195 OAE->getBase()->IgnoreParenImpCasts())
7196 .getCanonicalType();
7197
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007198 // If there is no length associated with the expression and lower bound is
7199 // not specified too, that means we are using the whole length of the
7200 // base.
7201 if (!OAE->getLength() && OAE->getColonLoc().isValid() &&
7202 !OAE->getLowerBound())
Samuel Antao86ace552016-04-27 22:40:57 +00007203 return CGF.getTypeSize(BaseTy);
7204
7205 llvm::Value *ElemSize;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007206 if (const auto *PTy = BaseTy->getAs<PointerType>()) {
Samuel Antao86ace552016-04-27 22:40:57 +00007207 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007208 } else {
7209 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr());
Samuel Antao86ace552016-04-27 22:40:57 +00007210 assert(ATy && "Expecting array type if not a pointer type.");
7211 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType());
7212 }
7213
7214 // If we don't have a length at this point, that is because we have an
7215 // array section with a single element.
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007216 if (!OAE->getLength() && OAE->getColonLoc().isInvalid())
Samuel Antao86ace552016-04-27 22:40:57 +00007217 return ElemSize;
7218
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007219 if (const Expr *LenExpr = OAE->getLength()) {
Michael Liaod838cf72019-10-02 00:22:45 +00007220 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr);
7221 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(),
7222 CGF.getContext().getSizeType(),
7223 LenExpr->getExprLoc());
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007224 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize);
7225 }
7226 assert(!OAE->getLength() && OAE->getColonLoc().isValid() &&
7227 OAE->getLowerBound() && "expected array_section[lb:].");
7228 // Size = sizetype - lb * elemtype;
7229 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy);
7230 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound());
7231 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(),
7232 CGF.getContext().getSizeType(),
7233 OAE->getLowerBound()->getExprLoc());
7234 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize);
7235 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal);
7236 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal);
7237 LengthVal = CGF.Builder.CreateSelect(
7238 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0));
7239 return LengthVal;
Samuel Antao86ace552016-04-27 22:40:57 +00007240 }
7241 return CGF.getTypeSize(ExprTy);
7242 }
7243
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007244 /// Return the corresponding bits for a given map clause modifier. Add
Samuel Antao86ace552016-04-27 22:40:57 +00007245 /// a flag marking the map as a pointer if requested. Add a flag marking the
Samuel Antao6782e942016-05-26 16:48:10 +00007246 /// map as the first one of a series of maps that relate to the same map
7247 /// expression.
Kelvin Lief579432018-12-18 22:18:41 +00007248 OpenMPOffloadMappingFlags getMapTypeBits(
7249 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
7250 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const {
Alexey Bataevb3638132018-07-19 16:34:13 +00007251 OpenMPOffloadMappingFlags Bits =
7252 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE;
Samuel Antao86ace552016-04-27 22:40:57 +00007253 switch (MapType) {
7254 case OMPC_MAP_alloc:
Samuel Antao6782e942016-05-26 16:48:10 +00007255 case OMPC_MAP_release:
7256 // alloc and release is the default behavior in the runtime library, i.e.
7257 // if we don't pass any bits alloc/release that is what the runtime is
7258 // going to do. Therefore, we don't need to signal anything for these two
7259 // type modifiers.
Samuel Antao86ace552016-04-27 22:40:57 +00007260 break;
7261 case OMPC_MAP_to:
Alexey Bataevb3638132018-07-19 16:34:13 +00007262 Bits |= OMP_MAP_TO;
Samuel Antao86ace552016-04-27 22:40:57 +00007263 break;
7264 case OMPC_MAP_from:
Alexey Bataevb3638132018-07-19 16:34:13 +00007265 Bits |= OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007266 break;
7267 case OMPC_MAP_tofrom:
Alexey Bataevb3638132018-07-19 16:34:13 +00007268 Bits |= OMP_MAP_TO | OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007269 break;
7270 case OMPC_MAP_delete:
Alexey Bataevb3638132018-07-19 16:34:13 +00007271 Bits |= OMP_MAP_DELETE;
Samuel Antao86ace552016-04-27 22:40:57 +00007272 break;
Alexey Bataevb3638132018-07-19 16:34:13 +00007273 case OMPC_MAP_unknown:
Samuel Antao86ace552016-04-27 22:40:57 +00007274 llvm_unreachable("Unexpected map type!");
Samuel Antao86ace552016-04-27 22:40:57 +00007275 }
7276 if (AddPtrFlag)
George Rokos065755d2017-11-07 18:27:04 +00007277 Bits |= OMP_MAP_PTR_AND_OBJ;
7278 if (AddIsTargetParamFlag)
7279 Bits |= OMP_MAP_TARGET_PARAM;
Kelvin Lief579432018-12-18 22:18:41 +00007280 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always)
7281 != MapModifiers.end())
Samuel Antao86ace552016-04-27 22:40:57 +00007282 Bits |= OMP_MAP_ALWAYS;
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007283 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close)
7284 != MapModifiers.end())
7285 Bits |= OMP_MAP_CLOSE;
Samuel Antao86ace552016-04-27 22:40:57 +00007286 return Bits;
7287 }
7288
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007289 /// Return true if the provided expression is a final array section. A
Samuel Antao86ace552016-04-27 22:40:57 +00007290 /// final array section, is one whose length can't be proved to be one.
7291 bool isFinalArraySectionExpression(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007292 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
Samuel Antao86ace552016-04-27 22:40:57 +00007293
7294 // It is not an array section and therefore not a unity-size one.
7295 if (!OASE)
7296 return false;
7297
7298 // An array section with no colon always refer to a single element.
7299 if (OASE->getColonLoc().isInvalid())
7300 return false;
7301
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007302 const Expr *Length = OASE->getLength();
Samuel Antao86ace552016-04-27 22:40:57 +00007303
7304 // If we don't have a length we have to check if the array has size 1
7305 // for this dimension. Also, we should always expect a length if the
7306 // base type is pointer.
7307 if (!Length) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007308 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType(
7309 OASE->getBase()->IgnoreParenImpCasts())
7310 .getCanonicalType();
7311 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
Samuel Antao86ace552016-04-27 22:40:57 +00007312 return ATy->getSize().getSExtValue() != 1;
7313 // If we don't have a constant dimension length, we have to consider
7314 // the current section as having any size, so it is not necessarily
7315 // unitary. If it happen to be unity size, that's user fault.
7316 return true;
7317 }
7318
7319 // Check if the length evaluates to 1.
Fangrui Song407659a2018-11-30 23:41:18 +00007320 Expr::EvalResult Result;
7321 if (!Length->EvaluateAsInt(Result, CGF.getContext()))
Samuel Antao86ace552016-04-27 22:40:57 +00007322 return true; // Can have more that size 1.
7323
Fangrui Song407659a2018-11-30 23:41:18 +00007324 llvm::APSInt ConstLength = Result.Val.getInt();
Samuel Antao86ace552016-04-27 22:40:57 +00007325 return ConstLength.getSExtValue() != 1;
7326 }
7327
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007328 /// Generate the base pointers, section pointers, sizes and map type
Samuel Antao86ace552016-04-27 22:40:57 +00007329 /// bits for the provided map type, map modifier, and expression components.
7330 /// \a IsFirstComponent should be set to true if the provided set of
7331 /// components is the first associated with a capture.
7332 void generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00007333 OpenMPMapClauseKind MapType,
7334 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Samuel Antao86ace552016-04-27 22:40:57 +00007335 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Samuel Antaocc10b852016-07-28 14:23:26 +00007336 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007337 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
Alexey Bataevb3638132018-07-19 16:34:13 +00007338 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007339 bool IsImplicit,
7340 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7341 OverlappedElements = llvm::None) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007342 // The following summarizes what has to be generated for each map and the
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00007343 // types below. The generated information is expressed in this order:
Samuel Antao86ace552016-04-27 22:40:57 +00007344 // base pointer, section pointer, size, flags
7345 // (to add to the ones that come from the map type and modifier).
7346 //
7347 // double d;
7348 // int i[100];
7349 // float *p;
7350 //
7351 // struct S1 {
7352 // int i;
7353 // float f[50];
7354 // }
7355 // struct S2 {
7356 // int i;
7357 // float f[50];
7358 // S1 s;
7359 // double *p;
7360 // struct S2 *ps;
7361 // }
7362 // S2 s;
7363 // S2 *ps;
7364 //
7365 // map(d)
Alexey Bataevb3638132018-07-19 16:34:13 +00007366 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007367 //
7368 // map(i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007369 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007370 //
7371 // map(i[1:23])
Alexey Bataevb3638132018-07-19 16:34:13 +00007372 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007373 //
7374 // map(p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007375 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007376 //
7377 // map(p[1:24])
Alexey Bataevb3638132018-07-19 16:34:13 +00007378 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007379 //
7380 // map(s)
Alexey Bataevb3638132018-07-19 16:34:13 +00007381 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007382 //
7383 // map(s.i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007384 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007385 //
7386 // map(s.s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007387 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007388 //
7389 // map(s.p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007390 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007391 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007392 // map(to: s.p[:22])
7393 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*)
7394 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**)
7395 // &(s.p), &(s.p[0]), 22*sizeof(double),
7396 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***)
7397 // (*) alloc space for struct members, only this is a target parameter
7398 // (**) map the pointer (nothing to be mapped in this example) (the compiler
7399 // optimizes this entry out, same in the examples below)
7400 // (***) map the pointee (map: to)
Samuel Antao86ace552016-04-27 22:40:57 +00007401 //
7402 // map(s.ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007403 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007404 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007405 // map(from: s.ps->s.i)
7406 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7407 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7408 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007409 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007410 // map(to: s.ps->ps)
7411 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7412 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7413 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007414 //
7415 // map(s.ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007416 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7417 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7418 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7419 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007420 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007421 // map(to: s.ps->ps->s.f[:22])
7422 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7423 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7424 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7425 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007426 //
7427 // map(ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007428 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007429 //
7430 // map(ps->i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007431 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007432 //
7433 // map(ps->s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007434 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007435 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007436 // map(from: ps->p)
7437 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007438 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007439 // map(to: ps->p[:22])
7440 // ps, &(ps->p), sizeof(double*), TARGET_PARAM
7441 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1)
7442 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007443 //
7444 // map(ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007445 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007446 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007447 // map(from: ps->ps->s.i)
7448 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7449 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7450 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007451 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007452 // map(from: ps->ps->ps)
7453 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7454 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7455 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007456 //
7457 // map(ps->ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007458 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7459 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7460 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7461 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007462 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007463 // map(to: ps->ps->ps->s.f[:22])
7464 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7465 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7466 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7467 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
7468 //
7469 // map(to: s.f[:22]) map(from: s.p[:33])
7470 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) +
7471 // sizeof(double*) (**), TARGET_PARAM
7472 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO
7473 // &s, &(s.p), sizeof(double*), MEMBER_OF(1)
7474 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7475 // (*) allocate contiguous space needed to fit all mapped members even if
7476 // we allocate space for members not mapped (in this example,
7477 // s.f[22..49] and s.s are not mapped, yet we must allocate space for
7478 // them as well because they fall between &s.f[0] and &s.p)
7479 //
7480 // map(from: s.f[:22]) map(to: ps->p[:33])
7481 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM
7482 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7483 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*)
7484 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO
7485 // (*) the struct this entry pertains to is the 2nd element in the list of
7486 // arguments, hence MEMBER_OF(2)
7487 //
7488 // map(from: s.f[:22], s.s) map(to: ps->p[:33])
7489 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM
7490 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM
7491 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM
7492 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7493 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*)
7494 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO
7495 // (*) the struct this entry pertains to is the 4th element in the list
7496 // of arguments, hence MEMBER_OF(4)
Samuel Antao86ace552016-04-27 22:40:57 +00007497
7498 // Track if the map information being generated is the first for a capture.
7499 bool IsCaptureFirstInfo = IsFirstComponentList;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007500 // When the variable is on a declare target link or in a to clause with
7501 // unified memory, a reference is needed to hold the host/device address
7502 // of the variable.
7503 bool RequiresReference = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007504
7505 // Scan the components from the base to the complete expression.
7506 auto CI = Components.rbegin();
7507 auto CE = Components.rend();
7508 auto I = CI;
7509
7510 // Track if the map information being generated is the first for a list of
7511 // components.
7512 bool IsExpressionFirstInfo = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00007513 Address BP = Address::invalid();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007514 const Expr *AssocExpr = I->getAssociatedExpression();
7515 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7516 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
Samuel Antao86ace552016-04-27 22:40:57 +00007517
Patrick Lystere13b1e32019-01-02 19:28:48 +00007518 if (isa<MemberExpr>(AssocExpr)) {
Samuel Antao86ace552016-04-27 22:40:57 +00007519 // The base is the 'this' pointer. The content of the pointer is going
7520 // to be the base of the field being mapped.
Alexey Bataevb3638132018-07-19 16:34:13 +00007521 BP = CGF.LoadCXXThisAddress();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007522 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7523 (OASE &&
7524 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08007525 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF);
Samuel Antao86ace552016-04-27 22:40:57 +00007526 } else {
7527 // The base is the reference to the variable.
7528 // BP = &Var.
Akira Hatanakaf139ae32019-12-03 15:17:01 -08007529 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF);
Alexey Bataev92327c52018-03-26 16:40:55 +00007530 if (const auto *VD =
7531 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7532 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007533 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7534 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7535 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
7536 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) {
7537 RequiresReference = true;
7538 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataev2c1dffe2018-04-16 20:34:41 +00007539 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007540 }
Alexey Bataev92327c52018-03-26 16:40:55 +00007541 }
Samuel Antao86ace552016-04-27 22:40:57 +00007542
7543 // If the variable is a pointer and is being dereferenced (i.e. is not
Nico Webera6916892016-06-10 18:53:04 +00007544 // the last component), the base has to be the pointer itself, not its
Samuel Antao403ffd42016-07-27 22:49:49 +00007545 // reference. References are ignored for mapping purposes.
7546 QualType Ty =
7547 I->getAssociatedDeclaration()->getType().getNonReferenceType();
7548 if (Ty->isAnyPointerType() && std::next(I) != CE) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007549 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
Samuel Antao86ace552016-04-27 22:40:57 +00007550
7551 // We do not need to generate individual map information for the
7552 // pointer, it can be associated with the combined storage.
7553 ++I;
7554 }
7555 }
7556
Alexey Bataevb3638132018-07-19 16:34:13 +00007557 // Track whether a component of the list should be marked as MEMBER_OF some
7558 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry
7559 // in a component list should be marked as MEMBER_OF, all subsequent entries
7560 // do not belong to the base struct. E.g.
7561 // struct S2 s;
7562 // s.ps->ps->ps->f[:]
7563 // (1) (2) (3) (4)
7564 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a
7565 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3)
7566 // is the pointee of ps(2) which is not member of struct s, so it should not
7567 // be marked as such (it is still PTR_AND_OBJ).
7568 // The variable is initialized to false so that PTR_AND_OBJ entries which
7569 // are not struct members are not considered (e.g. array of pointers to
7570 // data).
7571 bool ShouldBeMemberOf = false;
7572
7573 // Variable keeping track of whether or not we have encountered a component
7574 // in the component list which is a member expression. Useful when we have a
7575 // pointer or a final array section, in which case it is the previous
7576 // component in the list which tells us whether we have a member expression.
7577 // E.g. X.f[:]
7578 // While processing the final array section "[:]" it is "f" which tells us
7579 // whether we are dealing with a member of a declared struct.
7580 const MemberExpr *EncounteredME = nullptr;
7581
Samuel Antao86ace552016-04-27 22:40:57 +00007582 for (; I != CE; ++I) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007583 // If the current component is member of a struct (parent struct) mark it.
7584 if (!EncounteredME) {
7585 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7586 // If we encounter a PTR_AND_OBJ entry from now on it should be marked
7587 // as MEMBER_OF the parent struct.
7588 if (EncounteredME)
7589 ShouldBeMemberOf = true;
7590 }
7591
Samuel Antao86ace552016-04-27 22:40:57 +00007592 auto Next = std::next(I);
7593
7594 // We need to generate the addresses and sizes if this is the last
7595 // component, if the component is a pointer or if it is an array section
7596 // whose length can't be proved to be one. If this is a pointer, it
7597 // becomes the base address for the following components.
7598
7599 // A final array section, is one whose length can't be proved to be one.
7600 bool IsFinalArraySection =
7601 isFinalArraySectionExpression(I->getAssociatedExpression());
7602
7603 // Get information on whether the element is a pointer. Have to do a
7604 // special treatment for array sections given that they are built-in
7605 // types.
7606 const auto *OASE =
7607 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression());
7608 bool IsPointer =
Alexey Bataevb3638132018-07-19 16:34:13 +00007609 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE)
7610 .getCanonicalType()
7611 ->isAnyPointerType()) ||
Samuel Antao86ace552016-04-27 22:40:57 +00007612 I->getAssociatedExpression()->getType()->isAnyPointerType();
7613
7614 if (Next == CE || IsPointer || IsFinalArraySection) {
Samuel Antao86ace552016-04-27 22:40:57 +00007615 // If this is not the last component, we expect the pointer to be
7616 // associated with an array expression or member expression.
7617 assert((Next == CE ||
7618 isa<MemberExpr>(Next->getAssociatedExpression()) ||
7619 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||
7620 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) &&
7621 "Unexpected expression");
7622
Akira Hatanakaf139ae32019-12-03 15:17:01 -08007623 Address LB = CGF.EmitOMPSharedLValue(I->getAssociatedExpression())
7624 .getAddress(CGF);
Samuel Antao86ace552016-04-27 22:40:57 +00007625
Alexey Bataevb3638132018-07-19 16:34:13 +00007626 // If this component is a pointer inside the base struct then we don't
7627 // need to create any entry for it - it will be combined with the object
7628 // it is pointing to into a single PTR_AND_OBJ entry.
7629 bool IsMemberPointer =
7630 IsPointer && EncounteredME &&
7631 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) ==
7632 EncounteredME);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007633 if (!OverlappedElements.empty()) {
7634 // Handle base element with the info for overlapped elements.
7635 assert(!PartialStruct.Base.isValid() && "The base element is set.");
7636 assert(Next == CE &&
7637 "Expected last element for the overlapped elements.");
7638 assert(!IsPointer &&
7639 "Unexpected base element with the pointer type.");
7640 // Mark the whole struct as the struct that requires allocation on the
7641 // device.
7642 PartialStruct.LowestElem = {0, LB};
7643 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(
7644 I->getAssociatedExpression()->getType());
7645 Address HB = CGF.Builder.CreateConstGEP(
7646 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB,
7647 CGF.VoidPtrTy),
James Y Knight751fe282019-02-09 22:22:28 +00007648 TypeSize.getQuantity() - 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007649 PartialStruct.HighestElem = {
7650 std::numeric_limits<decltype(
7651 PartialStruct.HighestElem.first)>::max(),
7652 HB};
7653 PartialStruct.Base = BP;
7654 // Emit data for non-overlapped data.
7655 OpenMPOffloadMappingFlags Flags =
7656 OMP_MAP_MEMBER_OF |
Kelvin Lief579432018-12-18 22:18:41 +00007657 getMapTypeBits(MapType, MapModifiers, IsImplicit,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007658 /*AddPtrFlag=*/false,
7659 /*AddIsTargetParamFlag=*/false);
7660 LB = BP;
7661 llvm::Value *Size = nullptr;
7662 // Do bitcopy of all non-overlapped structure elements.
7663 for (OMPClauseMappableExprCommon::MappableExprComponentListRef
7664 Component : OverlappedElements) {
7665 Address ComponentLB = Address::invalid();
7666 for (const OMPClauseMappableExprCommon::MappableComponent &MC :
7667 Component) {
7668 if (MC.getAssociatedDeclaration()) {
7669 ComponentLB =
7670 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
Akira Hatanakaf139ae32019-12-03 15:17:01 -08007671 .getAddress(CGF);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007672 Size = CGF.Builder.CreatePtrDiff(
7673 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()),
7674 CGF.EmitCastToVoidPtr(LB.getPointer()));
7675 break;
7676 }
7677 }
7678 BasePointers.push_back(BP.getPointer());
7679 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007680 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty,
7681 /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007682 Types.push_back(Flags);
James Y Knight751fe282019-02-09 22:22:28 +00007683 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007684 }
7685 BasePointers.push_back(BP.getPointer());
7686 Pointers.push_back(LB.getPointer());
7687 Size = CGF.Builder.CreatePtrDiff(
7688 CGF.EmitCastToVoidPtr(
James Y Knight751fe282019-02-09 22:22:28 +00007689 CGF.Builder.CreateConstGEP(HB, 1).getPointer()),
Alexey Bataeve82445f2018-09-20 13:54:02 +00007690 CGF.EmitCastToVoidPtr(LB.getPointer()));
Alexey Bataeva90fc662019-06-25 16:00:43 +00007691 Sizes.push_back(
7692 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007693 Types.push_back(Flags);
7694 break;
7695 }
7696 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
Alexey Bataevb3638132018-07-19 16:34:13 +00007697 if (!IsMemberPointer) {
7698 BasePointers.push_back(BP.getPointer());
7699 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007700 Sizes.push_back(
7701 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Samuel Antao03a3cec2016-07-27 22:52:16 +00007702
Alexey Bataevb3638132018-07-19 16:34:13 +00007703 // We need to add a pointer flag for each map that comes from the
7704 // same expression except for the first one. We also need to signal
7705 // this map is the first one that relates with the current capture
7706 // (there is a set of entries for each capture).
7707 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
Kelvin Lief579432018-12-18 22:18:41 +00007708 MapType, MapModifiers, IsImplicit,
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007709 !IsExpressionFirstInfo || RequiresReference,
7710 IsCaptureFirstInfo && !RequiresReference);
Alexey Bataevb3638132018-07-19 16:34:13 +00007711
7712 if (!IsExpressionFirstInfo) {
7713 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007714 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags.
Alexey Bataevb3638132018-07-19 16:34:13 +00007715 if (IsPointer)
7716 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS |
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007717 OMP_MAP_DELETE | OMP_MAP_CLOSE);
Alexey Bataevb3638132018-07-19 16:34:13 +00007718
7719 if (ShouldBeMemberOf) {
7720 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag
7721 // should be later updated with the correct value of MEMBER_OF.
7722 Flags |= OMP_MAP_MEMBER_OF;
7723 // From now on, all subsequent PTR_AND_OBJ entries should not be
7724 // marked as MEMBER_OF.
7725 ShouldBeMemberOf = false;
7726 }
7727 }
7728
7729 Types.push_back(Flags);
Samuel Antao03a3cec2016-07-27 22:52:16 +00007730 }
7731
Alexey Bataevb3638132018-07-19 16:34:13 +00007732 // If we have encountered a member expression so far, keep track of the
7733 // mapped member. If the parent is "*this", then the value declaration
7734 // is nullptr.
7735 if (EncounteredME) {
7736 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl());
7737 unsigned FieldIndex = FD->getFieldIndex();
Samuel Antao03a3cec2016-07-27 22:52:16 +00007738
Alexey Bataevb3638132018-07-19 16:34:13 +00007739 // Update info about the lowest and highest elements for this struct
7740 if (!PartialStruct.Base.isValid()) {
7741 PartialStruct.LowestElem = {FieldIndex, LB};
7742 PartialStruct.HighestElem = {FieldIndex, LB};
7743 PartialStruct.Base = BP;
7744 } else if (FieldIndex < PartialStruct.LowestElem.first) {
7745 PartialStruct.LowestElem = {FieldIndex, LB};
7746 } else if (FieldIndex > PartialStruct.HighestElem.first) {
7747 PartialStruct.HighestElem = {FieldIndex, LB};
7748 }
7749 }
Samuel Antao86ace552016-04-27 22:40:57 +00007750
7751 // If we have a final array section, we are done with this expression.
7752 if (IsFinalArraySection)
7753 break;
7754
7755 // The pointer becomes the base for the next element.
7756 if (Next != CE)
7757 BP = LB;
7758
7759 IsExpressionFirstInfo = false;
7760 IsCaptureFirstInfo = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007761 }
7762 }
7763 }
7764
Alexey Bataevb3638132018-07-19 16:34:13 +00007765 /// Return the adjusted map modifiers if the declaration a capture refers to
7766 /// appears in a first-private clause. This is expected to be used only with
7767 /// directives that start with 'target'.
7768 MappableExprsHandler::OpenMPOffloadMappingFlags
7769 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const {
7770 assert(Cap.capturesVariable() && "Expected capture by reference only!");
7771
7772 // A first private variable captured by reference will use only the
7773 // 'private ptr' and 'map to' flag. Return the right flags if the captured
7774 // declaration is known as first-private in this handler.
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007775 if (FirstPrivateDecls.count(Cap.getCapturedVar())) {
7776 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) &&
7777 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef)
7778 return MappableExprsHandler::OMP_MAP_ALWAYS |
7779 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataevc2b831f2019-04-02 16:03:40 +00007780 if (Cap.getCapturedVar()->getType()->isAnyPointerType())
7781 return MappableExprsHandler::OMP_MAP_TO |
7782 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ;
Alexey Bataevb3638132018-07-19 16:34:13 +00007783 return MappableExprsHandler::OMP_MAP_PRIVATE |
7784 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007785 }
Alexey Bataevb3638132018-07-19 16:34:13 +00007786 return MappableExprsHandler::OMP_MAP_TO |
7787 MappableExprsHandler::OMP_MAP_FROM;
7788 }
7789
7790 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) {
Michael Krused47b9432019-08-05 18:43:21 +00007791 // Rotate by getFlagMemberOffset() bits.
Alexey Bataevb3638132018-07-19 16:34:13 +00007792 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1)
Michael Krused47b9432019-08-05 18:43:21 +00007793 << getFlagMemberOffset());
Alexey Bataevb3638132018-07-19 16:34:13 +00007794 }
7795
7796 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags,
7797 OpenMPOffloadMappingFlags MemberOfFlag) {
7798 // If the entry is PTR_AND_OBJ but has not been marked with the special
7799 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be
7800 // marked as MEMBER_OF.
7801 if ((Flags & OMP_MAP_PTR_AND_OBJ) &&
7802 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF))
7803 return;
7804
7805 // Reset the placeholder value to prepare the flag for the assignment of the
7806 // proper MEMBER_OF value.
7807 Flags &= ~OMP_MAP_MEMBER_OF;
7808 Flags |= MemberOfFlag;
7809 }
7810
Alexey Bataeve82445f2018-09-20 13:54:02 +00007811 void getPlainLayout(const CXXRecordDecl *RD,
7812 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
7813 bool AsBase) const {
7814 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD);
7815
7816 llvm::StructType *St =
7817 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType();
7818
7819 unsigned NumElements = St->getNumElements();
7820 llvm::SmallVector<
7821 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
7822 RecordLayout(NumElements);
7823
7824 // Fill bases.
7825 for (const auto &I : RD->bases()) {
7826 if (I.isVirtual())
7827 continue;
7828 const auto *Base = I.getType()->getAsCXXRecordDecl();
7829 // Ignore empty bases.
7830 if (Base->isEmpty() || CGF.getContext()
7831 .getASTRecordLayout(Base)
7832 .getNonVirtualSize()
7833 .isZero())
7834 continue;
7835
7836 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
7837 RecordLayout[FieldIndex] = Base;
7838 }
7839 // Fill in virtual bases.
7840 for (const auto &I : RD->vbases()) {
7841 const auto *Base = I.getType()->getAsCXXRecordDecl();
7842 // Ignore empty bases.
7843 if (Base->isEmpty())
7844 continue;
7845 unsigned FieldIndex = RL.getVirtualBaseIndex(Base);
7846 if (RecordLayout[FieldIndex])
7847 continue;
7848 RecordLayout[FieldIndex] = Base;
7849 }
7850 // Fill in all the fields.
7851 assert(!RD->isUnion() && "Unexpected union.");
7852 for (const auto *Field : RD->fields()) {
7853 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
7854 // will fill in later.)
Richard Smith78b239e2019-06-20 20:44:45 +00007855 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) {
Alexey Bataeve82445f2018-09-20 13:54:02 +00007856 unsigned FieldIndex = RL.getLLVMFieldNo(Field);
7857 RecordLayout[FieldIndex] = Field;
7858 }
7859 }
7860 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
7861 &Data : RecordLayout) {
7862 if (Data.isNull())
7863 continue;
7864 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>())
7865 getPlainLayout(Base, Layout, /*AsBase=*/true);
7866 else
7867 Layout.push_back(Data.get<const FieldDecl *>());
7868 }
7869 }
7870
Alexey Bataevb3638132018-07-19 16:34:13 +00007871public:
7872 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
Michael Krused47b9432019-08-05 18:43:21 +00007873 : CurDir(&Dir), CGF(CGF) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007874 // Extract firstprivate clause information.
7875 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>())
7876 for (const auto *D : C->varlists())
Alexey Bataevf288cf92019-06-27 18:53:07 +00007877 FirstPrivateDecls.try_emplace(
7878 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit());
Alexey Bataevb3638132018-07-19 16:34:13 +00007879 // Extract device pointer clause information.
7880 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
7881 for (auto L : C->component_lists())
7882 DevPointersMap[L.first].push_back(L.second);
7883 }
7884
Michael Krused47b9432019-08-05 18:43:21 +00007885 /// Constructor for the declare mapper directive.
7886 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF)
7887 : CurDir(&Dir), CGF(CGF) {}
7888
Alexey Bataevb3638132018-07-19 16:34:13 +00007889 /// Generate code for the combined entry if we have a partially mapped struct
7890 /// and take care of the mapping flags of the arguments corresponding to
7891 /// individual struct members.
7892 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers,
7893 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7894 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes,
7895 const StructRangeInfoTy &PartialStruct) const {
7896 // Base is the base of the struct
7897 BasePointers.push_back(PartialStruct.Base.getPointer());
7898 // Pointer is the address of the lowest element
7899 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer();
7900 Pointers.push_back(LB);
7901 // Size is (addr of {highest+1} element) - (addr of lowest element)
7902 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer();
7903 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1);
7904 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy);
7905 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy);
7906 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00007907 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00007908 /*isSigned=*/false);
Alexey Bataevb3638132018-07-19 16:34:13 +00007909 Sizes.push_back(Size);
7910 // Map type is always TARGET_PARAM
7911 Types.push_back(OMP_MAP_TARGET_PARAM);
7912 // Remove TARGET_PARAM flag from the first element
7913 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM;
7914
7915 // All other current entries will be MEMBER_OF the combined entry
7916 // (except for PTR_AND_OBJ entries which do not have a placeholder value
7917 // 0xFFFF in the MEMBER_OF field).
7918 OpenMPOffloadMappingFlags MemberOfFlag =
7919 getMemberOfFlag(BasePointers.size() - 1);
7920 for (auto &M : CurTypes)
7921 setCorrectMemberOfFlag(M, MemberOfFlag);
7922 }
7923
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007924 /// Generate all the base pointers, section pointers, sizes and map
Samuel Antaocc10b852016-07-28 14:23:26 +00007925 /// types for the extracted mappable expressions. Also, for each item that
7926 /// relates with a device pointer, a pair of the relevant declaration and
7927 /// index where it occurs is appended to the device pointers info array.
7928 void generateAllInfo(MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007929 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7930 MapFlagsArrayTy &Types) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007931 // We have to process the component lists that relate with the same
7932 // declaration in a single chunk so that we can generate the map flags
7933 // correctly. Therefore, we organize all lists in a map.
Alexey Bataev5d1c3f62017-06-27 15:46:42 +00007934 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
Samuel Antao8d2d7302016-05-26 18:30:22 +00007935
7936 // Helper function to fill the information map for the different supported
7937 // clauses.
Samuel Antaocc10b852016-07-28 14:23:26 +00007938 auto &&InfoGen = [&Info](
7939 const ValueDecl *D,
7940 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
Kelvin Lief579432018-12-18 22:18:41 +00007941 OpenMPMapClauseKind MapType,
7942 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007943 bool ReturnDevicePointer, bool IsImplicit) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007944 const ValueDecl *VD =
7945 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
Kelvin Lief579432018-12-18 22:18:41 +00007946 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007947 IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00007948 };
Samuel Antao8d2d7302016-05-26 18:30:22 +00007949
Michael Krused47b9432019-08-05 18:43:21 +00007950 assert(CurDir.is<const OMPExecutableDirective *>() &&
7951 "Expect a executable directive");
7952 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
7953 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>())
Mark de Wever51abceb2019-11-12 20:48:11 +01007954 for (const auto L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007955 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(),
Alexey Bataevb3638132018-07-19 16:34:13 +00007956 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007957 }
Michael Krused47b9432019-08-05 18:43:21 +00007958 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>())
Mark de Wever51abceb2019-11-12 20:48:11 +01007959 for (const auto L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007960 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007961 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007962 }
Michael Krused47b9432019-08-05 18:43:21 +00007963 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>())
Mark de Wever51abceb2019-11-12 20:48:11 +01007964 for (const auto L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007965 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007966 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007967 }
Samuel Antao86ace552016-04-27 22:40:57 +00007968
Samuel Antaocc10b852016-07-28 14:23:26 +00007969 // Look at the use_device_ptr clause information and mark the existing map
7970 // entries as such. If there is no map information for an entry in the
7971 // use_device_ptr list, we create one with map type 'alloc' and zero size
Alexey Bataevb3638132018-07-19 16:34:13 +00007972 // section. It is the user fault if that was not mapped before. If there is
7973 // no map information and the pointer is a struct member, then we defer the
7974 // emission of that entry until the whole struct has been processed.
7975 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>>
7976 DeferredInfo;
7977
Alexey Bataevb3638132018-07-19 16:34:13 +00007978 for (const auto *C :
Michael Krused47b9432019-08-05 18:43:21 +00007979 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) {
Mark de Wever51abceb2019-11-12 20:48:11 +01007980 for (const auto L : C->component_lists()) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007981 assert(!L.second.empty() && "Not expecting empty list of components!");
7982 const ValueDecl *VD = L.second.back().getAssociatedDeclaration();
7983 VD = cast<ValueDecl>(VD->getCanonicalDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007984 const Expr *IE = L.second.back().getAssociatedExpression();
Samuel Antaocc10b852016-07-28 14:23:26 +00007985 // If the first component is a member expression, we have to look into
7986 // 'this', which maps to null in the map of map information. Otherwise
7987 // look directly for the information.
7988 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
7989
7990 // We potentially have map information for this declaration already.
7991 // Look for the first set of components that refer to it.
7992 if (It != Info.end()) {
7993 auto CI = std::find_if(
7994 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) {
7995 return MI.Components.back().getAssociatedDeclaration() == VD;
7996 });
7997 // If we found a map entry, signal that the pointer has to be returned
7998 // and move on to the next declaration.
7999 if (CI != It->second.end()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00008000 CI->ReturnDevicePointer = true;
Samuel Antaocc10b852016-07-28 14:23:26 +00008001 continue;
8002 }
8003 }
8004
8005 // We didn't find any match in our map information - generate a zero
Alexey Bataevb3638132018-07-19 16:34:13 +00008006 // size array section - if the pointer is a struct member we defer this
8007 // action until the whole struct has been processed.
Alexey Bataevb3638132018-07-19 16:34:13 +00008008 if (isa<MemberExpr>(IE)) {
8009 // Insert the pointer into Info to be processed by
8010 // generateInfoForComponentList. Because it is a member pointer
8011 // without a pointee, no entry will be generated for it, therefore
8012 // we need to generate one after the whole struct has been processed.
8013 // Nonetheless, generateInfoForComponentList must be called to take
8014 // the pointer into account for the calculation of the range of the
8015 // partial struct.
Kelvin Lief579432018-12-18 22:18:41 +00008016 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00008017 /*ReturnDevicePointer=*/false, C->isImplicit());
8018 DeferredInfo[nullptr].emplace_back(IE, VD);
8019 } else {
Michael Krused47b9432019-08-05 18:43:21 +00008020 llvm::Value *Ptr =
8021 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc());
Alexey Bataevb3638132018-07-19 16:34:13 +00008022 BasePointers.emplace_back(Ptr, VD);
8023 Pointers.push_back(Ptr);
Michael Krused47b9432019-08-05 18:43:21 +00008024 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00008025 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM);
8026 }
Samuel Antaocc10b852016-07-28 14:23:26 +00008027 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008028 }
Samuel Antaocc10b852016-07-28 14:23:26 +00008029
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008030 for (const auto &M : Info) {
Samuel Antao86ace552016-04-27 22:40:57 +00008031 // We need to know when we generate information for the first component
8032 // associated with a capture, because the mapping flags depend on it.
8033 bool IsFirstComponentList = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00008034
8035 // Temporary versions of arrays
8036 MapBaseValuesArrayTy CurBasePointers;
8037 MapValuesArrayTy CurPointers;
8038 MapValuesArrayTy CurSizes;
8039 MapFlagsArrayTy CurTypes;
8040 StructRangeInfoTy PartialStruct;
8041
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008042 for (const MapInfo &L : M.second) {
Samuel Antao86ace552016-04-27 22:40:57 +00008043 assert(!L.Components.empty() &&
8044 "Not expecting declaration with no component lists.");
Samuel Antaocc10b852016-07-28 14:23:26 +00008045
8046 // Remember the current base pointer index.
Alexey Bataevb3638132018-07-19 16:34:13 +00008047 unsigned CurrentBasePointersIdx = CurBasePointers.size();
Michael Krused47b9432019-08-05 18:43:21 +00008048 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8049 CurBasePointers, CurPointers, CurSizes,
8050 CurTypes, PartialStruct,
8051 IsFirstComponentList, L.IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00008052
8053 // If this entry relates with a device pointer, set the relevant
8054 // declaration and add the 'return pointer' flag.
Alexey Bataevb3638132018-07-19 16:34:13 +00008055 if (L.ReturnDevicePointer) {
8056 assert(CurBasePointers.size() > CurrentBasePointersIdx &&
Samuel Antaocc10b852016-07-28 14:23:26 +00008057 "Unexpected number of mapped base pointers.");
8058
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008059 const ValueDecl *RelevantVD =
8060 L.Components.back().getAssociatedDeclaration();
Samuel Antaocc10b852016-07-28 14:23:26 +00008061 assert(RelevantVD &&
8062 "No relevant declaration related with device pointer??");
8063
Alexey Bataevb3638132018-07-19 16:34:13 +00008064 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD);
8065 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008066 }
Samuel Antao86ace552016-04-27 22:40:57 +00008067 IsFirstComponentList = false;
8068 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008069
8070 // Append any pending zero-length pointers which are struct members and
8071 // used with use_device_ptr.
8072 auto CI = DeferredInfo.find(M.first);
8073 if (CI != DeferredInfo.end()) {
8074 for (const DeferredDevicePtrEntryTy &L : CI->second) {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008075 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF);
Alexey Bataevb3638132018-07-19 16:34:13 +00008076 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar(
8077 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc());
8078 CurBasePointers.emplace_back(BasePtr, L.VD);
8079 CurPointers.push_back(Ptr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008080 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00008081 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder
8082 // value MEMBER_OF=FFFF so that the entry is later updated with the
8083 // correct value of MEMBER_OF.
8084 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM |
8085 OMP_MAP_MEMBER_OF);
8086 }
8087 }
8088
8089 // If there is an entry in PartialStruct it means we have a struct with
8090 // individual members mapped. Emit an extra combined entry.
8091 if (PartialStruct.Base.isValid())
8092 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8093 PartialStruct);
8094
8095 // We need to append the results of this capture to what we already have.
8096 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8097 Pointers.append(CurPointers.begin(), CurPointers.end());
8098 Sizes.append(CurSizes.begin(), CurSizes.end());
8099 Types.append(CurTypes.begin(), CurTypes.end());
Samuel Antao86ace552016-04-27 22:40:57 +00008100 }
8101 }
8102
Michael Krused47b9432019-08-05 18:43:21 +00008103 /// Generate all the base pointers, section pointers, sizes and map types for
8104 /// the extracted map clauses of user-defined mapper.
8105 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers,
8106 MapValuesArrayTy &Pointers,
8107 MapValuesArrayTy &Sizes,
8108 MapFlagsArrayTy &Types) const {
8109 assert(CurDir.is<const OMPDeclareMapperDecl *>() &&
8110 "Expect a declare mapper directive");
8111 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>();
8112 // We have to process the component lists that relate with the same
8113 // declaration in a single chunk so that we can generate the map flags
8114 // correctly. Therefore, we organize all lists in a map.
8115 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
8116
8117 // Helper function to fill the information map for the different supported
8118 // clauses.
8119 auto &&InfoGen = [&Info](
8120 const ValueDecl *D,
8121 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
8122 OpenMPMapClauseKind MapType,
8123 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8124 bool ReturnDevicePointer, bool IsImplicit) {
8125 const ValueDecl *VD =
8126 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
8127 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
8128 IsImplicit);
8129 };
8130
8131 for (const auto *C : CurMapperDir->clauselists()) {
8132 const auto *MC = cast<OMPMapClause>(C);
Mark de Wever51abceb2019-11-12 20:48:11 +01008133 for (const auto L : MC->component_lists()) {
Michael Krused47b9432019-08-05 18:43:21 +00008134 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(),
8135 /*ReturnDevicePointer=*/false, MC->isImplicit());
8136 }
8137 }
8138
8139 for (const auto &M : Info) {
8140 // We need to know when we generate information for the first component
8141 // associated with a capture, because the mapping flags depend on it.
8142 bool IsFirstComponentList = true;
8143
8144 // Temporary versions of arrays
8145 MapBaseValuesArrayTy CurBasePointers;
8146 MapValuesArrayTy CurPointers;
8147 MapValuesArrayTy CurSizes;
8148 MapFlagsArrayTy CurTypes;
8149 StructRangeInfoTy PartialStruct;
8150
8151 for (const MapInfo &L : M.second) {
8152 assert(!L.Components.empty() &&
8153 "Not expecting declaration with no component lists.");
8154 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8155 CurBasePointers, CurPointers, CurSizes,
8156 CurTypes, PartialStruct,
8157 IsFirstComponentList, L.IsImplicit);
8158 IsFirstComponentList = false;
8159 }
8160
8161 // If there is an entry in PartialStruct it means we have a struct with
8162 // individual members mapped. Emit an extra combined entry.
8163 if (PartialStruct.Base.isValid())
8164 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8165 PartialStruct);
8166
8167 // We need to append the results of this capture to what we already have.
8168 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8169 Pointers.append(CurPointers.begin(), CurPointers.end());
8170 Sizes.append(CurSizes.begin(), CurSizes.end());
8171 Types.append(CurTypes.begin(), CurTypes.end());
8172 }
8173 }
8174
Alexey Bataev60705422018-10-30 15:50:12 +00008175 /// Emit capture info for lambdas for variables captured by reference.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008176 void generateInfoForLambdaCaptures(
8177 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers,
8178 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
8179 MapFlagsArrayTy &Types,
8180 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008181 const auto *RD = VD->getType()
8182 .getCanonicalType()
8183 .getNonReferenceType()
8184 ->getAsCXXRecordDecl();
8185 if (!RD || !RD->isLambda())
8186 return;
8187 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD));
8188 LValue VDLVal = CGF.MakeAddrLValue(
8189 VDAddr, VD->getType().getCanonicalType().getNonReferenceType());
8190 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
8191 FieldDecl *ThisCapture = nullptr;
8192 RD->getCaptureFields(Captures, ThisCapture);
8193 if (ThisCapture) {
8194 LValue ThisLVal =
8195 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture);
Alexey Bataev969dbc02018-11-08 15:47:39 +00008196 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008197 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
8198 VDLVal.getPointer(CGF));
8199 BasePointers.push_back(ThisLVal.getPointer(CGF));
8200 Pointers.push_back(ThisLValVal.getPointer(CGF));
Alexey Bataeva90fc662019-06-25 16:00:43 +00008201 Sizes.push_back(
8202 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8203 CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008204 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008205 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8206 }
8207 for (const LambdaCapture &LC : RD->captures()) {
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008208 if (!LC.capturesVariable())
Alexey Bataev60705422018-10-30 15:50:12 +00008209 continue;
8210 const VarDecl *VD = LC.getCapturedVar();
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008211 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType())
8212 continue;
Alexey Bataev60705422018-10-30 15:50:12 +00008213 auto It = Captures.find(VD);
8214 assert(It != Captures.end() && "Found lambda capture without field.");
8215 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second);
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008216 if (LC.getCaptureKind() == LCK_ByRef) {
8217 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008218 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
8219 VDLVal.getPointer(CGF));
8220 BasePointers.push_back(VarLVal.getPointer(CGF));
8221 Pointers.push_back(VarLValVal.getPointer(CGF));
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008222 Sizes.push_back(CGF.Builder.CreateIntCast(
8223 CGF.getTypeSize(
8224 VD->getType().getCanonicalType().getNonReferenceType()),
8225 CGF.Int64Ty, /*isSigned=*/true));
8226 } else {
8227 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008228 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
8229 VDLVal.getPointer(CGF));
8230 BasePointers.push_back(VarLVal.getPointer(CGF));
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008231 Pointers.push_back(VarRVal.getScalarVal());
8232 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0));
8233 }
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008234 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008235 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8236 }
8237 }
8238
8239 /// Set correct indices for lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008240 void adjustMemberOfForLambdaCaptures(
8241 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
8242 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
8243 MapFlagsArrayTy &Types) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008244 for (unsigned I = 0, E = Types.size(); I < E; ++I) {
8245 // Set correct member_of idx for all implicit lambda captures.
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008246 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008247 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT))
8248 continue;
Alexey Bataev969dbc02018-11-08 15:47:39 +00008249 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]);
8250 assert(BasePtr && "Unable to find base lambda address.");
Alexey Bataev60705422018-10-30 15:50:12 +00008251 int TgtIdx = -1;
8252 for (unsigned J = I; J > 0; --J) {
8253 unsigned Idx = J - 1;
8254 if (Pointers[Idx] != BasePtr)
8255 continue;
8256 TgtIdx = Idx;
8257 break;
8258 }
8259 assert(TgtIdx != -1 && "Unable to find parent lambda.");
8260 // All other current entries will be MEMBER_OF the combined entry
8261 // (except for PTR_AND_OBJ entries which do not have a placeholder value
8262 // 0xFFFF in the MEMBER_OF field).
8263 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx);
8264 setCorrectMemberOfFlag(Types[I], MemberOfFlag);
8265 }
8266 }
8267
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008268 /// Generate the base pointers, section pointers, sizes and map types
Samuel Antao86ace552016-04-27 22:40:57 +00008269 /// associated to a given capture.
8270 void generateInfoForCapture(const CapturedStmt::Capture *Cap,
Samuel Antao6890b092016-07-28 14:25:09 +00008271 llvm::Value *Arg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008272 MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00008273 MapValuesArrayTy &Pointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008274 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
8275 StructRangeInfoTy &PartialStruct) const {
Samuel Antao86ace552016-04-27 22:40:57 +00008276 assert(!Cap->capturesVariableArrayType() &&
8277 "Not expecting to generate map info for a variable array type!");
8278
Samuel Antao6890b092016-07-28 14:25:09 +00008279 // We need to know when we generating information for the first component
Alexey Bataevb3638132018-07-19 16:34:13 +00008280 const ValueDecl *VD = Cap->capturesThis()
8281 ? nullptr
8282 : Cap->getCapturedVar()->getCanonicalDecl();
Samuel Antao86ace552016-04-27 22:40:57 +00008283
Samuel Antao6890b092016-07-28 14:25:09 +00008284 // If this declaration appears in a is_device_ptr clause we just have to
8285 // pass the pointer by value. If it is a reference to a declaration, we just
Alexey Bataevb3638132018-07-19 16:34:13 +00008286 // pass its value.
8287 if (DevPointersMap.count(VD)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008288 BasePointers.emplace_back(Arg, VD);
Samuel Antao6890b092016-07-28 14:25:09 +00008289 Pointers.push_back(Arg);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008290 Sizes.push_back(
8291 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8292 CGF.Int64Ty, /*isSigned=*/true));
George Rokos065755d2017-11-07 18:27:04 +00008293 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM);
Samuel Antao6890b092016-07-28 14:25:09 +00008294 return;
8295 }
8296
Alexey Bataeve82445f2018-09-20 13:54:02 +00008297 using MapData =
8298 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
Kelvin Lief579432018-12-18 22:18:41 +00008299 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008300 SmallVector<MapData, 4> DeclComponentLists;
Michael Krused47b9432019-08-05 18:43:21 +00008301 assert(CurDir.is<const OMPExecutableDirective *>() &&
8302 "Expect a executable directive");
8303 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
8304 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
Mark de Wever51abceb2019-11-12 20:48:11 +01008305 for (const auto L : C->decl_component_lists(VD)) {
Samuel Antao86ace552016-04-27 22:40:57 +00008306 assert(L.first == VD &&
8307 "We got information for the wrong declaration??");
8308 assert(!L.second.empty() &&
8309 "Not expecting declaration with no component lists.");
Alexey Bataeve82445f2018-09-20 13:54:02 +00008310 DeclComponentLists.emplace_back(L.second, C->getMapType(),
Kelvin Lief579432018-12-18 22:18:41 +00008311 C->getMapTypeModifiers(),
Alexey Bataeve82445f2018-09-20 13:54:02 +00008312 C->isImplicit());
Samuel Antao86ace552016-04-27 22:40:57 +00008313 }
Alexey Bataeve82445f2018-09-20 13:54:02 +00008314 }
8315
8316 // Find overlapping elements (including the offset from the base element).
8317 llvm::SmallDenseMap<
8318 const MapData *,
8319 llvm::SmallVector<
8320 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>,
8321 4>
8322 OverlappedData;
8323 size_t Count = 0;
8324 for (const MapData &L : DeclComponentLists) {
8325 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8326 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008327 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008328 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008329 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008330 ++Count;
8331 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) {
8332 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1;
Kelvin Lief579432018-12-18 22:18:41 +00008333 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008334 auto CI = Components.rbegin();
8335 auto CE = Components.rend();
8336 auto SI = Components1.rbegin();
8337 auto SE = Components1.rend();
8338 for (; CI != CE && SI != SE; ++CI, ++SI) {
8339 if (CI->getAssociatedExpression()->getStmtClass() !=
8340 SI->getAssociatedExpression()->getStmtClass())
8341 break;
8342 // Are we dealing with different variables/fields?
8343 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
8344 break;
8345 }
8346 // Found overlapping if, at least for one component, reached the head of
8347 // the components list.
8348 if (CI == CE || SI == SE) {
8349 assert((CI != CE || SI != SE) &&
8350 "Unexpected full match of the mapping components.");
8351 const MapData &BaseData = CI == CE ? L : L1;
8352 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData =
8353 SI == SE ? Components : Components1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008354 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData);
8355 OverlappedElements.getSecond().push_back(SubData);
8356 }
8357 }
8358 }
8359 // Sort the overlapped elements for each item.
8360 llvm::SmallVector<const FieldDecl *, 4> Layout;
8361 if (!OverlappedData.empty()) {
8362 if (const auto *CRD =
8363 VD->getType().getCanonicalType()->getAsCXXRecordDecl())
8364 getPlainLayout(CRD, Layout, /*AsBase=*/false);
8365 else {
8366 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl();
8367 Layout.append(RD->field_begin(), RD->field_end());
8368 }
8369 }
8370 for (auto &Pair : OverlappedData) {
8371 llvm::sort(
8372 Pair.getSecond(),
8373 [&Layout](
8374 OMPClauseMappableExprCommon::MappableExprComponentListRef First,
8375 OMPClauseMappableExprCommon::MappableExprComponentListRef
8376 Second) {
8377 auto CI = First.rbegin();
8378 auto CE = First.rend();
8379 auto SI = Second.rbegin();
8380 auto SE = Second.rend();
8381 for (; CI != CE && SI != SE; ++CI, ++SI) {
8382 if (CI->getAssociatedExpression()->getStmtClass() !=
8383 SI->getAssociatedExpression()->getStmtClass())
8384 break;
8385 // Are we dealing with different variables/fields?
8386 if (CI->getAssociatedDeclaration() !=
8387 SI->getAssociatedDeclaration())
8388 break;
8389 }
Richard Trieu5061e832018-09-21 21:20:33 +00008390
8391 // Lists contain the same elements.
8392 if (CI == CE && SI == SE)
8393 return false;
8394
8395 // List with less elements is less than list with more elements.
8396 if (CI == CE || SI == SE)
8397 return CI == CE;
8398
Alexey Bataeve82445f2018-09-20 13:54:02 +00008399 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
8400 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
8401 if (FD1->getParent() == FD2->getParent())
8402 return FD1->getFieldIndex() < FD2->getFieldIndex();
8403 const auto It =
8404 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) {
8405 return FD == FD1 || FD == FD2;
8406 });
8407 return *It == FD1;
8408 });
8409 }
8410
8411 // Associated with a capture, because the mapping flags depend on it.
8412 // Go through all of the elements with the overlapped elements.
8413 for (const auto &Pair : OverlappedData) {
8414 const MapData &L = *Pair.getFirst();
8415 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8416 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008417 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008418 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008419 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008420 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
8421 OverlappedComponents = Pair.getSecond();
8422 bool IsFirstComponentList = true;
Kelvin Lief579432018-12-18 22:18:41 +00008423 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008424 BasePointers, Pointers, Sizes, Types,
8425 PartialStruct, IsFirstComponentList,
8426 IsImplicit, OverlappedComponents);
8427 }
8428 // Go through other elements without overlapped elements.
8429 bool IsFirstComponentList = OverlappedData.empty();
8430 for (const MapData &L : DeclComponentLists) {
8431 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8432 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008433 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008434 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008435 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008436 auto It = OverlappedData.find(&L);
8437 if (It == OverlappedData.end())
Kelvin Lief579432018-12-18 22:18:41 +00008438 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008439 BasePointers, Pointers, Sizes, Types,
8440 PartialStruct, IsFirstComponentList,
8441 IsImplicit);
8442 IsFirstComponentList = false;
8443 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008444 }
Samuel Antao86ace552016-04-27 22:40:57 +00008445
Alexey Bataevb3638132018-07-19 16:34:13 +00008446 /// Generate the base pointers, section pointers, sizes and map types
8447 /// associated with the declare target link variables.
8448 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers,
8449 MapValuesArrayTy &Pointers,
8450 MapValuesArrayTy &Sizes,
8451 MapFlagsArrayTy &Types) const {
Michael Krused47b9432019-08-05 18:43:21 +00008452 assert(CurDir.is<const OMPExecutableDirective *>() &&
8453 "Expect a executable directive");
8454 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
Alexey Bataevb3638132018-07-19 16:34:13 +00008455 // Map other list items in the map clause which are not captured variables
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00008456 // but "declare target link" global variables.
Michael Krused47b9432019-08-05 18:43:21 +00008457 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
Mark de Wever51abceb2019-11-12 20:48:11 +01008458 for (const auto L : C->component_lists()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00008459 if (!L.first)
8460 continue;
8461 const auto *VD = dyn_cast<VarDecl>(L.first);
8462 if (!VD)
8463 continue;
8464 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00008465 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00008466 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
8467 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)
Alexey Bataevb3638132018-07-19 16:34:13 +00008468 continue;
8469 StructRangeInfoTy PartialStruct;
8470 generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00008471 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008472 Pointers, Sizes, Types, PartialStruct,
8473 /*IsFirstComponentList=*/true, C->isImplicit());
8474 assert(!PartialStruct.Base.isValid() &&
8475 "No partial structs for declare target link expected.");
8476 }
8477 }
Samuel Antao86ace552016-04-27 22:40:57 +00008478 }
Samuel Antaod486f842016-05-26 16:53:38 +00008479
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008480 /// Generate the default map information for a given capture \a CI,
Samuel Antaod486f842016-05-26 16:53:38 +00008481 /// record field declaration \a RI and captured value \a CV.
Samuel Antaocc10b852016-07-28 14:23:26 +00008482 void generateDefaultMapInfo(const CapturedStmt::Capture &CI,
8483 const FieldDecl &RI, llvm::Value *CV,
8484 MapBaseValuesArrayTy &CurBasePointers,
8485 MapValuesArrayTy &CurPointers,
8486 MapValuesArrayTy &CurSizes,
Alexey Bataevb3638132018-07-19 16:34:13 +00008487 MapFlagsArrayTy &CurMapTypes) const {
Alexey Bataevf288cf92019-06-27 18:53:07 +00008488 bool IsImplicit = true;
Samuel Antaod486f842016-05-26 16:53:38 +00008489 // Do the default mapping.
8490 if (CI.capturesThis()) {
8491 CurBasePointers.push_back(CV);
8492 CurPointers.push_back(CV);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008493 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr());
Alexey Bataeva90fc662019-06-25 16:00:43 +00008494 CurSizes.push_back(
8495 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()),
8496 CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008497 // Default map type.
Samuel Antaocc10b852016-07-28 14:23:26 +00008498 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM);
Samuel Antaod486f842016-05-26 16:53:38 +00008499 } else if (CI.capturesVariableByCopy()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008500 CurBasePointers.push_back(CV);
8501 CurPointers.push_back(CV);
Samuel Antaod486f842016-05-26 16:53:38 +00008502 if (!RI.getType()->isAnyPointerType()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008503 // We have to signal to the runtime captures passed by value that are
8504 // not pointers.
George Rokos065755d2017-11-07 18:27:04 +00008505 CurMapTypes.push_back(OMP_MAP_LITERAL);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008506 CurSizes.push_back(CGF.Builder.CreateIntCast(
8507 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008508 } else {
8509 // Pointers are implicitly mapped with a zero size and no flags
8510 // (other than first map that is added for all implicit maps).
Alexey Bataevb3638132018-07-19 16:34:13 +00008511 CurMapTypes.push_back(OMP_MAP_NONE);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008512 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
Samuel Antaod486f842016-05-26 16:53:38 +00008513 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008514 const VarDecl *VD = CI.getCapturedVar();
8515 auto I = FirstPrivateDecls.find(VD);
8516 if (I != FirstPrivateDecls.end())
8517 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008518 } else {
8519 assert(CI.capturesVariable() && "Expected captured reference.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008520 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr());
Samuel Antaod486f842016-05-26 16:53:38 +00008521 QualType ElementType = PtrTy->getPointeeType();
Alexey Bataeva90fc662019-06-25 16:00:43 +00008522 CurSizes.push_back(CGF.Builder.CreateIntCast(
8523 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008524 // The default map type for a scalar/complex type is 'to' because by
8525 // default the value doesn't have to be retrieved. For an aggregate
8526 // type, the default is 'tofrom'.
Alexey Bataevb3638132018-07-19 16:34:13 +00008527 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI));
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008528 const VarDecl *VD = CI.getCapturedVar();
Alexey Bataevf288cf92019-06-27 18:53:07 +00008529 auto I = FirstPrivateDecls.find(VD);
8530 if (I != FirstPrivateDecls.end() &&
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008531 VD->getType().isConstant(CGF.getContext())) {
8532 llvm::Constant *Addr =
8533 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD);
8534 // Copy the value of the original variable to the new global copy.
8535 CGF.Builder.CreateMemCpy(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008536 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(CGF),
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008537 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)),
Rui Ueyama49a3ad22019-07-16 04:46:31 +00008538 CurSizes.back(), /*IsVolatile=*/false);
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008539 // Use new global variable as the base pointers.
8540 CurBasePointers.push_back(Addr);
8541 CurPointers.push_back(Addr);
8542 } else {
8543 CurBasePointers.push_back(CV);
Alexey Bataevf288cf92019-06-27 18:53:07 +00008544 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) {
Alexey Bataevc2b831f2019-04-02 16:03:40 +00008545 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue(
8546 CV, ElementType, CGF.getContext().getDeclAlign(VD),
8547 AlignmentSource::Decl));
8548 CurPointers.push_back(PtrAddr.getPointer());
8549 } else {
8550 CurPointers.push_back(CV);
8551 }
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008552 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008553 if (I != FirstPrivateDecls.end())
8554 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008555 }
George Rokos065755d2017-11-07 18:27:04 +00008556 // Every default map produces a single argument which is a target parameter.
8557 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM;
Alexey Bataevb3638132018-07-19 16:34:13 +00008558
8559 // Add flag stating this is an implicit map.
Alexey Bataevf288cf92019-06-27 18:53:07 +00008560 if (IsImplicit)
8561 CurMapTypes.back() |= OMP_MAP_IMPLICIT;
Samuel Antaod486f842016-05-26 16:53:38 +00008562 }
Samuel Antao86ace552016-04-27 22:40:57 +00008563};
Samuel Antaodf158d52016-04-27 22:58:19 +00008564} // anonymous namespace
8565
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008566/// Emit the arrays used to pass the captures and map information to the
Samuel Antaodf158d52016-04-27 22:58:19 +00008567/// offloading runtime library. If there is no map or capture information,
8568/// return nullptr by reference.
8569static void
Samuel Antaocc10b852016-07-28 14:23:26 +00008570emitOffloadingArrays(CodeGenFunction &CGF,
8571 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers,
Samuel Antaodf158d52016-04-27 22:58:19 +00008572 MappableExprsHandler::MapValuesArrayTy &Pointers,
8573 MappableExprsHandler::MapValuesArrayTy &Sizes,
Samuel Antaocc10b852016-07-28 14:23:26 +00008574 MappableExprsHandler::MapFlagsArrayTy &MapTypes,
8575 CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008576 CodeGenModule &CGM = CGF.CGM;
8577 ASTContext &Ctx = CGF.getContext();
Samuel Antaodf158d52016-04-27 22:58:19 +00008578
Samuel Antaocc10b852016-07-28 14:23:26 +00008579 // Reset the array information.
8580 Info.clearArrayInfo();
8581 Info.NumberOfPtrs = BasePointers.size();
Samuel Antaodf158d52016-04-27 22:58:19 +00008582
Samuel Antaocc10b852016-07-28 14:23:26 +00008583 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008584 // Detect if we have any capture size requiring runtime evaluation of the
8585 // size so that a constant array could be eventually used.
8586 bool hasRuntimeEvaluationCaptureSize = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008587 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008588 if (!isa<llvm::Constant>(S)) {
8589 hasRuntimeEvaluationCaptureSize = true;
8590 break;
8591 }
8592
Samuel Antaocc10b852016-07-28 14:23:26 +00008593 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true);
Richard Smith772e2662019-10-04 01:25:59 +00008594 QualType PointerArrayType = Ctx.getConstantArrayType(
8595 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal,
8596 /*IndexTypeQuals=*/0);
Samuel Antaodf158d52016-04-27 22:58:19 +00008597
Samuel Antaocc10b852016-07-28 14:23:26 +00008598 Info.BasePointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008599 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
Samuel Antaocc10b852016-07-28 14:23:26 +00008600 Info.PointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008601 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
8602
8603 // If we don't have any VLA types or other types that require runtime
8604 // evaluation, we can use a constant array for the map sizes, otherwise we
8605 // need to fill up the arrays as we do for the pointers.
Alexey Bataeva90fc662019-06-25 16:00:43 +00008606 QualType Int64Ty =
8607 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Samuel Antaodf158d52016-04-27 22:58:19 +00008608 if (hasRuntimeEvaluationCaptureSize) {
Richard Smith772e2662019-10-04 01:25:59 +00008609 QualType SizeArrayType = Ctx.getConstantArrayType(
8610 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal,
8611 /*IndexTypeQuals=*/0);
Samuel Antaocc10b852016-07-28 14:23:26 +00008612 Info.SizesArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008613 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
8614 } else {
8615 // We expect all the sizes to be constant, so we collect them to create
8616 // a constant array.
8617 SmallVector<llvm::Constant *, 16> ConstSizes;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008618 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008619 ConstSizes.push_back(cast<llvm::Constant>(S));
8620
8621 auto *SizesArrayInit = llvm::ConstantArray::get(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008622 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008623 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008624 auto *SizesArrayGbl = new llvm::GlobalVariable(
8625 CGM.getModule(), SizesArrayInit->getType(),
8626 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008627 SizesArrayInit, Name);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008628 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008629 Info.SizesArray = SizesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008630 }
8631
8632 // The map types are always constant so we don't need to generate code to
8633 // fill arrays. Instead, we create an array constant.
Alexey Bataevb3638132018-07-19 16:34:13 +00008634 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0);
8635 llvm::copy(MapTypes, Mapping.begin());
Samuel Antaodf158d52016-04-27 22:58:19 +00008636 llvm::Constant *MapTypesArrayInit =
Alexey Bataevb3638132018-07-19 16:34:13 +00008637 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008638 std::string MaptypesName =
8639 CGM.getOpenMPRuntime().getName({"offload_maptypes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008640 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
8641 CGM.getModule(), MapTypesArrayInit->getType(),
8642 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008643 MapTypesArrayInit, MaptypesName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008644 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008645 Info.MapTypesArray = MapTypesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008646
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008647 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) {
8648 llvm::Value *BPVal = *BasePointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008649 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008650 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008651 Info.BasePointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008652 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8653 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008654 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8655 CGF.Builder.CreateStore(BPVal, BPAddr);
8656
Samuel Antaocc10b852016-07-28 14:23:26 +00008657 if (Info.requiresDevicePointerInfo())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008658 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl())
Alexey Bataev43a919f2018-04-13 17:48:43 +00008659 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr);
Samuel Antaocc10b852016-07-28 14:23:26 +00008660
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008661 llvm::Value *PVal = Pointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008662 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008663 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008664 Info.PointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008665 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8666 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008667 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8668 CGF.Builder.CreateStore(PVal, PAddr);
8669
8670 if (hasRuntimeEvaluationCaptureSize) {
8671 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008672 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008673 Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008674 /*Idx0=*/0,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008675 /*Idx1=*/I);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008676 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty));
Samuel Antaodf158d52016-04-27 22:58:19 +00008677 CGF.Builder.CreateStore(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008678 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true),
Samuel Antaodf158d52016-04-27 22:58:19 +00008679 SAddr);
8680 }
8681 }
8682 }
8683}
Michael Krused47b9432019-08-05 18:43:21 +00008684
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008685/// Emit the arguments to be passed to the runtime library based on the
Samuel Antaodf158d52016-04-27 22:58:19 +00008686/// arrays of pointers, sizes and map types.
8687static void emitOffloadingArraysArgument(
8688 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg,
8689 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008690 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008691 CodeGenModule &CGM = CGF.CGM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008692 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008693 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008694 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8695 Info.BasePointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008696 /*Idx0=*/0, /*Idx1=*/0);
8697 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008698 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8699 Info.PointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008700 /*Idx0=*/0,
8701 /*Idx1=*/0);
8702 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008703 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008704 /*Idx0=*/0, /*Idx1=*/0);
8705 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
George Rokos63bc9d62017-11-21 18:25:12 +00008706 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008707 Info.MapTypesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008708 /*Idx0=*/0,
8709 /*Idx1=*/0);
8710 } else {
8711 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
8712 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008713 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008714 MapTypesArrayArg =
George Rokos63bc9d62017-11-21 18:25:12 +00008715 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008716 }
Samuel Antao86ace552016-04-27 22:40:57 +00008717}
8718
Alexey Bataev7bb33532019-01-07 21:30:43 +00008719/// Check for inner distribute directive.
8720static const OMPExecutableDirective *
8721getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
8722 const auto *CS = D.getInnermostCapturedStmt();
8723 const auto *Body =
8724 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00008725 const Stmt *ChildStmt =
8726 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
Alexey Bataev7bb33532019-01-07 21:30:43 +00008727
Alexey Bataev5c427362019-04-10 19:11:33 +00008728 if (const auto *NestedDir =
8729 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008730 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind();
8731 switch (D.getDirectiveKind()) {
8732 case OMPD_target:
8733 if (isOpenMPDistributeDirective(DKind))
8734 return NestedDir;
8735 if (DKind == OMPD_teams) {
8736 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
8737 /*IgnoreCaptured=*/true);
8738 if (!Body)
8739 return nullptr;
Alexey Bataev5c427362019-04-10 19:11:33 +00008740 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
8741 if (const auto *NND =
8742 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008743 DKind = NND->getDirectiveKind();
8744 if (isOpenMPDistributeDirective(DKind))
8745 return NND;
8746 }
8747 }
8748 return nullptr;
8749 case OMPD_target_teams:
8750 if (isOpenMPDistributeDirective(DKind))
8751 return NestedDir;
8752 return nullptr;
8753 case OMPD_target_parallel:
8754 case OMPD_target_simd:
8755 case OMPD_target_parallel_for:
8756 case OMPD_target_parallel_for_simd:
8757 return nullptr;
8758 case OMPD_target_teams_distribute:
8759 case OMPD_target_teams_distribute_simd:
8760 case OMPD_target_teams_distribute_parallel_for:
8761 case OMPD_target_teams_distribute_parallel_for_simd:
8762 case OMPD_parallel:
8763 case OMPD_for:
8764 case OMPD_parallel_for:
8765 case OMPD_parallel_sections:
8766 case OMPD_for_simd:
8767 case OMPD_parallel_for_simd:
8768 case OMPD_cancel:
8769 case OMPD_cancellation_point:
8770 case OMPD_ordered:
8771 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00008772 case OMPD_allocate:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008773 case OMPD_task:
8774 case OMPD_simd:
8775 case OMPD_sections:
8776 case OMPD_section:
8777 case OMPD_single:
8778 case OMPD_master:
8779 case OMPD_critical:
8780 case OMPD_taskyield:
8781 case OMPD_barrier:
8782 case OMPD_taskwait:
8783 case OMPD_taskgroup:
8784 case OMPD_atomic:
8785 case OMPD_flush:
8786 case OMPD_teams:
8787 case OMPD_target_data:
8788 case OMPD_target_exit_data:
8789 case OMPD_target_enter_data:
8790 case OMPD_distribute:
8791 case OMPD_distribute_simd:
8792 case OMPD_distribute_parallel_for:
8793 case OMPD_distribute_parallel_for_simd:
8794 case OMPD_teams_distribute:
8795 case OMPD_teams_distribute_simd:
8796 case OMPD_teams_distribute_parallel_for:
8797 case OMPD_teams_distribute_parallel_for_simd:
8798 case OMPD_target_update:
8799 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00008800 case OMPD_declare_variant:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008801 case OMPD_declare_target:
8802 case OMPD_end_declare_target:
8803 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00008804 case OMPD_declare_mapper:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008805 case OMPD_taskloop:
8806 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00008807 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00008808 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00008809 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04008810 case OMPD_parallel_master_taskloop_simd:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008811 case OMPD_requires:
8812 case OMPD_unknown:
8813 llvm_unreachable("Unexpected directive.");
8814 }
8815 }
8816
8817 return nullptr;
8818}
8819
Michael Krused47b9432019-08-05 18:43:21 +00008820/// Emit the user-defined mapper function. The code generation follows the
8821/// pattern in the example below.
8822/// \code
8823/// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle,
8824/// void *base, void *begin,
8825/// int64_t size, int64_t type) {
8826/// // Allocate space for an array section first.
8827/// if (size > 1 && !maptype.IsDelete)
8828/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
8829/// size*sizeof(Ty), clearToFrom(type));
8830/// // Map members.
8831/// for (unsigned i = 0; i < size; i++) {
8832/// // For each component specified by this mapper:
8833/// for (auto c : all_components) {
8834/// if (c.hasMapper())
8835/// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size,
8836/// c.arg_type);
8837/// else
8838/// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base,
8839/// c.arg_begin, c.arg_size, c.arg_type);
8840/// }
8841/// }
8842/// // Delete the array section.
8843/// if (size > 1 && maptype.IsDelete)
8844/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
8845/// size*sizeof(Ty), clearToFrom(type));
8846/// }
8847/// \endcode
8848void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D,
8849 CodeGenFunction *CGF) {
8850 if (UDMMap.count(D) > 0)
8851 return;
8852 ASTContext &C = CGM.getContext();
8853 QualType Ty = D->getType();
8854 QualType PtrTy = C.getPointerType(Ty).withRestrict();
8855 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
8856 auto *MapperVarDecl =
8857 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl());
8858 SourceLocation Loc = D->getLocation();
8859 CharUnits ElementSize = C.getTypeSizeInChars(Ty);
8860
8861 // Prepare mapper function arguments and attributes.
8862 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
8863 C.VoidPtrTy, ImplicitParamDecl::Other);
8864 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
8865 ImplicitParamDecl::Other);
8866 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
8867 C.VoidPtrTy, ImplicitParamDecl::Other);
8868 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
8869 ImplicitParamDecl::Other);
8870 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
8871 ImplicitParamDecl::Other);
8872 FunctionArgList Args;
8873 Args.push_back(&HandleArg);
8874 Args.push_back(&BaseArg);
8875 Args.push_back(&BeginArg);
8876 Args.push_back(&SizeArg);
8877 Args.push_back(&TypeArg);
8878 const CGFunctionInfo &FnInfo =
8879 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
8880 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
8881 SmallString<64> TyStr;
8882 llvm::raw_svector_ostream Out(TyStr);
8883 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out);
8884 std::string Name = getName({"omp_mapper", TyStr, D->getName()});
8885 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
8886 Name, &CGM.getModule());
8887 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
8888 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
8889 // Start the mapper function code generation.
8890 CodeGenFunction MapperCGF(CGM);
8891 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
8892 // Compute the starting and end addreses of array elements.
8893 llvm::Value *Size = MapperCGF.EmitLoadOfScalar(
8894 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false,
8895 C.getPointerType(Int64Ty), Loc);
8896 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast(
8897 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(),
8898 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy)));
8899 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size);
8900 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar(
8901 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false,
8902 C.getPointerType(Int64Ty), Loc);
8903 // Prepare common arguments for array initiation and deletion.
8904 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar(
8905 MapperCGF.GetAddrOfLocalVar(&HandleArg),
8906 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8907 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar(
8908 MapperCGF.GetAddrOfLocalVar(&BaseArg),
8909 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8910 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar(
8911 MapperCGF.GetAddrOfLocalVar(&BeginArg),
8912 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8913
8914 // Emit array initiation if this is an array section and \p MapType indicates
8915 // that memory allocation is required.
8916 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head");
8917 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
8918 ElementSize, HeadBB, /*IsInit=*/true);
8919
8920 // Emit a for loop to iterate through SizeArg of elements and map all of them.
8921
8922 // Emit the loop header block.
8923 MapperCGF.EmitBlock(HeadBB);
8924 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body");
8925 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done");
8926 // Evaluate whether the initial condition is satisfied.
8927 llvm::Value *IsEmpty =
8928 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty");
8929 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
8930 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock();
8931
8932 // Emit the loop body block.
8933 MapperCGF.EmitBlock(BodyBB);
8934 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI(
8935 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent");
8936 PtrPHI->addIncoming(PtrBegin, EntryBB);
8937 Address PtrCurrent =
8938 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg)
8939 .getAlignment()
8940 .alignmentOfArrayElement(ElementSize));
8941 // Privatize the declared variable of mapper to be the current array element.
8942 CodeGenFunction::OMPPrivateScope Scope(MapperCGF);
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08008943 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() {
Michael Krused47b9432019-08-05 18:43:21 +00008944 return MapperCGF
8945 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>())
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008946 .getAddress(MapperCGF);
Michael Krused47b9432019-08-05 18:43:21 +00008947 });
8948 (void)Scope.Privatize();
8949
8950 // Get map clause information. Fill up the arrays with all mapped variables.
8951 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
8952 MappableExprsHandler::MapValuesArrayTy Pointers;
8953 MappableExprsHandler::MapValuesArrayTy Sizes;
8954 MappableExprsHandler::MapFlagsArrayTy MapTypes;
8955 MappableExprsHandler MEHandler(*D, MapperCGF);
8956 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes);
8957
8958 // Call the runtime API __tgt_mapper_num_components to get the number of
8959 // pre-existing components.
8960 llvm::Value *OffloadingArgs[] = {Handle};
8961 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall(
8962 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs);
8963 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl(
8964 PreviousSize,
8965 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset()));
8966
8967 // Fill up the runtime mapper handle for all components.
8968 for (unsigned I = 0; I < BasePointers.size(); ++I) {
8969 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast(
8970 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
8971 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast(
8972 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
8973 llvm::Value *CurSizeArg = Sizes[I];
8974
8975 // Extract the MEMBER_OF field from the map type.
8976 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member");
8977 MapperCGF.EmitBlock(MemberBB);
8978 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]);
8979 llvm::Value *Member = MapperCGF.Builder.CreateAnd(
8980 OriMapType,
8981 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF));
8982 llvm::BasicBlock *MemberCombineBB =
8983 MapperCGF.createBasicBlock("omp.member.combine");
8984 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type");
8985 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member);
8986 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB);
8987 // Add the number of pre-existing components to the MEMBER_OF field if it
8988 // is valid.
8989 MapperCGF.EmitBlock(MemberCombineBB);
8990 llvm::Value *CombinedMember =
8991 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
8992 // Do nothing if it is not a member of previous components.
8993 MapperCGF.EmitBlock(TypeBB);
8994 llvm::PHINode *MemberMapType =
8995 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype");
8996 MemberMapType->addIncoming(OriMapType, MemberBB);
8997 MemberMapType->addIncoming(CombinedMember, MemberCombineBB);
8998
8999 // Combine the map type inherited from user-defined mapper with that
9000 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM
9001 // bits of the \a MapType, which is the input argument of the mapper
9002 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM
9003 // bits of MemberMapType.
9004 // [OpenMP 5.0], 1.2.6. map-type decay.
9005 // | alloc | to | from | tofrom | release | delete
9006 // ----------------------------------------------------------
9007 // alloc | alloc | alloc | alloc | alloc | release | delete
9008 // to | alloc | to | alloc | to | release | delete
9009 // from | alloc | alloc | from | from | release | delete
9010 // tofrom | alloc | to | from | tofrom | release | delete
9011 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd(
9012 MapType,
9013 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO |
9014 MappableExprsHandler::OMP_MAP_FROM));
9015 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc");
9016 llvm::BasicBlock *AllocElseBB =
9017 MapperCGF.createBasicBlock("omp.type.alloc.else");
9018 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to");
9019 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else");
9020 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from");
9021 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end");
9022 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom);
9023 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
9024 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM.
9025 MapperCGF.EmitBlock(AllocBB);
9026 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd(
9027 MemberMapType,
9028 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9029 MappableExprsHandler::OMP_MAP_FROM)));
9030 MapperCGF.Builder.CreateBr(EndBB);
9031 MapperCGF.EmitBlock(AllocElseBB);
9032 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ(
9033 LeftToFrom,
9034 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO));
9035 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
9036 // In case of to, clear OMP_MAP_FROM.
9037 MapperCGF.EmitBlock(ToBB);
9038 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd(
9039 MemberMapType,
9040 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM));
9041 MapperCGF.Builder.CreateBr(EndBB);
9042 MapperCGF.EmitBlock(ToElseBB);
9043 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ(
9044 LeftToFrom,
9045 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM));
9046 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB);
9047 // In case of from, clear OMP_MAP_TO.
9048 MapperCGF.EmitBlock(FromBB);
9049 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd(
9050 MemberMapType,
9051 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO));
9052 // In case of tofrom, do nothing.
9053 MapperCGF.EmitBlock(EndBB);
9054 llvm::PHINode *CurMapType =
9055 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype");
9056 CurMapType->addIncoming(AllocMapType, AllocBB);
9057 CurMapType->addIncoming(ToMapType, ToBB);
9058 CurMapType->addIncoming(FromMapType, FromBB);
9059 CurMapType->addIncoming(MemberMapType, ToElseBB);
9060
9061 // TODO: call the corresponding mapper function if a user-defined mapper is
9062 // associated with this map clause.
9063 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9064 // data structure.
9065 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg,
9066 CurSizeArg, CurMapType};
9067 MapperCGF.EmitRuntimeCall(
9068 createRuntimeFunction(OMPRTL__tgt_push_mapper_component),
9069 OffloadingArgs);
9070 }
9071
9072 // Update the pointer to point to the next element that needs to be mapped,
9073 // and check whether we have mapped all elements.
9074 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32(
9075 PtrPHI, /*Idx0=*/1, "omp.arraymap.next");
9076 PtrPHI->addIncoming(PtrNext, BodyBB);
9077 llvm::Value *IsDone =
9078 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone");
9079 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit");
9080 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
9081
9082 MapperCGF.EmitBlock(ExitBB);
9083 // Emit array deletion if this is an array section and \p MapType indicates
9084 // that deletion is required.
9085 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
9086 ElementSize, DoneBB, /*IsInit=*/false);
9087
9088 // Emit the function exit block.
9089 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true);
9090 MapperCGF.FinishFunction();
9091 UDMMap.try_emplace(D, Fn);
9092 if (CGF) {
9093 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn);
9094 Decls.second.push_back(D);
9095 }
9096}
9097
9098/// Emit the array initialization or deletion portion for user-defined mapper
9099/// code generation. First, it evaluates whether an array section is mapped and
9100/// whether the \a MapType instructs to delete this section. If \a IsInit is
9101/// true, and \a MapType indicates to not delete this array, array
9102/// initialization code is generated. If \a IsInit is false, and \a MapType
9103/// indicates to not this array, array deletion code is generated.
9104void CGOpenMPRuntime::emitUDMapperArrayInitOrDel(
9105 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base,
9106 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType,
9107 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) {
9108 StringRef Prefix = IsInit ? ".init" : ".del";
9109
9110 // Evaluate if this is an array section.
9111 llvm::BasicBlock *IsDeleteBB =
9112 MapperCGF.createBasicBlock("omp.array" + Prefix + ".evaldelete");
9113 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.array" + Prefix);
9114 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE(
9115 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray");
9116 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB);
9117
9118 // Evaluate if we are going to delete this section.
9119 MapperCGF.EmitBlock(IsDeleteBB);
9120 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd(
9121 MapType,
9122 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE));
9123 llvm::Value *DeleteCond;
9124 if (IsInit) {
9125 DeleteCond = MapperCGF.Builder.CreateIsNull(
9126 DeleteBit, "omp.array" + Prefix + ".delete");
9127 } else {
9128 DeleteCond = MapperCGF.Builder.CreateIsNotNull(
9129 DeleteBit, "omp.array" + Prefix + ".delete");
9130 }
9131 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB);
9132
9133 MapperCGF.EmitBlock(BodyBB);
9134 // Get the array size by multiplying element size and element number (i.e., \p
9135 // Size).
9136 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul(
9137 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
9138 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves
9139 // memory allocation/deletion purpose only.
9140 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd(
9141 MapType,
9142 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9143 MappableExprsHandler::OMP_MAP_FROM)));
9144 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9145 // data structure.
9146 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg};
9147 MapperCGF.EmitRuntimeCall(
9148 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs);
9149}
9150
Alexey Bataev7bb33532019-01-07 21:30:43 +00009151void CGOpenMPRuntime::emitTargetNumIterationsCall(
Alexey Bataevec7946e2019-09-23 14:06:51 +00009152 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9153 llvm::Value *DeviceID,
9154 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9155 const OMPLoopDirective &D)>
9156 SizeEmitter) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00009157 OpenMPDirectiveKind Kind = D.getDirectiveKind();
9158 const OMPExecutableDirective *TD = &D;
9159 // Get nested teams distribute kind directive, if any.
9160 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind))
9161 TD = getNestedDistributeDirective(CGM.getContext(), D);
9162 if (!TD)
9163 return;
9164 const auto *LD = cast<OMPLoopDirective>(TD);
Alexey Bataevec7946e2019-09-23 14:06:51 +00009165 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF,
Alexey Bataev7bb33532019-01-07 21:30:43 +00009166 PrePostActionTy &) {
Alexey Bataevec7946e2019-09-23 14:06:51 +00009167 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) {
9168 llvm::Value *Args[] = {DeviceID, NumIterations};
9169 CGF.EmitRuntimeCall(
9170 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args);
9171 }
Alexey Bataev7bb33532019-01-07 21:30:43 +00009172 };
9173 emitInlinedDirective(CGF, OMPD_unknown, CodeGen);
9174}
9175
Alexey Bataevec7946e2019-09-23 14:06:51 +00009176void CGOpenMPRuntime::emitTargetCall(
9177 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9178 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
9179 const Expr *Device,
9180 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9181 const OMPLoopDirective &D)>
9182 SizeEmitter) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00009183 if (!CGF.HaveInsertPoint())
9184 return;
Samuel Antaobed3c462015-10-02 16:14:20 +00009185
Samuel Antaoee8fb302016-01-06 13:42:12 +00009186 assert(OutlinedFn && "Invalid outlined function!");
9187
Alexey Bataev8451efa2018-01-15 19:06:12 +00009188 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>();
9189 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
Alexey Bataev475a7442018-01-12 19:39:11 +00009190 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009191 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF,
9192 PrePostActionTy &) {
9193 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9194 };
9195 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen);
Samuel Antao86ace552016-04-27 22:40:57 +00009196
Alexey Bataev8451efa2018-01-15 19:06:12 +00009197 CodeGenFunction::OMPTargetDataInfo InputInfo;
9198 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobed3c462015-10-02 16:14:20 +00009199 // Fill up the pointer arrays and transfer execution to the device.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009200 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo,
Alexey Bataevec7946e2019-09-23 14:06:51 +00009201 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars,
9202 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobed3c462015-10-02 16:14:20 +00009203 // On top of the arrays that were filled up, the target offloading call
9204 // takes as arguments the device id as well as the host pointer. The host
9205 // pointer is used by the runtime library to identify the current target
9206 // region, so it only has to be unique and not necessarily point to
9207 // anything. It could be the pointer to the outlined function that
9208 // implements the target region, but we aren't using that so that the
9209 // compiler doesn't need to keep that, and could therefore inline the host
9210 // function if proven worthwhile during optimization.
9211
Samuel Antaoee8fb302016-01-06 13:42:12 +00009212 // From this point on, we need to have an ID of the target region defined.
9213 assert(OutlinedFnID && "Invalid outlined function ID!");
Samuel Antaobed3c462015-10-02 16:14:20 +00009214
9215 // Emit device ID if any.
9216 llvm::Value *DeviceID;
George Rokos63bc9d62017-11-21 18:25:12 +00009217 if (Device) {
Samuel Antaobed3c462015-10-02 16:14:20 +00009218 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009219 CGF.Int64Ty, /*isSigned=*/true);
9220 } else {
9221 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9222 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009223
Samuel Antaodf158d52016-04-27 22:58:19 +00009224 // Emit the number of elements in the offloading arrays.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009225 llvm::Value *PointerNum =
9226 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaodf158d52016-04-27 22:58:19 +00009227
Samuel Antaob68e2db2016-03-03 16:20:23 +00009228 // Return value of the runtime offloading call.
9229 llvm::Value *Return;
9230
Alexey Bataev5c427362019-04-10 19:11:33 +00009231 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D);
9232 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009233
Alexey Bataevec7946e2019-09-23 14:06:51 +00009234 // Emit tripcount for the target loop-based directive.
9235 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter);
9236
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009237 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00009238 // The target region is an outlined function launched by the runtime
9239 // via calls __tgt_target() or __tgt_target_teams().
9240 //
9241 // __tgt_target() launches a target region with one team and one thread,
9242 // executing a serial region. This master thread may in turn launch
9243 // more threads within its team upon encountering a parallel region,
9244 // however, no additional teams can be launched on the device.
9245 //
9246 // __tgt_target_teams() launches a target region with one or more teams,
9247 // each with one or more threads. This call is required for target
9248 // constructs such as:
9249 // 'target teams'
9250 // 'target' / 'teams'
9251 // 'target teams distribute parallel for'
9252 // 'target parallel'
9253 // and so on.
9254 //
9255 // Note that on the host and CPU targets, the runtime implementation of
9256 // these calls simply call the outlined function without forking threads.
9257 // The outlined functions themselves have runtime calls to
9258 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by
9259 // the compiler in emitTeamsCall() and emitParallelCall().
9260 //
9261 // In contrast, on the NVPTX target, the implementation of
9262 // __tgt_target_teams() launches a GPU kernel with the requested number
9263 // of teams and threads so no additional calls to the runtime are required.
Samuel Antaob68e2db2016-03-03 16:20:23 +00009264 if (NumTeams) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00009265 // If we have NumTeams defined this means that we have an enclosed teams
9266 // region. Therefore we also expect to have NumThreads defined. These two
9267 // values should be defined in the presence of a teams directive,
9268 // regardless of having any clauses associated. If the user is using teams
9269 // but no clauses, these two values will be the default that should be
9270 // passed to the runtime library - a 32-bit integer with the value zero.
9271 assert(NumThreads && "Thread limit expression should be available along "
9272 "with number of teams.");
Alexey Bataev8451efa2018-01-15 19:06:12 +00009273 llvm::Value *OffloadingArgs[] = {DeviceID,
9274 OutlinedFnID,
9275 PointerNum,
9276 InputInfo.BasePointersArray.getPointer(),
9277 InputInfo.PointersArray.getPointer(),
9278 InputInfo.SizesArray.getPointer(),
9279 MapTypesArray,
9280 NumTeams,
9281 NumThreads};
Samuel Antaob68e2db2016-03-03 16:20:23 +00009282 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00009283 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait
9284 : OMPRTL__tgt_target_teams),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009285 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009286 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009287 llvm::Value *OffloadingArgs[] = {DeviceID,
9288 OutlinedFnID,
9289 PointerNum,
9290 InputInfo.BasePointersArray.getPointer(),
9291 InputInfo.PointersArray.getPointer(),
9292 InputInfo.SizesArray.getPointer(),
9293 MapTypesArray};
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009294 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00009295 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait
9296 : OMPRTL__tgt_target),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009297 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009298 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009299
Alexey Bataev2a007e02017-10-02 14:20:58 +00009300 // Check the error code and execute the host version if required.
9301 llvm::BasicBlock *OffloadFailedBlock =
9302 CGF.createBasicBlock("omp_offload.failed");
9303 llvm::BasicBlock *OffloadContBlock =
9304 CGF.createBasicBlock("omp_offload.cont");
9305 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return);
9306 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
9307
9308 CGF.EmitBlock(OffloadFailedBlock);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009309 if (RequiresOuterTask) {
9310 CapturedVars.clear();
9311 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9312 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009313 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev2a007e02017-10-02 14:20:58 +00009314 CGF.EmitBranch(OffloadContBlock);
9315
9316 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00009317 };
9318
Samuel Antaoee8fb302016-01-06 13:42:12 +00009319 // Notify that the host version must be executed.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009320 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars,
9321 RequiresOuterTask](CodeGenFunction &CGF,
9322 PrePostActionTy &) {
9323 if (RequiresOuterTask) {
9324 CapturedVars.clear();
9325 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9326 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009327 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009328 };
9329
9330 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray,
9331 &CapturedVars, RequiresOuterTask,
9332 &CS](CodeGenFunction &CGF, PrePostActionTy &) {
9333 // Fill up the arrays with all the captured variables.
9334 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
9335 MappableExprsHandler::MapValuesArrayTy Pointers;
9336 MappableExprsHandler::MapValuesArrayTy Sizes;
9337 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9338
Alexey Bataev8451efa2018-01-15 19:06:12 +00009339 // Get mappable expression information.
9340 MappableExprsHandler MEHandler(D, CGF);
Alexey Bataev969dbc02018-11-08 15:47:39 +00009341 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
Alexey Bataev8451efa2018-01-15 19:06:12 +00009342
9343 auto RI = CS.getCapturedRecordDecl()->field_begin();
9344 auto CV = CapturedVars.begin();
9345 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
9346 CE = CS.capture_end();
9347 CI != CE; ++CI, ++RI, ++CV) {
Alexey Bataevb3638132018-07-19 16:34:13 +00009348 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers;
9349 MappableExprsHandler::MapValuesArrayTy CurPointers;
9350 MappableExprsHandler::MapValuesArrayTy CurSizes;
9351 MappableExprsHandler::MapFlagsArrayTy CurMapTypes;
9352 MappableExprsHandler::StructRangeInfoTy PartialStruct;
Alexey Bataev8451efa2018-01-15 19:06:12 +00009353
9354 // VLA sizes are passed to the outlined region by copy and do not have map
9355 // information associated.
9356 if (CI->capturesVariableArrayType()) {
9357 CurBasePointers.push_back(*CV);
9358 CurPointers.push_back(*CV);
Alexey Bataeva90fc662019-06-25 16:00:43 +00009359 CurSizes.push_back(CGF.Builder.CreateIntCast(
9360 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev8451efa2018-01-15 19:06:12 +00009361 // Copy to the device as an argument. No need to retrieve it.
9362 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL |
Alexey Bataevf288cf92019-06-27 18:53:07 +00009363 MappableExprsHandler::OMP_MAP_TARGET_PARAM |
9364 MappableExprsHandler::OMP_MAP_IMPLICIT);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009365 } else {
9366 // If we have any information in the map clause, we use it, otherwise we
9367 // just do a default mapping.
9368 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00009369 CurSizes, CurMapTypes, PartialStruct);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009370 if (CurBasePointers.empty())
9371 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers,
9372 CurPointers, CurSizes, CurMapTypes);
Alexey Bataev60705422018-10-30 15:50:12 +00009373 // Generate correct mapping for variables captured by reference in
9374 // lambdas.
9375 if (CI->capturesVariable())
Alexey Bataev969dbc02018-11-08 15:47:39 +00009376 MEHandler.generateInfoForLambdaCaptures(
9377 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes,
9378 CurMapTypes, LambdaPointers);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009379 }
9380 // We expect to have at least an element of information for this capture.
9381 assert(!CurBasePointers.empty() &&
9382 "Non-existing map pointer for capture!");
9383 assert(CurBasePointers.size() == CurPointers.size() &&
9384 CurBasePointers.size() == CurSizes.size() &&
9385 CurBasePointers.size() == CurMapTypes.size() &&
9386 "Inconsistent map information sizes!");
9387
Alexey Bataevb3638132018-07-19 16:34:13 +00009388 // If there is an entry in PartialStruct it means we have a struct with
9389 // individual members mapped. Emit an extra combined entry.
9390 if (PartialStruct.Base.isValid())
9391 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes,
9392 CurMapTypes, PartialStruct);
9393
Alexey Bataev8451efa2018-01-15 19:06:12 +00009394 // We need to append the results of this capture to what we already have.
9395 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
9396 Pointers.append(CurPointers.begin(), CurPointers.end());
9397 Sizes.append(CurSizes.begin(), CurSizes.end());
9398 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end());
9399 }
Alexey Bataev60705422018-10-30 15:50:12 +00009400 // Adjust MEMBER_OF flags for the lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00009401 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers,
9402 Pointers, MapTypes);
Alexey Bataev92327c52018-03-26 16:40:55 +00009403 // Map other list items in the map clause which are not captured variables
9404 // but "declare target link" global variables.
Alexey Bataevb3638132018-07-19 16:34:13 +00009405 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes,
9406 MapTypes);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009407
9408 TargetDataInfo Info;
9409 // Fill up the arrays and create the arguments.
9410 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
9411 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
9412 Info.PointersArray, Info.SizesArray,
9413 Info.MapTypesArray, Info);
9414 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
9415 InputInfo.BasePointersArray =
9416 Address(Info.BasePointersArray, CGM.getPointerAlign());
9417 InputInfo.PointersArray =
9418 Address(Info.PointersArray, CGM.getPointerAlign());
9419 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign());
9420 MapTypesArray = Info.MapTypesArray;
9421 if (RequiresOuterTask)
9422 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
9423 else
9424 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
9425 };
9426
9427 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask](
9428 CodeGenFunction &CGF, PrePostActionTy &) {
9429 if (RequiresOuterTask) {
9430 CodeGenFunction::OMPTargetDataInfo InputInfo;
9431 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo);
9432 } else {
9433 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen);
9434 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009435 };
9436
9437 // If we have a target function ID it means that we need to support
9438 // offloading, otherwise, just execute on the host. We need to execute on host
9439 // regardless of the conditional in the if clause if, e.g., the user do not
9440 // specify target triples.
9441 if (OutlinedFnID) {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009442 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -05009443 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009444 } else {
9445 RegionCodeGenTy ThenRCG(TargetThenGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00009446 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00009447 }
9448 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009449 RegionCodeGenTy ElseRCG(TargetElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00009450 ElseRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00009451 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009452}
Samuel Antaoee8fb302016-01-06 13:42:12 +00009453
9454void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
9455 StringRef ParentName) {
9456 if (!S)
9457 return;
9458
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009459 // Codegen OMP target directives that offload compute to the device.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009460 bool RequiresDeviceCodegen =
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009461 isa<OMPExecutableDirective>(S) &&
9462 isOpenMPTargetExecutionDirective(
9463 cast<OMPExecutableDirective>(S)->getDirectiveKind());
Samuel Antaoee8fb302016-01-06 13:42:12 +00009464
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009465 if (RequiresDeviceCodegen) {
9466 const auto &E = *cast<OMPExecutableDirective>(S);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009467 unsigned DeviceID;
9468 unsigned FileID;
9469 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009470 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID,
Samuel Antao2de62b02016-02-13 23:35:10 +00009471 FileID, Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009472
9473 // Is this a target region that should not be emitted as an entry point? If
9474 // so just signal we are done with this target region.
Samuel Antao2de62b02016-02-13 23:35:10 +00009475 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
9476 ParentName, Line))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009477 return;
9478
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009479 switch (E.getDirectiveKind()) {
9480 case OMPD_target:
9481 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName,
9482 cast<OMPTargetDirective>(E));
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009483 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009484 case OMPD_target_parallel:
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009485 CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009486 CGM, ParentName, cast<OMPTargetParallelDirective>(E));
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009487 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009488 case OMPD_target_teams:
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009489 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009490 CGM, ParentName, cast<OMPTargetTeamsDirective>(E));
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009491 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009492 case OMPD_target_teams_distribute:
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009493 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009494 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E));
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009495 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009496 case OMPD_target_teams_distribute_simd:
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009497 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009498 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E));
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009499 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009500 case OMPD_target_parallel_for:
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009501 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009502 CGM, ParentName, cast<OMPTargetParallelForDirective>(E));
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009503 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009504 case OMPD_target_parallel_for_simd:
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009505 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009506 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E));
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009507 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009508 case OMPD_target_simd:
Alexey Bataevf8365372017-11-17 17:57:25 +00009509 CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009510 CGM, ParentName, cast<OMPTargetSimdDirective>(E));
Alexey Bataevf8365372017-11-17 17:57:25 +00009511 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009512 case OMPD_target_teams_distribute_parallel_for:
Carlo Bertolli52978c32018-01-03 21:12:44 +00009513 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
9514 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009515 cast<OMPTargetTeamsDistributeParallelForDirective>(E));
Carlo Bertolli52978c32018-01-03 21:12:44 +00009516 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009517 case OMPD_target_teams_distribute_parallel_for_simd:
Alexey Bataev647dd842018-01-15 20:59:40 +00009518 CodeGenFunction::
9519 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
9520 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009521 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E));
Alexey Bataev647dd842018-01-15 20:59:40 +00009522 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009523 case OMPD_parallel:
9524 case OMPD_for:
9525 case OMPD_parallel_for:
9526 case OMPD_parallel_sections:
9527 case OMPD_for_simd:
9528 case OMPD_parallel_for_simd:
9529 case OMPD_cancel:
9530 case OMPD_cancellation_point:
9531 case OMPD_ordered:
9532 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00009533 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009534 case OMPD_task:
9535 case OMPD_simd:
9536 case OMPD_sections:
9537 case OMPD_section:
9538 case OMPD_single:
9539 case OMPD_master:
9540 case OMPD_critical:
9541 case OMPD_taskyield:
9542 case OMPD_barrier:
9543 case OMPD_taskwait:
9544 case OMPD_taskgroup:
9545 case OMPD_atomic:
9546 case OMPD_flush:
9547 case OMPD_teams:
9548 case OMPD_target_data:
9549 case OMPD_target_exit_data:
9550 case OMPD_target_enter_data:
9551 case OMPD_distribute:
9552 case OMPD_distribute_simd:
9553 case OMPD_distribute_parallel_for:
9554 case OMPD_distribute_parallel_for_simd:
9555 case OMPD_teams_distribute:
9556 case OMPD_teams_distribute_simd:
9557 case OMPD_teams_distribute_parallel_for:
9558 case OMPD_teams_distribute_parallel_for_simd:
9559 case OMPD_target_update:
9560 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00009561 case OMPD_declare_variant:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009562 case OMPD_declare_target:
9563 case OMPD_end_declare_target:
9564 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00009565 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009566 case OMPD_taskloop:
9567 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00009568 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00009569 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00009570 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04009571 case OMPD_parallel_master_taskloop_simd:
Kelvin Li1408f912018-09-26 04:28:39 +00009572 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009573 case OMPD_unknown:
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009574 llvm_unreachable("Unknown target directive for OpenMP device codegen.");
9575 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009576 return;
9577 }
9578
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009579 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
Alexey Bataev475a7442018-01-12 19:39:11 +00009580 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009581 return;
9582
9583 scanForTargetRegionsFunctions(
Alexey Bataev475a7442018-01-12 19:39:11 +00009584 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009585 return;
9586 }
9587
9588 // If this is a lambda function, look into its body.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009589 if (const auto *L = dyn_cast<LambdaExpr>(S))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009590 S = L->getBody();
9591
9592 // Keep looking for target regions recursively.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009593 for (const Stmt *II : S->children())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009594 scanForTargetRegionsFunctions(II, ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009595}
9596
9597bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009598 // If emitting code for the host, we do not process FD here. Instead we do
9599 // the normal code generation.
Alexey Bataev729e2422019-08-23 16:11:14 +00009600 if (!CGM.getLangOpts().OpenMPIsDevice) {
9601 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) {
9602 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9603 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9604 // Do not emit device_type(nohost) functions for the host.
9605 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
9606 return true;
9607 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009608 return false;
Alexey Bataev729e2422019-08-23 16:11:14 +00009609 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009610
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009611 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009612 StringRef Name = CGM.getMangledName(GD);
9613 // Try to detect target regions in the function.
Alexey Bataev729e2422019-08-23 16:11:14 +00009614 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009615 scanForTargetRegionsFunctions(FD->getBody(), Name);
Alexey Bataev729e2422019-08-23 16:11:14 +00009616 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9617 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9618 // Do not emit device_type(nohost) functions for the host.
9619 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
9620 return true;
9621 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009622
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009623 // Do not to emit function if it is not marked as declare target.
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009624 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009625 AlreadyEmittedTargetFunctions.count(Name) == 0;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009626}
9627
9628bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
9629 if (!CGM.getLangOpts().OpenMPIsDevice)
9630 return false;
9631
9632 // Check if there are Ctors/Dtors in this declaration and look for target
9633 // regions in it. We use the complete variant to produce the kernel name
9634 // mangling.
9635 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009636 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
9637 for (const CXXConstructorDecl *Ctor : RD->ctors()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009638 StringRef ParentName =
9639 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
9640 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
9641 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009642 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009643 StringRef ParentName =
9644 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
9645 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
9646 }
9647 }
9648
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009649 // Do not to emit variable if it is not marked as declare target.
Alexey Bataev92327c52018-03-26 16:40:55 +00009650 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009651 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
9652 cast<VarDecl>(GD.getDecl()));
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009653 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
9654 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9655 HasRequiresUnifiedSharedMemory)) {
Alexey Bataevd01b7492018-08-15 19:45:12 +00009656 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009657 return true;
9658 }
9659 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009660}
9661
Alexey Bataev1af5bd52019-03-05 17:47:18 +00009662llvm::Constant *
9663CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF,
9664 const VarDecl *VD) {
9665 assert(VD->getType().isConstant(CGM.getContext()) &&
9666 "Expected constant variable.");
9667 StringRef VarName;
9668 llvm::Constant *Addr;
9669 llvm::GlobalValue::LinkageTypes Linkage;
9670 QualType Ty = VD->getType();
9671 SmallString<128> Buffer;
9672 {
9673 unsigned DeviceID;
9674 unsigned FileID;
9675 unsigned Line;
9676 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID,
9677 FileID, Line);
9678 llvm::raw_svector_ostream OS(Buffer);
9679 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID)
9680 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
9681 VarName = OS.str();
9682 }
9683 Linkage = llvm::GlobalValue::InternalLinkage;
9684 Addr =
9685 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName,
9686 getDefaultFirstprivateAddressSpace());
9687 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage);
9688 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty);
9689 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr));
9690 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9691 VarName, Addr, VarSize,
9692 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage);
9693 return Addr;
9694}
9695
Alexey Bataev03f270c2018-03-30 18:31:07 +00009696void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
9697 llvm::Constant *Addr) {
Alexey Bataev36724b72019-10-03 16:46:49 +00009698 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
9699 !CGM.getLangOpts().OpenMPIsDevice)
Alexey Bataev4db9dc62019-09-23 15:53:51 +00009700 return;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009701 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9702 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
9703 if (!Res) {
9704 if (CGM.getLangOpts().OpenMPIsDevice) {
9705 // Register non-target variables being emitted in device code (debug info
9706 // may cause this).
9707 StringRef VarName = CGM.getMangledName(VD);
9708 EmittedNonTargetVariables.try_emplace(VarName, Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009709 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009710 return;
Alexey Bataev03f270c2018-03-30 18:31:07 +00009711 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009712 // Register declare target variables.
9713 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
9714 StringRef VarName;
9715 CharUnits VarSize;
9716 llvm::GlobalValue::LinkageTypes Linkage;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009717
9718 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9719 !HasRequiresUnifiedSharedMemory) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009720 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9721 VarName = CGM.getMangledName(VD);
9722 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) {
9723 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType());
9724 assert(!VarSize.isZero() && "Expected non-zero size of the variable");
9725 } else {
9726 VarSize = CharUnits::Zero();
9727 }
9728 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
9729 // Temp solution to prevent optimizations of the internal variables.
9730 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) {
9731 std::string RefName = getName({VarName, "ref"});
9732 if (!CGM.GetGlobalValue(RefName)) {
9733 llvm::Constant *AddrRef =
9734 getOrCreateInternalVariable(Addr->getType(), RefName);
9735 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef);
9736 GVAddrRef->setConstant(/*Val=*/true);
9737 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage);
9738 GVAddrRef->setInitializer(Addr);
9739 CGM.addCompilerUsedGlobal(GVAddrRef);
9740 }
9741 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009742 } else {
9743 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
9744 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9745 HasRequiresUnifiedSharedMemory)) &&
9746 "Declare target attribute must link or to with unified memory.");
9747 if (*Res == OMPDeclareTargetDeclAttr::MT_Link)
9748 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink;
9749 else
9750 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9751
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009752 if (CGM.getLangOpts().OpenMPIsDevice) {
9753 VarName = Addr->getName();
9754 Addr = nullptr;
9755 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009756 VarName = getAddrOfDeclareTargetVar(VD).getName();
9757 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009758 }
9759 VarSize = CGM.getPointerSize();
9760 Linkage = llvm::GlobalValue::WeakAnyLinkage;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009761 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009762
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009763 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9764 VarName, Addr, VarSize, Flags, Linkage);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009765}
9766
Samuel Antaoee8fb302016-01-06 13:42:12 +00009767bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009768 if (isa<FunctionDecl>(GD.getDecl()) ||
9769 isa<OMPDeclareReductionDecl>(GD.getDecl()))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009770 return emitTargetFunctions(GD);
9771
9772 return emitTargetGlobalVariable(GD);
9773}
9774
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009775void CGOpenMPRuntime::emitDeferredTargetDecls() const {
9776 for (const VarDecl *VD : DeferredGlobalVariables) {
9777 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009778 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009779 if (!Res)
9780 continue;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009781 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9782 !HasRequiresUnifiedSharedMemory) {
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009783 CGM.EmitGlobal(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009784 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009785 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
9786 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9787 HasRequiresUnifiedSharedMemory)) &&
9788 "Expected link clause or to clause with unified memory.");
9789 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009790 }
9791 }
9792}
9793
Alexey Bataev60705422018-10-30 15:50:12 +00009794void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas(
9795 CodeGenFunction &CGF, const OMPExecutableDirective &D) const {
9796 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) &&
9797 " Expected target-based directive.");
9798}
9799
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009800void CGOpenMPRuntime::checkArchForUnifiedAddressing(
9801 const OMPRequiresDecl *D) {
9802 for (const OMPClause *Clause : D->clauselists()) {
9803 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
9804 HasRequiresUnifiedSharedMemory = true;
9805 break;
9806 }
9807 }
9808}
9809
Alexey Bataevc5687252019-03-21 19:35:27 +00009810bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD,
9811 LangAS &AS) {
9812 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())
9813 return false;
9814 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
9815 switch(A->getAllocatorType()) {
9816 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
9817 // Not supported, fallback to the default mem space.
9818 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
9819 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
9820 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
9821 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
9822 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
9823 case OMPAllocateDeclAttr::OMPConstMemAlloc:
9824 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
9825 AS = LangAS::Default;
9826 return true;
9827 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
9828 llvm_unreachable("Expected predefined allocator for the variables with the "
9829 "static storage.");
9830 }
9831 return false;
9832}
9833
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00009834bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const {
9835 return HasRequiresUnifiedSharedMemory;
9836}
9837
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009838CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
9839 CodeGenModule &CGM)
9840 : CGM(CGM) {
9841 if (CGM.getLangOpts().OpenMPIsDevice) {
9842 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
9843 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
9844 }
9845}
9846
9847CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() {
9848 if (CGM.getLangOpts().OpenMPIsDevice)
9849 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
9850}
9851
Alexey Bataev6d944102018-05-02 15:45:28 +00009852bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009853 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal)
9854 return true;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009855
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009856 StringRef Name = CGM.getMangledName(GD);
Alexey Bataev6d944102018-05-02 15:45:28 +00009857 const auto *D = cast<FunctionDecl>(GD.getDecl());
Alexey Bataev34f8a702018-03-28 14:28:54 +00009858 // Do not to emit function if it is marked as declare target as it was already
9859 // emitted.
Alexey Bataev97b72212018-08-14 18:31:20 +00009860 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009861 if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) {
9862 if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name)))
Alexey Bataev34f8a702018-03-28 14:28:54 +00009863 return !F->isDeclaration();
9864 return false;
9865 }
9866 return true;
9867 }
9868
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009869 return !AlreadyEmittedTargetFunctions.insert(Name).second;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009870}
9871
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009872llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() {
9873 // If we don't have entries or if we are emitting code for the device, we
9874 // don't need to do anything.
9875 if (CGM.getLangOpts().OMPTargetTriples.empty() ||
9876 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice ||
9877 (OffloadEntriesInfoManager.empty() &&
9878 !HasEmittedDeclareTargetRegion &&
9879 !HasEmittedTargetRegion))
9880 return nullptr;
9881
9882 // Create and register the function that handles the requires directives.
9883 ASTContext &C = CGM.getContext();
9884
9885 llvm::Function *RequiresRegFn;
9886 {
9887 CodeGenFunction CGF(CGM);
9888 const auto &FI = CGM.getTypes().arrangeNullaryFunction();
9889 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
9890 std::string ReqName = getName({"omp_offloading", "requires_reg"});
9891 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI);
9892 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {});
9893 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE;
9894 // TODO: check for other requires clauses.
9895 // The requires directive takes effect only when a target region is
9896 // present in the compilation unit. Otherwise it is ignored and not
9897 // passed to the runtime. This avoids the runtime from throwing an error
9898 // for mismatching requires clauses across compilation units that don't
9899 // contain at least 1 target region.
9900 assert((HasEmittedTargetRegion ||
9901 HasEmittedDeclareTargetRegion ||
9902 !OffloadEntriesInfoManager.empty()) &&
9903 "Target or declare target region expected.");
9904 if (HasRequiresUnifiedSharedMemory)
9905 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY;
9906 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires),
9907 llvm::ConstantInt::get(CGM.Int64Ty, Flags));
9908 CGF.FinishFunction();
9909 }
9910 return RequiresRegFn;
9911}
9912
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009913void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
9914 const OMPExecutableDirective &D,
9915 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00009916 llvm::Function *OutlinedFn,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009917 ArrayRef<llvm::Value *> CapturedVars) {
9918 if (!CGF.HaveInsertPoint())
9919 return;
9920
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009921 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009922 CodeGenFunction::RunCleanupsScope Scope(CGF);
9923
9924 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
9925 llvm::Value *Args[] = {
9926 RTLoc,
9927 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
9928 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
9929 llvm::SmallVector<llvm::Value *, 16> RealArgs;
9930 RealArgs.append(std::begin(Args), std::end(Args));
9931 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
9932
James Y Knight9871db02019-02-05 16:42:33 +00009933 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009934 CGF.EmitRuntimeCall(RTLFn, RealArgs);
9935}
9936
9937void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
Carlo Bertollic6872252016-04-04 15:55:02 +00009938 const Expr *NumTeams,
9939 const Expr *ThreadLimit,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009940 SourceLocation Loc) {
9941 if (!CGF.HaveInsertPoint())
9942 return;
9943
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009944 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009945
Carlo Bertollic6872252016-04-04 15:55:02 +00009946 llvm::Value *NumTeamsVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009947 NumTeams
Carlo Bertollic6872252016-04-04 15:55:02 +00009948 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
9949 CGF.CGM.Int32Ty, /* isSigned = */ true)
9950 : CGF.Builder.getInt32(0);
9951
9952 llvm::Value *ThreadLimitVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009953 ThreadLimit
Carlo Bertollic6872252016-04-04 15:55:02 +00009954 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
9955 CGF.CGM.Int32Ty, /* isSigned = */ true)
9956 : CGF.Builder.getInt32(0);
9957
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009958 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
Carlo Bertollic6872252016-04-04 15:55:02 +00009959 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
9960 ThreadLimitVal};
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009961 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams),
9962 PushNumTeamsArgs);
9963}
Samuel Antaodf158d52016-04-27 22:58:19 +00009964
Samuel Antaocc10b852016-07-28 14:23:26 +00009965void CGOpenMPRuntime::emitTargetDataCalls(
9966 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
9967 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009968 if (!CGF.HaveInsertPoint())
9969 return;
9970
Samuel Antaocc10b852016-07-28 14:23:26 +00009971 // Action used to replace the default codegen action and turn privatization
9972 // off.
9973 PrePostActionTy NoPrivAction;
Samuel Antaodf158d52016-04-27 22:58:19 +00009974
9975 // Generate the code for the opening of the data environment. Capture all the
9976 // arguments of the runtime call by reference because they are used in the
9977 // closing of the region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009978 auto &&BeginThenGen = [this, &D, Device, &Info,
9979 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009980 // Fill up the arrays with all the mapped variables.
Samuel Antaocc10b852016-07-28 14:23:26 +00009981 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
Samuel Antaodf158d52016-04-27 22:58:19 +00009982 MappableExprsHandler::MapValuesArrayTy Pointers;
9983 MappableExprsHandler::MapValuesArrayTy Sizes;
9984 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9985
9986 // Get map clause information.
9987 MappableExprsHandler MCHandler(D, CGF);
9988 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
Samuel Antaodf158d52016-04-27 22:58:19 +00009989
9990 // Fill up the arrays and create the arguments.
Samuel Antaocc10b852016-07-28 14:23:26 +00009991 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +00009992
9993 llvm::Value *BasePointersArrayArg = nullptr;
9994 llvm::Value *PointersArrayArg = nullptr;
9995 llvm::Value *SizesArrayArg = nullptr;
9996 llvm::Value *MapTypesArrayArg = nullptr;
9997 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00009998 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +00009999
10000 // Emit device ID if any.
10001 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010002 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +000010003 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010004 CGF.Int64Ty, /*isSigned=*/true);
10005 } else {
10006 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10007 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010008
10009 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010010 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +000010011
10012 llvm::Value *OffloadingArgs[] = {
10013 DeviceID, PointerNum, BasePointersArrayArg,
10014 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010015 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin),
Samuel Antaodf158d52016-04-27 22:58:19 +000010016 OffloadingArgs);
Samuel Antaocc10b852016-07-28 14:23:26 +000010017
10018 // If device pointer privatization is required, emit the body of the region
10019 // here. It will have to be duplicated: with and without privatization.
10020 if (!Info.CaptureDeviceAddrMap.empty())
10021 CodeGen(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010022 };
10023
10024 // Generate code for the closing of the data region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010025 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF,
10026 PrePostActionTy &) {
Samuel Antaocc10b852016-07-28 14:23:26 +000010027 assert(Info.isValid() && "Invalid data environment closing arguments.");
Samuel Antaodf158d52016-04-27 22:58:19 +000010028
10029 llvm::Value *BasePointersArrayArg = nullptr;
10030 llvm::Value *PointersArrayArg = nullptr;
10031 llvm::Value *SizesArrayArg = nullptr;
10032 llvm::Value *MapTypesArrayArg = nullptr;
10033 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +000010034 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +000010035
10036 // Emit device ID if any.
10037 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010038 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +000010039 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010040 CGF.Int64Ty, /*isSigned=*/true);
10041 } else {
10042 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10043 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010044
10045 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010046 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +000010047
10048 llvm::Value *OffloadingArgs[] = {
10049 DeviceID, PointerNum, BasePointersArrayArg,
10050 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010051 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end),
Samuel Antaodf158d52016-04-27 22:58:19 +000010052 OffloadingArgs);
10053 };
10054
Samuel Antaocc10b852016-07-28 14:23:26 +000010055 // If we need device pointer privatization, we need to emit the body of the
10056 // region with no privatization in the 'else' branch of the conditional.
10057 // Otherwise, we don't have to do anything.
10058 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF,
10059 PrePostActionTy &) {
10060 if (!Info.CaptureDeviceAddrMap.empty()) {
10061 CodeGen.setAction(NoPrivAction);
10062 CodeGen(CGF);
10063 }
10064 };
10065
10066 // We don't have to do anything to close the region if the if clause evaluates
10067 // to false.
10068 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
Samuel Antaodf158d52016-04-27 22:58:19 +000010069
10070 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -050010071 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +000010072 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +000010073 RegionCodeGenTy RCG(BeginThenGen);
10074 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010075 }
10076
Samuel Antaocc10b852016-07-28 14:23:26 +000010077 // If we don't require privatization of device pointers, we emit the body in
10078 // between the runtime calls. This avoids duplicating the body code.
10079 if (Info.CaptureDeviceAddrMap.empty()) {
10080 CodeGen.setAction(NoPrivAction);
10081 CodeGen(CGF);
10082 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010083
10084 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -050010085 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +000010086 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +000010087 RegionCodeGenTy RCG(EndThenGen);
10088 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010089 }
10090}
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010091
Samuel Antao8d2d7302016-05-26 18:30:22 +000010092void CGOpenMPRuntime::emitTargetDataStandAloneCall(
Samuel Antao8dd66282016-04-27 23:14:30 +000010093 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10094 const Expr *Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010095 if (!CGF.HaveInsertPoint())
10096 return;
10097
Samuel Antao8dd66282016-04-27 23:14:30 +000010098 assert((isa<OMPTargetEnterDataDirective>(D) ||
Samuel Antao8d2d7302016-05-26 18:30:22 +000010099 isa<OMPTargetExitDataDirective>(D) ||
10100 isa<OMPTargetUpdateDirective>(D)) &&
10101 "Expecting either target enter, exit data, or update directives.");
Samuel Antao8dd66282016-04-27 23:14:30 +000010102
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010103 CodeGenFunction::OMPTargetDataInfo InputInfo;
10104 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010105 // Generate the code for the opening of the data environment.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010106 auto &&ThenGen = [this, &D, Device, &InputInfo,
10107 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010108 // Emit device ID if any.
10109 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010110 if (Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010111 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010112 CGF.Int64Ty, /*isSigned=*/true);
10113 } else {
10114 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10115 }
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010116
10117 // Emit the number of elements in the offloading arrays.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010118 llvm::Constant *PointerNum =
10119 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010120
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010121 llvm::Value *OffloadingArgs[] = {DeviceID,
10122 PointerNum,
10123 InputInfo.BasePointersArray.getPointer(),
10124 InputInfo.PointersArray.getPointer(),
10125 InputInfo.SizesArray.getPointer(),
10126 MapTypesArray};
Samuel Antao8d2d7302016-05-26 18:30:22 +000010127
Samuel Antao8d2d7302016-05-26 18:30:22 +000010128 // Select the right runtime function call for each expected standalone
10129 // directive.
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010130 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Samuel Antao8d2d7302016-05-26 18:30:22 +000010131 OpenMPRTLFunction RTLFn;
10132 switch (D.getDirectiveKind()) {
Samuel Antao8d2d7302016-05-26 18:30:22 +000010133 case OMPD_target_enter_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010134 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait
10135 : OMPRTL__tgt_target_data_begin;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010136 break;
10137 case OMPD_target_exit_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010138 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait
10139 : OMPRTL__tgt_target_data_end;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010140 break;
10141 case OMPD_target_update:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010142 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait
10143 : OMPRTL__tgt_target_data_update;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010144 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010145 case OMPD_parallel:
10146 case OMPD_for:
10147 case OMPD_parallel_for:
10148 case OMPD_parallel_sections:
10149 case OMPD_for_simd:
10150 case OMPD_parallel_for_simd:
10151 case OMPD_cancel:
10152 case OMPD_cancellation_point:
10153 case OMPD_ordered:
10154 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +000010155 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010156 case OMPD_task:
10157 case OMPD_simd:
10158 case OMPD_sections:
10159 case OMPD_section:
10160 case OMPD_single:
10161 case OMPD_master:
10162 case OMPD_critical:
10163 case OMPD_taskyield:
10164 case OMPD_barrier:
10165 case OMPD_taskwait:
10166 case OMPD_taskgroup:
10167 case OMPD_atomic:
10168 case OMPD_flush:
10169 case OMPD_teams:
10170 case OMPD_target_data:
10171 case OMPD_distribute:
10172 case OMPD_distribute_simd:
10173 case OMPD_distribute_parallel_for:
10174 case OMPD_distribute_parallel_for_simd:
10175 case OMPD_teams_distribute:
10176 case OMPD_teams_distribute_simd:
10177 case OMPD_teams_distribute_parallel_for:
10178 case OMPD_teams_distribute_parallel_for_simd:
10179 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +000010180 case OMPD_declare_variant:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010181 case OMPD_declare_target:
10182 case OMPD_end_declare_target:
10183 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +000010184 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010185 case OMPD_taskloop:
10186 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +000010187 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +000010188 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +000010189 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -040010190 case OMPD_parallel_master_taskloop_simd:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010191 case OMPD_target:
10192 case OMPD_target_simd:
10193 case OMPD_target_teams_distribute:
10194 case OMPD_target_teams_distribute_simd:
10195 case OMPD_target_teams_distribute_parallel_for:
10196 case OMPD_target_teams_distribute_parallel_for_simd:
10197 case OMPD_target_teams:
10198 case OMPD_target_parallel:
10199 case OMPD_target_parallel_for:
10200 case OMPD_target_parallel_for_simd:
Kelvin Li1408f912018-09-26 04:28:39 +000010201 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010202 case OMPD_unknown:
10203 llvm_unreachable("Unexpected standalone target data directive.");
10204 break;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010205 }
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010206 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010207 };
10208
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010209 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray](
10210 CodeGenFunction &CGF, PrePostActionTy &) {
10211 // Fill up the arrays with all the mapped variables.
10212 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
10213 MappableExprsHandler::MapValuesArrayTy Pointers;
10214 MappableExprsHandler::MapValuesArrayTy Sizes;
10215 MappableExprsHandler::MapFlagsArrayTy MapTypes;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010216
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010217 // Get map clause information.
10218 MappableExprsHandler MEHandler(D, CGF);
10219 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
10220
10221 TargetDataInfo Info;
10222 // Fill up the arrays and create the arguments.
10223 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
10224 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
10225 Info.PointersArray, Info.SizesArray,
10226 Info.MapTypesArray, Info);
10227 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
10228 InputInfo.BasePointersArray =
10229 Address(Info.BasePointersArray, CGM.getPointerAlign());
10230 InputInfo.PointersArray =
10231 Address(Info.PointersArray, CGM.getPointerAlign());
10232 InputInfo.SizesArray =
10233 Address(Info.SizesArray, CGM.getPointerAlign());
10234 MapTypesArray = Info.MapTypesArray;
10235 if (D.hasClausesOfKind<OMPDependClause>())
10236 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
10237 else
Alexey Bataev768f1f22018-01-09 19:59:25 +000010238 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010239 };
10240
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010241 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -050010242 emitIfClause(CGF, IfCond, TargetThenGen,
10243 [](CodeGenFunction &CGF, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010244 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010245 RegionCodeGenTy ThenRCG(TargetThenGen);
10246 ThenRCG(CGF);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010247 }
10248}
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010249
10250namespace {
10251 /// Kind of parameter in a function with 'declare simd' directive.
10252 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector };
10253 /// Attribute set of the parameter.
10254 struct ParamAttrTy {
10255 ParamKindTy Kind = Vector;
10256 llvm::APSInt StrideOrArg;
10257 llvm::APSInt Alignment;
10258 };
10259} // namespace
10260
10261static unsigned evaluateCDTSize(const FunctionDecl *FD,
10262 ArrayRef<ParamAttrTy> ParamAttrs) {
10263 // Every vector variant of a SIMD-enabled function has a vector length (VLEN).
10264 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument
10265 // of that clause. The VLEN value must be power of 2.
10266 // In other case the notion of the function`s "characteristic data type" (CDT)
10267 // is used to compute the vector length.
10268 // CDT is defined in the following order:
10269 // a) For non-void function, the CDT is the return type.
10270 // b) If the function has any non-uniform, non-linear parameters, then the
10271 // CDT is the type of the first such parameter.
10272 // c) If the CDT determined by a) or b) above is struct, union, or class
10273 // type which is pass-by-value (except for the type that maps to the
10274 // built-in complex data type), the characteristic data type is int.
10275 // d) If none of the above three cases is applicable, the CDT is int.
10276 // The VLEN is then determined based on the CDT and the size of vector
10277 // register of that ISA for which current vector version is generated. The
10278 // VLEN is computed using the formula below:
10279 // VLEN = sizeof(vector_register) / sizeof(CDT),
10280 // where vector register size specified in section 3.2.1 Registers and the
10281 // Stack Frame of original AMD64 ABI document.
10282 QualType RetType = FD->getReturnType();
10283 if (RetType.isNull())
10284 return 0;
10285 ASTContext &C = FD->getASTContext();
10286 QualType CDT;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010287 if (!RetType.isNull() && !RetType->isVoidType()) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010288 CDT = RetType;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010289 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010290 unsigned Offset = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010291 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010292 if (ParamAttrs[Offset].Kind == Vector)
10293 CDT = C.getPointerType(C.getRecordType(MD->getParent()));
10294 ++Offset;
10295 }
10296 if (CDT.isNull()) {
10297 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10298 if (ParamAttrs[I + Offset].Kind == Vector) {
10299 CDT = FD->getParamDecl(I)->getType();
10300 break;
10301 }
10302 }
10303 }
10304 }
10305 if (CDT.isNull())
10306 CDT = C.IntTy;
10307 CDT = CDT->getCanonicalTypeUnqualified();
10308 if (CDT->isRecordType() || CDT->isUnionType())
10309 CDT = C.IntTy;
10310 return C.getTypeSize(CDT);
10311}
10312
10313static void
10314emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
Benjamin Kramer81cb4b72016-11-24 16:01:20 +000010315 const llvm::APSInt &VLENVal,
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010316 ArrayRef<ParamAttrTy> ParamAttrs,
10317 OMPDeclareSimdDeclAttr::BranchStateTy State) {
10318 struct ISADataTy {
10319 char ISA;
10320 unsigned VecRegSize;
10321 };
10322 ISADataTy ISAData[] = {
10323 {
10324 'b', 128
10325 }, // SSE
10326 {
10327 'c', 256
10328 }, // AVX
10329 {
10330 'd', 256
10331 }, // AVX2
10332 {
10333 'e', 512
10334 }, // AVX512
10335 };
10336 llvm::SmallVector<char, 2> Masked;
10337 switch (State) {
10338 case OMPDeclareSimdDeclAttr::BS_Undefined:
10339 Masked.push_back('N');
10340 Masked.push_back('M');
10341 break;
10342 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10343 Masked.push_back('N');
10344 break;
10345 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10346 Masked.push_back('M');
10347 break;
10348 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010349 for (char Mask : Masked) {
10350 for (const ISADataTy &Data : ISAData) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010351 SmallString<256> Buffer;
10352 llvm::raw_svector_ostream Out(Buffer);
10353 Out << "_ZGV" << Data.ISA << Mask;
10354 if (!VLENVal) {
Simon Pilgrim823a99c2019-05-22 13:02:19 +000010355 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs);
10356 assert(NumElts && "Non-zero simdlen/cdtsize expected");
10357 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010358 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010359 Out << VLENVal;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010360 }
10361 for (const ParamAttrTy &ParamAttr : ParamAttrs) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010362 switch (ParamAttr.Kind){
10363 case LinearWithVarStride:
10364 Out << 's' << ParamAttr.StrideOrArg;
10365 break;
10366 case Linear:
10367 Out << 'l';
10368 if (!!ParamAttr.StrideOrArg)
10369 Out << ParamAttr.StrideOrArg;
10370 break;
10371 case Uniform:
10372 Out << 'u';
10373 break;
10374 case Vector:
10375 Out << 'v';
10376 break;
10377 }
10378 if (!!ParamAttr.Alignment)
10379 Out << 'a' << ParamAttr.Alignment;
10380 }
10381 Out << '_' << Fn->getName();
10382 Fn->addFnAttr(Out.str());
10383 }
10384 }
10385}
10386
Alexey Bataeva0a22642019-04-16 13:56:21 +000010387// This are the Functions that are needed to mangle the name of the
10388// vector functions generated by the compiler, according to the rules
10389// defined in the "Vector Function ABI specifications for AArch64",
10390// available at
10391// https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi.
10392
10393/// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI.
10394///
10395/// TODO: Need to implement the behavior for reference marked with a
10396/// var or no linear modifiers (1.b in the section). For this, we
10397/// need to extend ParamKindTy to support the linear modifiers.
10398static bool getAArch64MTV(QualType QT, ParamKindTy Kind) {
10399 QT = QT.getCanonicalType();
10400
10401 if (QT->isVoidType())
10402 return false;
10403
10404 if (Kind == ParamKindTy::Uniform)
10405 return false;
10406
10407 if (Kind == ParamKindTy::Linear)
10408 return false;
10409
10410 // TODO: Handle linear references with modifiers
10411
10412 if (Kind == ParamKindTy::LinearWithVarStride)
10413 return false;
10414
10415 return true;
10416}
10417
10418/// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
10419static bool getAArch64PBV(QualType QT, ASTContext &C) {
10420 QT = QT.getCanonicalType();
10421 unsigned Size = C.getTypeSize(QT);
10422
10423 // Only scalars and complex within 16 bytes wide set PVB to true.
10424 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
10425 return false;
10426
10427 if (QT->isFloatingType())
10428 return true;
10429
10430 if (QT->isIntegerType())
10431 return true;
10432
10433 if (QT->isPointerType())
10434 return true;
10435
10436 // TODO: Add support for complex types (section 3.1.2, item 2).
10437
10438 return false;
10439}
10440
10441/// Computes the lane size (LS) of a return type or of an input parameter,
10442/// as defined by `LS(P)` in 3.2.1 of the AAVFABI.
10443/// TODO: Add support for references, section 3.2.1, item 1.
10444static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) {
10445 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) {
10446 QualType PTy = QT.getCanonicalType()->getPointeeType();
10447 if (getAArch64PBV(PTy, C))
10448 return C.getTypeSize(PTy);
10449 }
10450 if (getAArch64PBV(QT, C))
10451 return C.getTypeSize(QT);
10452
10453 return C.getTypeSize(C.getUIntPtrType());
10454}
10455
10456// Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the
10457// signature of the scalar function, as defined in 3.2.2 of the
10458// AAVFABI.
10459static std::tuple<unsigned, unsigned, bool>
10460getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) {
10461 QualType RetType = FD->getReturnType().getCanonicalType();
10462
10463 ASTContext &C = FD->getASTContext();
10464
10465 bool OutputBecomesInput = false;
10466
10467 llvm::SmallVector<unsigned, 8> Sizes;
10468 if (!RetType->isVoidType()) {
10469 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C));
10470 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {}))
10471 OutputBecomesInput = true;
10472 }
10473 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10474 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType();
10475 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C));
10476 }
10477
10478 assert(!Sizes.empty() && "Unable to determine NDS and WDS.");
10479 // The LS of a function parameter / return value can only be a power
10480 // of 2, starting from 8 bits, up to 128.
10481 assert(std::all_of(Sizes.begin(), Sizes.end(),
10482 [](unsigned Size) {
10483 return Size == 8 || Size == 16 || Size == 32 ||
10484 Size == 64 || Size == 128;
10485 }) &&
10486 "Invalid size");
10487
10488 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)),
10489 *std::max_element(std::begin(Sizes), std::end(Sizes)),
10490 OutputBecomesInput);
10491}
10492
10493/// Mangle the parameter part of the vector function name according to
10494/// their OpenMP classification. The mangling function is defined in
10495/// section 3.5 of the AAVFABI.
10496static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) {
10497 SmallString<256> Buffer;
10498 llvm::raw_svector_ostream Out(Buffer);
10499 for (const auto &ParamAttr : ParamAttrs) {
10500 switch (ParamAttr.Kind) {
10501 case LinearWithVarStride:
10502 Out << "ls" << ParamAttr.StrideOrArg;
10503 break;
10504 case Linear:
10505 Out << 'l';
10506 // Don't print the step value if it is not present or if it is
10507 // equal to 1.
10508 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1)
10509 Out << ParamAttr.StrideOrArg;
10510 break;
10511 case Uniform:
10512 Out << 'u';
10513 break;
10514 case Vector:
10515 Out << 'v';
10516 break;
10517 }
10518
10519 if (!!ParamAttr.Alignment)
10520 Out << 'a' << ParamAttr.Alignment;
10521 }
10522
10523 return Out.str();
10524}
10525
10526// Function used to add the attribute. The parameter `VLEN` is
10527// templated to allow the use of "x" when targeting scalable functions
10528// for SVE.
10529template <typename T>
10530static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix,
10531 char ISA, StringRef ParSeq,
10532 StringRef MangledName, bool OutputBecomesInput,
10533 llvm::Function *Fn) {
10534 SmallString<256> Buffer;
10535 llvm::raw_svector_ostream Out(Buffer);
10536 Out << Prefix << ISA << LMask << VLEN;
10537 if (OutputBecomesInput)
10538 Out << "v";
10539 Out << ParSeq << "_" << MangledName;
10540 Fn->addFnAttr(Out.str());
10541}
10542
10543// Helper function to generate the Advanced SIMD names depending on
10544// the value of the NDS when simdlen is not present.
10545static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask,
10546 StringRef Prefix, char ISA,
10547 StringRef ParSeq, StringRef MangledName,
10548 bool OutputBecomesInput,
10549 llvm::Function *Fn) {
10550 switch (NDS) {
10551 case 8:
10552 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10553 OutputBecomesInput, Fn);
10554 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName,
10555 OutputBecomesInput, Fn);
10556 break;
10557 case 16:
10558 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10559 OutputBecomesInput, Fn);
10560 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10561 OutputBecomesInput, Fn);
10562 break;
10563 case 32:
10564 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10565 OutputBecomesInput, Fn);
10566 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10567 OutputBecomesInput, Fn);
10568 break;
10569 case 64:
10570 case 128:
10571 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10572 OutputBecomesInput, Fn);
10573 break;
10574 default:
10575 llvm_unreachable("Scalar type is too wide.");
10576 }
10577}
10578
10579/// Emit vector function attributes for AArch64, as defined in the AAVFABI.
10580static void emitAArch64DeclareSimdFunction(
10581 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN,
10582 ArrayRef<ParamAttrTy> ParamAttrs,
10583 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
10584 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) {
10585
10586 // Get basic data for building the vector signature.
10587 const auto Data = getNDSWDS(FD, ParamAttrs);
10588 const unsigned NDS = std::get<0>(Data);
10589 const unsigned WDS = std::get<1>(Data);
10590 const bool OutputBecomesInput = std::get<2>(Data);
10591
10592 // Check the values provided via `simdlen` by the user.
10593 // 1. A `simdlen(1)` doesn't produce vector signatures,
10594 if (UserVLEN == 1) {
10595 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10596 DiagnosticsEngine::Warning,
10597 "The clause simdlen(1) has no effect when targeting aarch64.");
10598 CGM.getDiags().Report(SLoc, DiagID);
10599 return;
10600 }
10601
10602 // 2. Section 3.3.1, item 1: user input must be a power of 2 for
10603 // Advanced SIMD output.
10604 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
10605 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10606 DiagnosticsEngine::Warning, "The value specified in simdlen must be a "
10607 "power of 2 when targeting Advanced SIMD.");
10608 CGM.getDiags().Report(SLoc, DiagID);
10609 return;
10610 }
10611
10612 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural
10613 // limits.
10614 if (ISA == 's' && UserVLEN != 0) {
10615 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
10616 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10617 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit "
10618 "lanes in the architectural constraints "
10619 "for SVE (min is 128-bit, max is "
10620 "2048-bit, by steps of 128-bit)");
10621 CGM.getDiags().Report(SLoc, DiagID) << WDS;
10622 return;
10623 }
10624 }
10625
10626 // Sort out parameter sequence.
10627 const std::string ParSeq = mangleVectorParameters(ParamAttrs);
10628 StringRef Prefix = "_ZGV";
10629 // Generate simdlen from user input (if any).
10630 if (UserVLEN) {
10631 if (ISA == 's') {
10632 // SVE generates only a masked function.
10633 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10634 OutputBecomesInput, Fn);
10635 } else {
10636 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10637 // Advanced SIMD generates one or two functions, depending on
10638 // the `[not]inbranch` clause.
10639 switch (State) {
10640 case OMPDeclareSimdDeclAttr::BS_Undefined:
10641 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10642 OutputBecomesInput, Fn);
10643 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10644 OutputBecomesInput, Fn);
10645 break;
10646 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10647 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10648 OutputBecomesInput, Fn);
10649 break;
10650 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10651 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10652 OutputBecomesInput, Fn);
10653 break;
10654 }
10655 }
10656 } else {
10657 // If no user simdlen is provided, follow the AAVFABI rules for
10658 // generating the vector length.
10659 if (ISA == 's') {
10660 // SVE, section 3.4.1, item 1.
10661 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName,
10662 OutputBecomesInput, Fn);
10663 } else {
10664 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10665 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or
10666 // two vector names depending on the use of the clause
10667 // `[not]inbranch`.
10668 switch (State) {
10669 case OMPDeclareSimdDeclAttr::BS_Undefined:
10670 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10671 OutputBecomesInput, Fn);
10672 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10673 OutputBecomesInput, Fn);
10674 break;
10675 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10676 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10677 OutputBecomesInput, Fn);
10678 break;
10679 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10680 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10681 OutputBecomesInput, Fn);
10682 break;
10683 }
10684 }
10685 }
10686}
10687
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010688void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
10689 llvm::Function *Fn) {
10690 ASTContext &C = CGM.getContext();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010691 FD = FD->getMostRecentDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010692 // Map params to their positions in function decl.
10693 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
10694 if (isa<CXXMethodDecl>(FD))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010695 ParamPositions.try_emplace(FD, 0);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010696 unsigned ParamPos = ParamPositions.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010697 for (const ParmVarDecl *P : FD->parameters()) {
10698 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010699 ++ParamPos;
10700 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010701 while (FD) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010702 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010703 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
10704 // Mark uniform parameters.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010705 for (const Expr *E : Attr->uniforms()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010706 E = E->IgnoreParenImpCasts();
10707 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010708 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010709 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010710 } else {
10711 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10712 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010713 Pos = ParamPositions[PVD];
10714 }
10715 ParamAttrs[Pos].Kind = Uniform;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010716 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010717 // Get alignment info.
10718 auto NI = Attr->alignments_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010719 for (const Expr *E : Attr->aligneds()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010720 E = E->IgnoreParenImpCasts();
10721 unsigned Pos;
10722 QualType ParmTy;
10723 if (isa<CXXThisExpr>(E)) {
10724 Pos = ParamPositions[FD];
10725 ParmTy = E->getType();
10726 } else {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010727 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10728 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010729 Pos = ParamPositions[PVD];
10730 ParmTy = PVD->getType();
10731 }
10732 ParamAttrs[Pos].Alignment =
10733 (*NI)
10734 ? (*NI)->EvaluateKnownConstInt(C)
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010735 : llvm::APSInt::getUnsigned(
10736 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy))
10737 .getQuantity());
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010738 ++NI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010739 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010740 // Mark linear parameters.
10741 auto SI = Attr->steps_begin();
10742 auto MI = Attr->modifiers_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010743 for (const Expr *E : Attr->linears()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010744 E = E->IgnoreParenImpCasts();
10745 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010746 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010747 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010748 } else {
10749 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10750 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010751 Pos = ParamPositions[PVD];
10752 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010753 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010754 ParamAttr.Kind = Linear;
10755 if (*SI) {
Fangrui Song407659a2018-11-30 23:41:18 +000010756 Expr::EvalResult Result;
10757 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010758 if (const auto *DRE =
10759 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
10760 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010761 ParamAttr.Kind = LinearWithVarStride;
10762 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(
10763 ParamPositions[StridePVD->getCanonicalDecl()]);
10764 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010765 }
Fangrui Song407659a2018-11-30 23:41:18 +000010766 } else {
10767 ParamAttr.StrideOrArg = Result.Val.getInt();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010768 }
10769 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010770 ++SI;
10771 ++MI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010772 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010773 llvm::APSInt VLENVal;
Alexey Bataeva0a22642019-04-16 13:56:21 +000010774 SourceLocation ExprLoc;
10775 const Expr *VLENExpr = Attr->getSimdlen();
10776 if (VLENExpr) {
10777 VLENVal = VLENExpr->EvaluateKnownConstInt(C);
10778 ExprLoc = VLENExpr->getExprLoc();
10779 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010780 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
10781 if (CGM.getTriple().getArch() == llvm::Triple::x86 ||
Alexey Bataeva0a22642019-04-16 13:56:21 +000010782 CGM.getTriple().getArch() == llvm::Triple::x86_64) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010783 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
Alexey Bataeva0a22642019-04-16 13:56:21 +000010784 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) {
10785 unsigned VLEN = VLENVal.getExtValue();
10786 StringRef MangledName = Fn->getName();
10787 if (CGM.getTarget().hasFeature("sve"))
10788 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10789 MangledName, 's', 128, Fn, ExprLoc);
10790 if (CGM.getTarget().hasFeature("neon"))
10791 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10792 MangledName, 'n', 128, Fn, ExprLoc);
10793 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010794 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010795 FD = FD->getPreviousDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010796 }
10797}
Alexey Bataev8b427062016-05-25 12:36:08 +000010798
10799namespace {
10800/// Cleanup action for doacross support.
10801class DoacrossCleanupTy final : public EHScopeStack::Cleanup {
10802public:
10803 static const int DoacrossFinArgs = 2;
10804
10805private:
James Y Knight9871db02019-02-05 16:42:33 +000010806 llvm::FunctionCallee RTLFn;
Alexey Bataev8b427062016-05-25 12:36:08 +000010807 llvm::Value *Args[DoacrossFinArgs];
10808
10809public:
James Y Knight9871db02019-02-05 16:42:33 +000010810 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
10811 ArrayRef<llvm::Value *> CallArgs)
Alexey Bataev8b427062016-05-25 12:36:08 +000010812 : RTLFn(RTLFn) {
10813 assert(CallArgs.size() == DoacrossFinArgs);
10814 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10815 }
10816 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10817 if (!CGF.HaveInsertPoint())
10818 return;
10819 CGF.EmitRuntimeCall(RTLFn, Args);
10820 }
10821};
10822} // namespace
10823
10824void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000010825 const OMPLoopDirective &D,
10826 ArrayRef<Expr *> NumIterations) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010827 if (!CGF.HaveInsertPoint())
10828 return;
10829
10830 ASTContext &C = CGM.getContext();
10831 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
10832 RecordDecl *RD;
10833 if (KmpDimTy.isNull()) {
10834 // Build struct kmp_dim { // loop bounds info casted to kmp_int64
10835 // kmp_int64 lo; // lower
10836 // kmp_int64 up; // upper
10837 // kmp_int64 st; // stride
10838 // };
10839 RD = C.buildImplicitRecord("kmp_dim");
10840 RD->startDefinition();
10841 addFieldToRecordDecl(C, RD, Int64Ty);
10842 addFieldToRecordDecl(C, RD, Int64Ty);
10843 addFieldToRecordDecl(C, RD, Int64Ty);
10844 RD->completeDefinition();
10845 KmpDimTy = C.getRecordType(RD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010846 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010847 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010848 }
Alexey Bataevf138fda2018-08-13 19:04:24 +000010849 llvm::APInt Size(/*numBits=*/32, NumIterations.size());
10850 QualType ArrayTy =
Richard Smith772e2662019-10-04 01:25:59 +000010851 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0);
Alexey Bataev8b427062016-05-25 12:36:08 +000010852
Alexey Bataevf138fda2018-08-13 19:04:24 +000010853 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
10854 CGF.EmitNullInitialization(DimsAddr, ArrayTy);
Alexey Bataev8b427062016-05-25 12:36:08 +000010855 enum { LowerFD = 0, UpperFD, StrideFD };
10856 // Fill dims with data.
Alexey Bataevf138fda2018-08-13 19:04:24 +000010857 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +000010858 LValue DimsLVal = CGF.MakeAddrLValue(
10859 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010860 // dims.upper = num_iterations;
10861 LValue UpperLVal = CGF.EmitLValueForField(
10862 DimsLVal, *std::next(RD->field_begin(), UpperFD));
10863 llvm::Value *NumIterVal =
10864 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]),
10865 D.getNumIterations()->getType(), Int64Ty,
10866 D.getNumIterations()->getExprLoc());
10867 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
10868 // dims.stride = 1;
10869 LValue StrideLVal = CGF.EmitLValueForField(
10870 DimsLVal, *std::next(RD->field_begin(), StrideFD));
10871 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
10872 StrideLVal);
10873 }
Alexey Bataev8b427062016-05-25 12:36:08 +000010874
10875 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
10876 // kmp_int32 num_dims, struct kmp_dim * dims);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010877 llvm::Value *Args[] = {
10878 emitUpdateLocation(CGF, D.getBeginLoc()),
10879 getThreadID(CGF, D.getBeginLoc()),
10880 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()),
10881 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knight751fe282019-02-09 22:22:28 +000010882 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(),
Alexey Bataevf138fda2018-08-13 19:04:24 +000010883 CGM.VoidPtrTy)};
Alexey Bataev8b427062016-05-25 12:36:08 +000010884
James Y Knight9871db02019-02-05 16:42:33 +000010885 llvm::FunctionCallee RTLFn =
10886 createRuntimeFunction(OMPRTL__kmpc_doacross_init);
Alexey Bataev8b427062016-05-25 12:36:08 +000010887 CGF.EmitRuntimeCall(RTLFn, Args);
10888 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
Stephen Kelly1c301dc2018-08-09 21:09:38 +000010889 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())};
James Y Knight9871db02019-02-05 16:42:33 +000010890 llvm::FunctionCallee FiniRTLFn =
10891 createRuntimeFunction(OMPRTL__kmpc_doacross_fini);
Alexey Bataev8b427062016-05-25 12:36:08 +000010892 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
10893 llvm::makeArrayRef(FiniArgs));
10894}
10895
10896void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
10897 const OMPDependClause *C) {
10898 QualType Int64Ty =
10899 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010900 llvm::APInt Size(/*numBits=*/32, C->getNumLoops());
10901 QualType ArrayTy = CGM.getContext().getConstantArrayType(
Richard Smith772e2662019-10-04 01:25:59 +000010902 Int64Ty, Size, nullptr, ArrayType::Normal, 0);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010903 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr");
10904 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) {
10905 const Expr *CounterVal = C->getLoopData(I);
10906 assert(CounterVal);
10907 llvm::Value *CntVal = CGF.EmitScalarConversion(
10908 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
10909 CounterVal->getExprLoc());
James Y Knight751fe282019-02-09 22:22:28 +000010910 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I),
10911 /*Volatile=*/false, Int64Ty);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010912 }
10913 llvm::Value *Args[] = {
10914 emitUpdateLocation(CGF, C->getBeginLoc()),
10915 getThreadID(CGF, C->getBeginLoc()),
James Y Knight751fe282019-02-09 22:22:28 +000010916 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()};
James Y Knight9871db02019-02-05 16:42:33 +000010917 llvm::FunctionCallee RTLFn;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010918 if (C->getDependencyKind() == OMPC_DEPEND_source) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010919 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010920 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010921 assert(C->getDependencyKind() == OMPC_DEPEND_sink);
10922 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait);
10923 }
10924 CGF.EmitRuntimeCall(RTLFn, Args);
10925}
10926
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010927void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000010928 llvm::FunctionCallee Callee,
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010929 ArrayRef<llvm::Value *> Args) const {
10930 assert(Loc.isValid() && "Outlined function call location must be valid.");
Alexey Bataev3c595a62017-08-14 15:01:03 +000010931 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
10932
James Y Knight9871db02019-02-05 16:42:33 +000010933 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010934 if (Fn->doesNotThrow()) {
Alexey Bataev3c595a62017-08-14 15:01:03 +000010935 CGF.EmitNounwindRuntimeCall(Fn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010936 return;
10937 }
10938 }
Alexey Bataev3c595a62017-08-14 15:01:03 +000010939 CGF.EmitRuntimeCall(Callee, Args);
10940}
10941
10942void CGOpenMPRuntime::emitOutlinedFunctionCall(
James Y Knight9871db02019-02-05 16:42:33 +000010943 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn,
Alexey Bataev3c595a62017-08-14 15:01:03 +000010944 ArrayRef<llvm::Value *> Args) const {
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010945 emitCall(CGF, Loc, OutlinedFn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010946}
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010947
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +000010948void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) {
10949 if (const auto *FD = dyn_cast<FunctionDecl>(D))
10950 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
10951 HasEmittedDeclareTargetRegion = true;
10952}
10953
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010954Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
10955 const VarDecl *NativeParam,
10956 const VarDecl *TargetParam) const {
10957 return CGF.GetAddrOfLocalVar(NativeParam);
10958}
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010959
Alexey Bataev4f680db2019-03-19 16:41:16 +000010960namespace {
10961/// Cleanup action for allocate support.
10962class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup {
10963public:
10964 static const int CleanupArgs = 3;
10965
10966private:
10967 llvm::FunctionCallee RTLFn;
10968 llvm::Value *Args[CleanupArgs];
10969
10970public:
10971 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
10972 ArrayRef<llvm::Value *> CallArgs)
10973 : RTLFn(RTLFn) {
10974 assert(CallArgs.size() == CleanupArgs &&
10975 "Size of arguments does not match.");
10976 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10977 }
10978 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10979 if (!CGF.HaveInsertPoint())
10980 return;
10981 CGF.EmitRuntimeCall(RTLFn, Args);
10982 }
10983};
10984} // namespace
10985
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000010986Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF,
10987 const VarDecl *VD) {
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010988 if (!VD)
10989 return Address::invalid();
Alexey Bataev4f680db2019-03-19 16:41:16 +000010990 const VarDecl *CVD = VD->getCanonicalDecl();
10991 if (!CVD->hasAttr<OMPAllocateDeclAttr>())
10992 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010993 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
10994 // Use the default allocation.
Alexey Bataev0fd3c682019-04-02 19:44:46 +000010995 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
10996 !AA->getAllocator())
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010997 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010998 llvm::Value *Size;
10999 CharUnits Align = CGM.getContext().getDeclAlign(CVD);
11000 if (CVD->getType()->isVariablyModifiedType()) {
11001 Size = CGF.getTypeSize(CVD->getType());
Alexey Bataev9c397812019-04-03 17:57:06 +000011002 // Align the size: ((size + align - 1) / align) * align
11003 Size = CGF.Builder.CreateNUWAdd(
11004 Size, CGM.getSize(Align - CharUnits::fromQuantity(1)));
11005 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align));
11006 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align));
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011007 } else {
11008 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType());
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011009 Size = CGM.getSize(Sz.alignTo(Align));
Alexey Bataev4f680db2019-03-19 16:41:16 +000011010 }
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011011 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc());
11012 assert(AA->getAllocator() &&
11013 "Expected allocator expression for non-default allocator.");
11014 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator());
Alexey Bataev6cf7b712019-04-08 19:06:42 +000011015 // According to the standard, the original allocator type is a enum (integer).
11016 // Convert to pointer type, if required.
11017 if (Allocator->getType()->isIntegerTy())
11018 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy);
11019 else if (Allocator->getType()->isPointerTy())
11020 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator,
11021 CGM.VoidPtrTy);
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011022 llvm::Value *Args[] = {ThreadID, Size, Allocator};
11023
11024 llvm::Value *Addr =
11025 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args,
11026 CVD->getName() + ".void.addr");
11027 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr,
11028 Allocator};
11029 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free);
11030
11031 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
11032 llvm::makeArrayRef(FiniArgs));
11033 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11034 Addr,
11035 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())),
11036 CVD->getName() + ".addr");
11037 return Address(Addr, Align);
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000011038}
11039
Alexey Bataevfde11e92019-11-07 11:03:10 -050011040namespace {
11041using OMPContextSelectorData =
Alexey Bataevf8ff3d72019-11-21 16:36:49 -050011042 OpenMPCtxSelectorData<ArrayRef<StringRef>, llvm::APSInt>;
Alexey Bataevfde11e92019-11-07 11:03:10 -050011043using CompleteOMPContextSelectorData = SmallVector<OMPContextSelectorData, 4>;
11044} // anonymous namespace
11045
Alexey Bataev2df5f122019-10-01 20:18:32 +000011046/// Checks current context and returns true if it matches the context selector.
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011047template <OpenMPContextSelectorSetKind CtxSet, OpenMPContextSelectorKind Ctx,
11048 typename... Arguments>
11049static bool checkContext(const OMPContextSelectorData &Data,
11050 Arguments... Params) {
Alexey Bataevfde11e92019-11-07 11:03:10 -050011051 assert(Data.CtxSet != OMP_CTX_SET_unknown && Data.Ctx != OMP_CTX_unknown &&
Alexey Bataev2df5f122019-10-01 20:18:32 +000011052 "Unknown context selector or context selector set.");
11053 return false;
11054}
11055
11056/// Checks for implementation={vendor(<vendor>)} context selector.
11057/// \returns true iff <vendor>="llvm", false otherwise.
11058template <>
Alexey Bataevfde11e92019-11-07 11:03:10 -050011059bool checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(
11060 const OMPContextSelectorData &Data) {
11061 return llvm::all_of(Data.Names,
Alexey Bataev303657a2019-10-08 19:44:16 +000011062 [](StringRef S) { return !S.compare_lower("llvm"); });
Alexey Bataev2df5f122019-10-01 20:18:32 +000011063}
11064
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011065/// Checks for device={kind(<kind>)} context selector.
11066/// \returns true if <kind>="host" and compilation is for host.
11067/// true if <kind>="nohost" and compilation is for device.
11068/// true if <kind>="cpu" and compilation is for Arm, X86 or PPC CPU.
11069/// true if <kind>="gpu" and compilation is for NVPTX or AMDGCN.
11070/// false otherwise.
11071template <>
11072bool checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>(
11073 const OMPContextSelectorData &Data, CodeGenModule &CGM) {
11074 for (StringRef Name : Data.Names) {
11075 if (!Name.compare_lower("host")) {
11076 if (CGM.getLangOpts().OpenMPIsDevice)
11077 return false;
11078 continue;
11079 }
11080 if (!Name.compare_lower("nohost")) {
11081 if (!CGM.getLangOpts().OpenMPIsDevice)
11082 return false;
11083 continue;
11084 }
11085 switch (CGM.getTriple().getArch()) {
11086 case llvm::Triple::arm:
11087 case llvm::Triple::armeb:
11088 case llvm::Triple::aarch64:
11089 case llvm::Triple::aarch64_be:
11090 case llvm::Triple::aarch64_32:
11091 case llvm::Triple::ppc:
11092 case llvm::Triple::ppc64:
11093 case llvm::Triple::ppc64le:
11094 case llvm::Triple::x86:
11095 case llvm::Triple::x86_64:
11096 if (Name.compare_lower("cpu"))
11097 return false;
11098 break;
11099 case llvm::Triple::amdgcn:
11100 case llvm::Triple::nvptx:
11101 case llvm::Triple::nvptx64:
11102 if (Name.compare_lower("gpu"))
11103 return false;
11104 break;
11105 case llvm::Triple::UnknownArch:
11106 case llvm::Triple::arc:
11107 case llvm::Triple::avr:
11108 case llvm::Triple::bpfel:
11109 case llvm::Triple::bpfeb:
11110 case llvm::Triple::hexagon:
11111 case llvm::Triple::mips:
11112 case llvm::Triple::mipsel:
11113 case llvm::Triple::mips64:
11114 case llvm::Triple::mips64el:
11115 case llvm::Triple::msp430:
11116 case llvm::Triple::r600:
11117 case llvm::Triple::riscv32:
11118 case llvm::Triple::riscv64:
11119 case llvm::Triple::sparc:
11120 case llvm::Triple::sparcv9:
11121 case llvm::Triple::sparcel:
11122 case llvm::Triple::systemz:
11123 case llvm::Triple::tce:
11124 case llvm::Triple::tcele:
11125 case llvm::Triple::thumb:
11126 case llvm::Triple::thumbeb:
11127 case llvm::Triple::xcore:
11128 case llvm::Triple::le32:
11129 case llvm::Triple::le64:
11130 case llvm::Triple::amdil:
11131 case llvm::Triple::amdil64:
11132 case llvm::Triple::hsail:
11133 case llvm::Triple::hsail64:
11134 case llvm::Triple::spir:
11135 case llvm::Triple::spir64:
11136 case llvm::Triple::kalimba:
11137 case llvm::Triple::shave:
11138 case llvm::Triple::lanai:
11139 case llvm::Triple::wasm32:
11140 case llvm::Triple::wasm64:
11141 case llvm::Triple::renderscript32:
11142 case llvm::Triple::renderscript64:
11143 return false;
11144 }
11145 }
11146 return true;
11147}
11148
11149bool matchesContext(CodeGenModule &CGM,
11150 const CompleteOMPContextSelectorData &ContextData) {
Alexey Bataevfde11e92019-11-07 11:03:10 -050011151 for (const OMPContextSelectorData &Data : ContextData) {
Alexey Bataev5459a902019-11-22 11:42:08 -050011152 switch (Data.Ctx) {
11153 case OMP_CTX_vendor:
11154 assert(Data.CtxSet == OMP_CTX_SET_implementation &&
11155 "Expected implementation context selector set.");
11156 if (!checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(Data))
11157 return false;
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011158 break;
Alexey Bataev5459a902019-11-22 11:42:08 -050011159 case OMP_CTX_kind:
11160 assert(Data.CtxSet == OMP_CTX_SET_device &&
11161 "Expected device context selector set.");
11162 if (!checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>(Data,
11163 CGM))
11164 return false;
Alexey Bataevfde11e92019-11-07 11:03:10 -050011165 break;
Alexey Bataev5459a902019-11-22 11:42:08 -050011166 case OMP_CTX_unknown:
11167 llvm_unreachable("Unknown context selector kind.");
Alexey Bataevfde11e92019-11-07 11:03:10 -050011168 }
11169 }
11170 return true;
11171}
11172
11173static CompleteOMPContextSelectorData
11174translateAttrToContextSelectorData(ASTContext &C,
11175 const OMPDeclareVariantAttr *A) {
11176 CompleteOMPContextSelectorData Data;
11177 for (unsigned I = 0, E = A->scores_size(); I < E; ++I) {
11178 Data.emplace_back();
11179 auto CtxSet = static_cast<OpenMPContextSelectorSetKind>(
11180 *std::next(A->ctxSelectorSets_begin(), I));
11181 auto Ctx = static_cast<OpenMPContextSelectorKind>(
11182 *std::next(A->ctxSelectors_begin(), I));
11183 Data.back().CtxSet = CtxSet;
11184 Data.back().Ctx = Ctx;
11185 const Expr *Score = *std::next(A->scores_begin(), I);
11186 Data.back().Score = Score->EvaluateKnownConstInt(C);
Alexey Bataev5459a902019-11-22 11:42:08 -050011187 switch (Ctx) {
11188 case OMP_CTX_vendor:
11189 assert(CtxSet == OMP_CTX_SET_implementation &&
11190 "Expected implementation context selector set.");
11191 Data.back().Names =
11192 llvm::makeArrayRef(A->implVendors_begin(), A->implVendors_end());
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011193 break;
Alexey Bataev5459a902019-11-22 11:42:08 -050011194 case OMP_CTX_kind:
11195 assert(CtxSet == OMP_CTX_SET_device &&
11196 "Expected device context selector set.");
11197 Data.back().Names =
11198 llvm::makeArrayRef(A->deviceKinds_begin(), A->deviceKinds_end());
Alexey Bataevfde11e92019-11-07 11:03:10 -050011199 break;
Alexey Bataev5459a902019-11-22 11:42:08 -050011200 case OMP_CTX_unknown:
11201 llvm_unreachable("Unknown context selector kind.");
Alexey Bataevfde11e92019-11-07 11:03:10 -050011202 }
11203 }
11204 return Data;
11205}
11206
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011207static bool isStrictSubset(const CompleteOMPContextSelectorData &LHS,
11208 const CompleteOMPContextSelectorData &RHS) {
11209 llvm::SmallDenseMap<std::pair<int, int>, llvm::StringSet<>, 4> RHSData;
11210 for (const OMPContextSelectorData &D : RHS) {
11211 auto &Pair = RHSData.FindAndConstruct(std::make_pair(D.CtxSet, D.Ctx));
11212 Pair.getSecond().insert(D.Names.begin(), D.Names.end());
11213 }
11214 bool AllSetsAreEqual = true;
11215 for (const OMPContextSelectorData &D : LHS) {
11216 auto It = RHSData.find(std::make_pair(D.CtxSet, D.Ctx));
11217 if (It == RHSData.end())
11218 return false;
11219 if (D.Names.size() > It->getSecond().size())
11220 return false;
11221 if (llvm::set_union(It->getSecond(), D.Names))
11222 return false;
11223 AllSetsAreEqual =
11224 AllSetsAreEqual && (D.Names.size() == It->getSecond().size());
11225 }
11226
11227 return LHS.size() != RHS.size() || !AllSetsAreEqual;
11228}
11229
Alexey Bataevfde11e92019-11-07 11:03:10 -050011230static bool greaterCtxScore(const CompleteOMPContextSelectorData &LHS,
11231 const CompleteOMPContextSelectorData &RHS) {
11232 // Score is calculated as sum of all scores + 1.
11233 llvm::APSInt LHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false);
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011234 bool RHSIsSubsetOfLHS = isStrictSubset(RHS, LHS);
11235 if (RHSIsSubsetOfLHS) {
11236 LHSScore = llvm::APSInt::get(0);
11237 } else {
11238 for (const OMPContextSelectorData &Data : LHS) {
11239 if (Data.Score.getBitWidth() > LHSScore.getBitWidth()) {
11240 LHSScore = LHSScore.extend(Data.Score.getBitWidth()) + Data.Score;
11241 } else if (Data.Score.getBitWidth() < LHSScore.getBitWidth()) {
11242 LHSScore += Data.Score.extend(LHSScore.getBitWidth());
11243 } else {
11244 LHSScore += Data.Score;
11245 }
Alexey Bataevfde11e92019-11-07 11:03:10 -050011246 }
11247 }
11248 llvm::APSInt RHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false);
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011249 if (!RHSIsSubsetOfLHS && isStrictSubset(LHS, RHS)) {
11250 RHSScore = llvm::APSInt::get(0);
11251 } else {
11252 for (const OMPContextSelectorData &Data : RHS) {
11253 if (Data.Score.getBitWidth() > RHSScore.getBitWidth()) {
11254 RHSScore = RHSScore.extend(Data.Score.getBitWidth()) + Data.Score;
11255 } else if (Data.Score.getBitWidth() < RHSScore.getBitWidth()) {
11256 RHSScore += Data.Score.extend(RHSScore.getBitWidth());
11257 } else {
11258 RHSScore += Data.Score;
11259 }
Alexey Bataevfde11e92019-11-07 11:03:10 -050011260 }
11261 }
11262 return llvm::APSInt::compareValues(LHSScore, RHSScore) >= 0;
Alexey Bataev0364c762019-10-03 20:49:48 +000011263}
11264
Alexey Bataev2df5f122019-10-01 20:18:32 +000011265/// Finds the variant function that matches current context with its context
11266/// selector.
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011267static const FunctionDecl *getDeclareVariantFunction(CodeGenModule &CGM,
Alexey Bataev0364c762019-10-03 20:49:48 +000011268 const FunctionDecl *FD) {
Alexey Bataev2df5f122019-10-01 20:18:32 +000011269 if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>())
11270 return FD;
11271 // Iterate through all DeclareVariant attributes and check context selectors.
Alexey Bataev0364c762019-10-03 20:49:48 +000011272 const OMPDeclareVariantAttr *TopMostAttr = nullptr;
Alexey Bataevfde11e92019-11-07 11:03:10 -050011273 CompleteOMPContextSelectorData TopMostData;
Alexey Bataev0364c762019-10-03 20:49:48 +000011274 for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) {
Alexey Bataevfde11e92019-11-07 11:03:10 -050011275 CompleteOMPContextSelectorData Data =
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011276 translateAttrToContextSelectorData(CGM.getContext(), A);
11277 if (!matchesContext(CGM, Data))
Alexey Bataevfde11e92019-11-07 11:03:10 -050011278 continue;
Alexey Bataev0364c762019-10-03 20:49:48 +000011279 // If the attribute matches the context, find the attribute with the highest
11280 // score.
Alexey Bataevfde11e92019-11-07 11:03:10 -050011281 if (!TopMostAttr || !greaterCtxScore(TopMostData, Data)) {
11282 TopMostAttr = A;
11283 TopMostData.swap(Data);
11284 }
Alexey Bataev2df5f122019-10-01 20:18:32 +000011285 }
Alexey Bataev0364c762019-10-03 20:49:48 +000011286 if (!TopMostAttr)
Alexey Bataev2df5f122019-10-01 20:18:32 +000011287 return FD;
Alexey Bataev2df5f122019-10-01 20:18:32 +000011288 return cast<FunctionDecl>(
Alexey Bataev0364c762019-10-03 20:49:48 +000011289 cast<DeclRefExpr>(TopMostAttr->getVariantFuncRef()->IgnoreParenImpCasts())
Alexey Bataev2df5f122019-10-01 20:18:32 +000011290 ->getDecl());
11291}
11292
11293bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) {
11294 const auto *D = cast<FunctionDecl>(GD.getDecl());
11295 // If the original function is defined already, use its definition.
11296 StringRef MangledName = CGM.getMangledName(GD);
11297 llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName);
11298 if (Orig && !Orig->isDeclaration())
11299 return false;
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011300 const FunctionDecl *NewFD = getDeclareVariantFunction(CGM, D);
Alexey Bataev2df5f122019-10-01 20:18:32 +000011301 // Emit original function if it does not have declare variant attribute or the
11302 // context does not match.
11303 if (NewFD == D)
11304 return false;
11305 GlobalDecl NewGD = GD.getWithDecl(NewFD);
Alexey Bataevc2cd2d42019-10-10 17:28:10 +000011306 if (tryEmitDeclareVariant(NewGD, GD, Orig, IsForDefinition)) {
Alexey Bataev2df5f122019-10-01 20:18:32 +000011307 DeferredVariantFunction.erase(D);
11308 return true;
11309 }
11310 DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD)));
11311 return true;
11312}
11313
James Y Knight9871db02019-02-05 16:42:33 +000011314llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011315 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11316 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11317 llvm_unreachable("Not supported in SIMD-only mode");
11318}
11319
James Y Knight9871db02019-02-05 16:42:33 +000011320llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011321 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11322 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11323 llvm_unreachable("Not supported in SIMD-only mode");
11324}
11325
James Y Knight9871db02019-02-05 16:42:33 +000011326llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011327 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11328 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
11329 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
11330 bool Tied, unsigned &NumberOfParts) {
11331 llvm_unreachable("Not supported in SIMD-only mode");
11332}
11333
11334void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF,
11335 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000011336 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011337 ArrayRef<llvm::Value *> CapturedVars,
11338 const Expr *IfCond) {
11339 llvm_unreachable("Not supported in SIMD-only mode");
11340}
11341
11342void CGOpenMPSIMDRuntime::emitCriticalRegion(
11343 CodeGenFunction &CGF, StringRef CriticalName,
11344 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
11345 const Expr *Hint) {
11346 llvm_unreachable("Not supported in SIMD-only mode");
11347}
11348
11349void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF,
11350 const RegionCodeGenTy &MasterOpGen,
11351 SourceLocation Loc) {
11352 llvm_unreachable("Not supported in SIMD-only mode");
11353}
11354
11355void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
11356 SourceLocation Loc) {
11357 llvm_unreachable("Not supported in SIMD-only mode");
11358}
11359
11360void CGOpenMPSIMDRuntime::emitTaskgroupRegion(
11361 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen,
11362 SourceLocation Loc) {
11363 llvm_unreachable("Not supported in SIMD-only mode");
11364}
11365
11366void CGOpenMPSIMDRuntime::emitSingleRegion(
11367 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen,
11368 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars,
11369 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs,
11370 ArrayRef<const Expr *> AssignmentOps) {
11371 llvm_unreachable("Not supported in SIMD-only mode");
11372}
11373
11374void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF,
11375 const RegionCodeGenTy &OrderedOpGen,
11376 SourceLocation Loc,
11377 bool IsThreads) {
11378 llvm_unreachable("Not supported in SIMD-only mode");
11379}
11380
11381void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF,
11382 SourceLocation Loc,
11383 OpenMPDirectiveKind Kind,
11384 bool EmitChecks,
11385 bool ForceSimpleCall) {
11386 llvm_unreachable("Not supported in SIMD-only mode");
11387}
11388
11389void CGOpenMPSIMDRuntime::emitForDispatchInit(
11390 CodeGenFunction &CGF, SourceLocation Loc,
11391 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
11392 bool Ordered, const DispatchRTInput &DispatchValues) {
11393 llvm_unreachable("Not supported in SIMD-only mode");
11394}
11395
11396void CGOpenMPSIMDRuntime::emitForStaticInit(
11397 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind,
11398 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) {
11399 llvm_unreachable("Not supported in SIMD-only mode");
11400}
11401
11402void CGOpenMPSIMDRuntime::emitDistributeStaticInit(
11403 CodeGenFunction &CGF, SourceLocation Loc,
11404 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) {
11405 llvm_unreachable("Not supported in SIMD-only mode");
11406}
11407
11408void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
11409 SourceLocation Loc,
11410 unsigned IVSize,
11411 bool IVSigned) {
11412 llvm_unreachable("Not supported in SIMD-only mode");
11413}
11414
11415void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF,
11416 SourceLocation Loc,
11417 OpenMPDirectiveKind DKind) {
11418 llvm_unreachable("Not supported in SIMD-only mode");
11419}
11420
11421llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF,
11422 SourceLocation Loc,
11423 unsigned IVSize, bool IVSigned,
11424 Address IL, Address LB,
11425 Address UB, Address ST) {
11426 llvm_unreachable("Not supported in SIMD-only mode");
11427}
11428
11429void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
11430 llvm::Value *NumThreads,
11431 SourceLocation Loc) {
11432 llvm_unreachable("Not supported in SIMD-only mode");
11433}
11434
11435void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF,
11436 OpenMPProcBindClauseKind ProcBind,
11437 SourceLocation Loc) {
11438 llvm_unreachable("Not supported in SIMD-only mode");
11439}
11440
11441Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
11442 const VarDecl *VD,
11443 Address VDAddr,
11444 SourceLocation Loc) {
11445 llvm_unreachable("Not supported in SIMD-only mode");
11446}
11447
11448llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition(
11449 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit,
11450 CodeGenFunction *CGF) {
11451 llvm_unreachable("Not supported in SIMD-only mode");
11452}
11453
11454Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate(
11455 CodeGenFunction &CGF, QualType VarType, StringRef Name) {
11456 llvm_unreachable("Not supported in SIMD-only mode");
11457}
11458
11459void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF,
11460 ArrayRef<const Expr *> Vars,
11461 SourceLocation Loc) {
11462 llvm_unreachable("Not supported in SIMD-only mode");
11463}
11464
11465void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
11466 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000011467 llvm::Function *TaskFunction,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011468 QualType SharedsTy, Address Shareds,
11469 const Expr *IfCond,
11470 const OMPTaskDataTy &Data) {
11471 llvm_unreachable("Not supported in SIMD-only mode");
11472}
11473
11474void CGOpenMPSIMDRuntime::emitTaskLoopCall(
11475 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000011476 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011477 const Expr *IfCond, const OMPTaskDataTy &Data) {
11478 llvm_unreachable("Not supported in SIMD-only mode");
11479}
11480
11481void CGOpenMPSIMDRuntime::emitReduction(
11482 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates,
11483 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
11484 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) {
11485 assert(Options.SimpleReduction && "Only simple reduction is expected.");
11486 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
11487 ReductionOps, Options);
11488}
11489
11490llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit(
11491 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
11492 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
11493 llvm_unreachable("Not supported in SIMD-only mode");
11494}
11495
11496void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
11497 SourceLocation Loc,
11498 ReductionCodeGen &RCG,
11499 unsigned N) {
11500 llvm_unreachable("Not supported in SIMD-only mode");
11501}
11502
11503Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
11504 SourceLocation Loc,
11505 llvm::Value *ReductionsPtr,
11506 LValue SharedLVal) {
11507 llvm_unreachable("Not supported in SIMD-only mode");
11508}
11509
11510void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
11511 SourceLocation Loc) {
11512 llvm_unreachable("Not supported in SIMD-only mode");
11513}
11514
11515void CGOpenMPSIMDRuntime::emitCancellationPointCall(
11516 CodeGenFunction &CGF, SourceLocation Loc,
11517 OpenMPDirectiveKind CancelRegion) {
11518 llvm_unreachable("Not supported in SIMD-only mode");
11519}
11520
11521void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF,
11522 SourceLocation Loc, const Expr *IfCond,
11523 OpenMPDirectiveKind CancelRegion) {
11524 llvm_unreachable("Not supported in SIMD-only mode");
11525}
11526
11527void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction(
11528 const OMPExecutableDirective &D, StringRef ParentName,
11529 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
11530 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
11531 llvm_unreachable("Not supported in SIMD-only mode");
11532}
11533
Alexey Bataevec7946e2019-09-23 14:06:51 +000011534void CGOpenMPSIMDRuntime::emitTargetCall(
11535 CodeGenFunction &CGF, const OMPExecutableDirective &D,
11536 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
11537 const Expr *Device,
11538 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
11539 const OMPLoopDirective &D)>
11540 SizeEmitter) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011541 llvm_unreachable("Not supported in SIMD-only mode");
11542}
11543
11544bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) {
11545 llvm_unreachable("Not supported in SIMD-only mode");
11546}
11547
11548bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
11549 llvm_unreachable("Not supported in SIMD-only mode");
11550}
11551
11552bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) {
11553 return false;
11554}
11555
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011556void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF,
11557 const OMPExecutableDirective &D,
11558 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000011559 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011560 ArrayRef<llvm::Value *> CapturedVars) {
11561 llvm_unreachable("Not supported in SIMD-only mode");
11562}
11563
11564void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
11565 const Expr *NumTeams,
11566 const Expr *ThreadLimit,
11567 SourceLocation Loc) {
11568 llvm_unreachable("Not supported in SIMD-only mode");
11569}
11570
11571void CGOpenMPSIMDRuntime::emitTargetDataCalls(
11572 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
11573 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
11574 llvm_unreachable("Not supported in SIMD-only mode");
11575}
11576
11577void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
11578 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
11579 const Expr *Device) {
11580 llvm_unreachable("Not supported in SIMD-only mode");
11581}
11582
11583void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000011584 const OMPLoopDirective &D,
11585 ArrayRef<Expr *> NumIterations) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011586 llvm_unreachable("Not supported in SIMD-only mode");
11587}
11588
11589void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
11590 const OMPDependClause *C) {
11591 llvm_unreachable("Not supported in SIMD-only mode");
11592}
11593
11594const VarDecl *
11595CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD,
11596 const VarDecl *NativeParam) const {
11597 llvm_unreachable("Not supported in SIMD-only mode");
11598}
11599
11600Address
11601CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF,
11602 const VarDecl *NativeParam,
11603 const VarDecl *TargetParam) const {
11604 llvm_unreachable("Not supported in SIMD-only mode");
11605}