blob: 9f1b907e89dbe8619229a5d659ed293f836d095c [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);
Adrian Prantlce7d3592019-12-05 12:26:16 -08006192 CGF.FinishFunction(Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006193 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:
cchen47d60942019-12-05 13:43:48 -05006677 case OMPD_parallel_master:
Alexey Bataev5c427362019-04-10 19:11:33 +00006678 case OMPD_parallel_sections:
6679 case OMPD_for_simd:
6680 case OMPD_parallel_for_simd:
6681 case OMPD_cancel:
6682 case OMPD_cancellation_point:
6683 case OMPD_ordered:
6684 case OMPD_threadprivate:
6685 case OMPD_allocate:
6686 case OMPD_task:
6687 case OMPD_simd:
6688 case OMPD_sections:
6689 case OMPD_section:
6690 case OMPD_single:
6691 case OMPD_master:
6692 case OMPD_critical:
6693 case OMPD_taskyield:
6694 case OMPD_barrier:
6695 case OMPD_taskwait:
6696 case OMPD_taskgroup:
6697 case OMPD_atomic:
6698 case OMPD_flush:
6699 case OMPD_teams:
6700 case OMPD_target_data:
6701 case OMPD_target_exit_data:
6702 case OMPD_target_enter_data:
6703 case OMPD_distribute:
6704 case OMPD_distribute_simd:
6705 case OMPD_distribute_parallel_for:
6706 case OMPD_distribute_parallel_for_simd:
6707 case OMPD_teams_distribute:
6708 case OMPD_teams_distribute_simd:
6709 case OMPD_teams_distribute_parallel_for:
6710 case OMPD_teams_distribute_parallel_for_simd:
6711 case OMPD_target_update:
6712 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00006713 case OMPD_declare_variant:
Alexey Bataev5c427362019-04-10 19:11:33 +00006714 case OMPD_declare_target:
6715 case OMPD_end_declare_target:
6716 case OMPD_declare_reduction:
6717 case OMPD_declare_mapper:
6718 case OMPD_taskloop:
6719 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00006720 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00006721 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00006722 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04006723 case OMPD_parallel_master_taskloop_simd:
Alexey Bataev5c427362019-04-10 19:11:33 +00006724 case OMPD_requires:
6725 case OMPD_unknown:
6726 break;
6727 }
6728 llvm_unreachable("Unexpected directive kind.");
6729}
Samuel Antaob68e2db2016-03-03 16:20:23 +00006730
Alexey Bataev5c427362019-04-10 19:11:33 +00006731static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS,
6732 llvm::Value *DefaultThreadLimitVal) {
6733 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6734 CGF.getContext(), CS->getCapturedStmt());
6735 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6736 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) {
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006737 llvm::Value *NumThreads = nullptr;
6738 llvm::Value *CondVal = nullptr;
6739 // Handle if clause. If if clause present, the number of threads is
6740 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6741 if (Dir->hasClausesOfKind<OMPIfClause>()) {
6742 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6743 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6744 const OMPIfClause *IfClause = nullptr;
6745 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) {
6746 if (C->getNameModifier() == OMPD_unknown ||
6747 C->getNameModifier() == OMPD_parallel) {
6748 IfClause = C;
6749 break;
6750 }
6751 }
6752 if (IfClause) {
6753 const Expr *Cond = IfClause->getCondition();
6754 bool Result;
6755 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6756 if (!Result)
6757 return CGF.Builder.getInt32(1);
6758 } else {
6759 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange());
6760 if (const auto *PreInit =
6761 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) {
6762 for (const auto *I : PreInit->decls()) {
6763 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6764 CGF.EmitVarDecl(cast<VarDecl>(*I));
6765 } else {
6766 CodeGenFunction::AutoVarEmission Emission =
6767 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6768 CGF.EmitAutoVarCleanups(Emission);
6769 }
6770 }
6771 }
6772 CondVal = CGF.EvaluateExprAsBool(Cond);
6773 }
6774 }
6775 }
6776 // Check the value of num_threads clause iff if clause was not specified
6777 // or is not evaluated to false.
Alexey Bataev5c427362019-04-10 19:11:33 +00006778 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) {
6779 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6780 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6781 const auto *NumThreadsClause =
6782 Dir->getSingleClause<OMPNumThreadsClause>();
6783 CodeGenFunction::LexicalScope Scope(
6784 CGF, NumThreadsClause->getNumThreads()->getSourceRange());
6785 if (const auto *PreInit =
6786 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6787 for (const auto *I : PreInit->decls()) {
6788 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6789 CGF.EmitVarDecl(cast<VarDecl>(*I));
6790 } else {
6791 CodeGenFunction::AutoVarEmission Emission =
6792 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6793 CGF.EmitAutoVarCleanups(Emission);
6794 }
6795 }
6796 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006797 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads());
Alexey Bataev5c427362019-04-10 19:11:33 +00006798 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006799 /*isSigned=*/false);
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006800 if (DefaultThreadLimitVal)
6801 NumThreads = CGF.Builder.CreateSelect(
6802 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads),
6803 DefaultThreadLimitVal, NumThreads);
6804 } else {
6805 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal
6806 : CGF.Builder.getInt32(0);
Alexey Bataev5c427362019-04-10 19:11:33 +00006807 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006808 // Process condition of the if clause.
6809 if (CondVal) {
6810 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads,
6811 CGF.Builder.getInt32(1));
6812 }
6813 return NumThreads;
Alexey Bataev5c427362019-04-10 19:11:33 +00006814 }
6815 if (isOpenMPSimdDirective(Dir->getDirectiveKind()))
6816 return CGF.Builder.getInt32(1);
6817 return DefaultThreadLimitVal;
6818 }
6819 return DefaultThreadLimitVal ? DefaultThreadLimitVal
6820 : CGF.Builder.getInt32(0);
Samuel Antaob68e2db2016-03-03 16:20:23 +00006821}
6822
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006823/// Emit the number of threads for a target directive. Inspect the
6824/// thread_limit clause associated with a teams construct combined or closely
6825/// nested with the target directive.
6826///
6827/// Emit the num_threads clause for directives such as 'target parallel' that
6828/// have no associated teams construct.
6829///
6830/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006831static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006832emitNumThreadsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006833 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006834 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6835 "Clauses associated with the teams directive expected to be emitted "
6836 "only for the host!");
6837 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6838 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6839 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006840 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006841 llvm::Value *ThreadLimitVal = nullptr;
6842 llvm::Value *NumThreadsVal = nullptr;
6843 switch (DirectiveKind) {
6844 case OMPD_target: {
6845 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6846 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6847 return NumThreads;
6848 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6849 CGF.getContext(), CS->getCapturedStmt());
6850 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6851 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) {
6852 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6853 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6854 const auto *ThreadLimitClause =
6855 Dir->getSingleClause<OMPThreadLimitClause>();
6856 CodeGenFunction::LexicalScope Scope(
6857 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange());
6858 if (const auto *PreInit =
6859 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6860 for (const auto *I : PreInit->decls()) {
6861 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6862 CGF.EmitVarDecl(cast<VarDecl>(*I));
6863 } else {
6864 CodeGenFunction::AutoVarEmission Emission =
6865 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6866 CGF.EmitAutoVarCleanups(Emission);
6867 }
6868 }
6869 }
6870 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6871 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6872 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006873 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006874 }
6875 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) &&
6876 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) {
6877 CS = Dir->getInnermostCapturedStmt();
6878 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6879 CGF.getContext(), CS->getCapturedStmt());
6880 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6881 }
6882 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) &&
6883 !isOpenMPSimdDirective(Dir->getDirectiveKind())) {
6884 CS = Dir->getInnermostCapturedStmt();
6885 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6886 return NumThreads;
6887 }
6888 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind()))
6889 return Bld.getInt32(1);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006890 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006891 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6892 }
6893 case OMPD_target_teams: {
6894 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6895 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6896 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6897 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6898 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6899 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006900 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006901 }
6902 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6903 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6904 return NumThreads;
6905 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6906 CGF.getContext(), CS->getCapturedStmt());
6907 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6908 if (Dir->getDirectiveKind() == OMPD_distribute) {
6909 CS = Dir->getInnermostCapturedStmt();
6910 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6911 return NumThreads;
6912 }
6913 }
6914 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6915 }
6916 case OMPD_target_teams_distribute:
6917 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6918 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6919 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6920 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6921 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6922 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006923 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006924 }
6925 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal);
6926 case OMPD_target_parallel:
6927 case OMPD_target_parallel_for:
6928 case OMPD_target_parallel_for_simd:
6929 case OMPD_target_teams_distribute_parallel_for:
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006930 case OMPD_target_teams_distribute_parallel_for_simd: {
6931 llvm::Value *CondVal = nullptr;
6932 // Handle if clause. If if clause present, the number of threads is
6933 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6934 if (D.hasClausesOfKind<OMPIfClause>()) {
6935 const OMPIfClause *IfClause = nullptr;
6936 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) {
6937 if (C->getNameModifier() == OMPD_unknown ||
6938 C->getNameModifier() == OMPD_parallel) {
6939 IfClause = C;
6940 break;
6941 }
6942 }
6943 if (IfClause) {
6944 const Expr *Cond = IfClause->getCondition();
6945 bool Result;
6946 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6947 if (!Result)
6948 return Bld.getInt32(1);
6949 } else {
6950 CodeGenFunction::RunCleanupsScope Scope(CGF);
6951 CondVal = CGF.EvaluateExprAsBool(Cond);
6952 }
6953 }
6954 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006955 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6956 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6957 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6958 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6959 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6960 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006961 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006962 }
6963 if (D.hasClausesOfKind<OMPNumThreadsClause>()) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006964 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
Alexey Bataev5c427362019-04-10 19:11:33 +00006965 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>();
6966 llvm::Value *NumThreads = CGF.EmitScalarExpr(
6967 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true);
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006968 NumThreadsVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006969 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006970 ThreadLimitVal = ThreadLimitVal
Alexey Bataev5c427362019-04-10 19:11:33 +00006971 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal,
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006972 ThreadLimitVal),
6973 NumThreadsVal, ThreadLimitVal)
6974 : NumThreadsVal;
Alexey Bataev50a1c782017-12-01 21:31:08 +00006975 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006976 if (!ThreadLimitVal)
6977 ThreadLimitVal = Bld.getInt32(0);
6978 if (CondVal)
6979 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1));
6980 return ThreadLimitVal;
6981 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006982 case OMPD_target_teams_distribute_simd:
6983 case OMPD_target_simd:
6984 return Bld.getInt32(1);
6985 case OMPD_parallel:
6986 case OMPD_for:
6987 case OMPD_parallel_for:
cchen47d60942019-12-05 13:43:48 -05006988 case OMPD_parallel_master:
Alexey Bataev5c427362019-04-10 19:11:33 +00006989 case OMPD_parallel_sections:
6990 case OMPD_for_simd:
6991 case OMPD_parallel_for_simd:
6992 case OMPD_cancel:
6993 case OMPD_cancellation_point:
6994 case OMPD_ordered:
6995 case OMPD_threadprivate:
6996 case OMPD_allocate:
6997 case OMPD_task:
6998 case OMPD_simd:
6999 case OMPD_sections:
7000 case OMPD_section:
7001 case OMPD_single:
7002 case OMPD_master:
7003 case OMPD_critical:
7004 case OMPD_taskyield:
7005 case OMPD_barrier:
7006 case OMPD_taskwait:
7007 case OMPD_taskgroup:
7008 case OMPD_atomic:
7009 case OMPD_flush:
7010 case OMPD_teams:
7011 case OMPD_target_data:
7012 case OMPD_target_exit_data:
7013 case OMPD_target_enter_data:
7014 case OMPD_distribute:
7015 case OMPD_distribute_simd:
7016 case OMPD_distribute_parallel_for:
7017 case OMPD_distribute_parallel_for_simd:
7018 case OMPD_teams_distribute:
7019 case OMPD_teams_distribute_simd:
7020 case OMPD_teams_distribute_parallel_for:
7021 case OMPD_teams_distribute_parallel_for_simd:
7022 case OMPD_target_update:
7023 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00007024 case OMPD_declare_variant:
Alexey Bataev5c427362019-04-10 19:11:33 +00007025 case OMPD_declare_target:
7026 case OMPD_end_declare_target:
7027 case OMPD_declare_reduction:
7028 case OMPD_declare_mapper:
7029 case OMPD_taskloop:
7030 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00007031 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00007032 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00007033 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04007034 case OMPD_parallel_master_taskloop_simd:
Alexey Bataev5c427362019-04-10 19:11:33 +00007035 case OMPD_requires:
7036 case OMPD_unknown:
7037 break;
Samuel Antaob68e2db2016-03-03 16:20:23 +00007038 }
Alexey Bataev5c427362019-04-10 19:11:33 +00007039 llvm_unreachable("Unsupported directive kind.");
Samuel Antaob68e2db2016-03-03 16:20:23 +00007040}
7041
Samuel Antao86ace552016-04-27 22:40:57 +00007042namespace {
Alexey Bataevb3638132018-07-19 16:34:13 +00007043LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
7044
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007045// Utility to handle information from clauses associated with a given
Samuel Antao86ace552016-04-27 22:40:57 +00007046// construct that use mappable expressions (e.g. 'map' clause, 'to' clause).
7047// It provides a convenient interface to obtain the information and generate
7048// code for that information.
7049class MappableExprsHandler {
7050public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007051 /// Values for bit flags used to specify the mapping type for
Samuel Antao86ace552016-04-27 22:40:57 +00007052 /// offloading.
Alexey Bataevb3638132018-07-19 16:34:13 +00007053 enum OpenMPOffloadMappingFlags : uint64_t {
7054 /// No flags
7055 OMP_MAP_NONE = 0x0,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007056 /// Allocate memory on the device and move data from host to device.
Samuel Antao86ace552016-04-27 22:40:57 +00007057 OMP_MAP_TO = 0x01,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007058 /// Allocate memory on the device and move data from device to host.
Samuel Antao86ace552016-04-27 22:40:57 +00007059 OMP_MAP_FROM = 0x02,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007060 /// Always perform the requested mapping action on the element, even
Samuel Antao86ace552016-04-27 22:40:57 +00007061 /// if it was already mapped before.
7062 OMP_MAP_ALWAYS = 0x04,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007063 /// Delete the element from the device environment, ignoring the
Samuel Antao86ace552016-04-27 22:40:57 +00007064 /// current reference count associated with the element.
Samuel Antao6782e942016-05-26 16:48:10 +00007065 OMP_MAP_DELETE = 0x08,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007066 /// The element being mapped is a pointer-pointee pair; both the
George Rokos065755d2017-11-07 18:27:04 +00007067 /// pointer and the pointee should be mapped.
7068 OMP_MAP_PTR_AND_OBJ = 0x10,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007069 /// This flags signals that the base address of an entry should be
George Rokos065755d2017-11-07 18:27:04 +00007070 /// passed to the target kernel as an argument.
7071 OMP_MAP_TARGET_PARAM = 0x20,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007072 /// Signal that the runtime library has to return the device pointer
George Rokos065755d2017-11-07 18:27:04 +00007073 /// in the current position for the data being mapped. Used when we have the
7074 /// use_device_ptr clause.
7075 OMP_MAP_RETURN_PARAM = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007076 /// This flag signals that the reference being passed is a pointer to
Samuel Antaod486f842016-05-26 16:53:38 +00007077 /// private data.
George Rokos065755d2017-11-07 18:27:04 +00007078 OMP_MAP_PRIVATE = 0x80,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007079 /// Pass the element to the device by value.
George Rokos065755d2017-11-07 18:27:04 +00007080 OMP_MAP_LITERAL = 0x100,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007081 /// Implicit map
7082 OMP_MAP_IMPLICIT = 0x200,
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007083 /// Close is a hint to the runtime to allocate memory close to
7084 /// the target device.
7085 OMP_MAP_CLOSE = 0x400,
Alexey Bataevb3638132018-07-19 16:34:13 +00007086 /// The 16 MSBs of the flags indicate whether the entry is member of some
7087 /// struct/class.
7088 OMP_MAP_MEMBER_OF = 0xffff000000000000,
7089 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF),
Samuel Antao86ace552016-04-27 22:40:57 +00007090 };
7091
Michael Krused47b9432019-08-05 18:43:21 +00007092 /// Get the offset of the OMP_MAP_MEMBER_OF field.
7093 static unsigned getFlagMemberOffset() {
7094 unsigned Offset = 0;
7095 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1);
7096 Remain = Remain >> 1)
7097 Offset++;
7098 return Offset;
7099 }
7100
Samuel Antaocc10b852016-07-28 14:23:26 +00007101 /// Class that associates information with a base pointer to be passed to the
7102 /// runtime library.
7103 class BasePointerInfo {
7104 /// The base pointer.
7105 llvm::Value *Ptr = nullptr;
7106 /// The base declaration that refers to this device pointer, or null if
7107 /// there is none.
7108 const ValueDecl *DevPtrDecl = nullptr;
7109
7110 public:
7111 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr)
7112 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {}
7113 llvm::Value *operator*() const { return Ptr; }
7114 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; }
7115 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; }
7116 };
7117
Alexey Bataevb3638132018-07-19 16:34:13 +00007118 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>;
7119 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>;
7120 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>;
7121
7122 /// Map between a struct and the its lowest & highest elements which have been
7123 /// mapped.
7124 /// [ValueDecl *] --> {LE(FieldIndex, Pointer),
7125 /// HE(FieldIndex, Pointer)}
7126 struct StructRangeInfoTy {
7127 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = {
7128 0, Address::invalid()};
7129 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = {
7130 0, Address::invalid()};
7131 Address Base = Address::invalid();
7132 };
Samuel Antao86ace552016-04-27 22:40:57 +00007133
7134private:
Alexey Bataevb3638132018-07-19 16:34:13 +00007135 /// Kind that defines how a device pointer has to be returned.
7136 struct MapInfo {
7137 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
7138 OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
Kelvin Lief579432018-12-18 22:18:41 +00007139 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataevb3638132018-07-19 16:34:13 +00007140 bool ReturnDevicePointer = false;
7141 bool IsImplicit = false;
7142
7143 MapInfo() = default;
7144 MapInfo(
7145 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Kelvin Lief579432018-12-18 22:18:41 +00007146 OpenMPMapClauseKind MapType,
7147 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007148 bool ReturnDevicePointer, bool IsImplicit)
Kelvin Lief579432018-12-18 22:18:41 +00007149 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
Alexey Bataevb3638132018-07-19 16:34:13 +00007150 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {}
7151 };
7152
7153 /// If use_device_ptr is used on a pointer which is a struct member and there
7154 /// is no map information about it, then emission of that entry is deferred
7155 /// until the whole struct has been processed.
7156 struct DeferredDevicePtrEntryTy {
7157 const Expr *IE = nullptr;
7158 const ValueDecl *VD = nullptr;
7159
7160 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD)
7161 : IE(IE), VD(VD) {}
7162 };
7163
Michael Krused47b9432019-08-05 18:43:21 +00007164 /// The target directive from where the mappable clauses were extracted. It
7165 /// is either a executable directive or a user-defined mapper directive.
7166 llvm::PointerUnion<const OMPExecutableDirective *,
7167 const OMPDeclareMapperDecl *>
7168 CurDir;
Samuel Antao86ace552016-04-27 22:40:57 +00007169
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007170 /// Function the directive is being generated for.
Samuel Antao86ace552016-04-27 22:40:57 +00007171 CodeGenFunction &CGF;
7172
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007173 /// Set of all first private variables in the current directive.
Alexey Bataevf288cf92019-06-27 18:53:07 +00007174 /// bool data is set to true if the variable is implicitly marked as
7175 /// firstprivate, false otherwise.
7176 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls;
Samuel Antaod486f842016-05-26 16:53:38 +00007177
Samuel Antao6890b092016-07-28 14:25:09 +00007178 /// Map between device pointer declarations and their expression components.
7179 /// The key value for declarations in 'this' is null.
7180 llvm::DenseMap<
7181 const ValueDecl *,
7182 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7183 DevPointersMap;
7184
Samuel Antao86ace552016-04-27 22:40:57 +00007185 llvm::Value *getExprTypeSize(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007186 QualType ExprTy = E->getType().getCanonicalType();
Samuel Antao86ace552016-04-27 22:40:57 +00007187
7188 // Reference types are ignored for mapping purposes.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007189 if (const auto *RefTy = ExprTy->getAs<ReferenceType>())
Samuel Antao86ace552016-04-27 22:40:57 +00007190 ExprTy = RefTy->getPointeeType().getCanonicalType();
7191
7192 // Given that an array section is considered a built-in type, we need to
7193 // do the calculation based on the length of the section instead of relying
7194 // on CGF.getTypeSize(E->getType()).
7195 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) {
7196 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType(
7197 OAE->getBase()->IgnoreParenImpCasts())
7198 .getCanonicalType();
7199
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007200 // If there is no length associated with the expression and lower bound is
7201 // not specified too, that means we are using the whole length of the
7202 // base.
7203 if (!OAE->getLength() && OAE->getColonLoc().isValid() &&
7204 !OAE->getLowerBound())
Samuel Antao86ace552016-04-27 22:40:57 +00007205 return CGF.getTypeSize(BaseTy);
7206
7207 llvm::Value *ElemSize;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007208 if (const auto *PTy = BaseTy->getAs<PointerType>()) {
Samuel Antao86ace552016-04-27 22:40:57 +00007209 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007210 } else {
7211 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr());
Samuel Antao86ace552016-04-27 22:40:57 +00007212 assert(ATy && "Expecting array type if not a pointer type.");
7213 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType());
7214 }
7215
7216 // If we don't have a length at this point, that is because we have an
7217 // array section with a single element.
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007218 if (!OAE->getLength() && OAE->getColonLoc().isInvalid())
Samuel Antao86ace552016-04-27 22:40:57 +00007219 return ElemSize;
7220
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007221 if (const Expr *LenExpr = OAE->getLength()) {
Michael Liaod838cf72019-10-02 00:22:45 +00007222 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr);
7223 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(),
7224 CGF.getContext().getSizeType(),
7225 LenExpr->getExprLoc());
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007226 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize);
7227 }
7228 assert(!OAE->getLength() && OAE->getColonLoc().isValid() &&
7229 OAE->getLowerBound() && "expected array_section[lb:].");
7230 // Size = sizetype - lb * elemtype;
7231 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy);
7232 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound());
7233 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(),
7234 CGF.getContext().getSizeType(),
7235 OAE->getLowerBound()->getExprLoc());
7236 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize);
7237 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal);
7238 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal);
7239 LengthVal = CGF.Builder.CreateSelect(
7240 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0));
7241 return LengthVal;
Samuel Antao86ace552016-04-27 22:40:57 +00007242 }
7243 return CGF.getTypeSize(ExprTy);
7244 }
7245
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007246 /// Return the corresponding bits for a given map clause modifier. Add
Samuel Antao86ace552016-04-27 22:40:57 +00007247 /// a flag marking the map as a pointer if requested. Add a flag marking the
Samuel Antao6782e942016-05-26 16:48:10 +00007248 /// map as the first one of a series of maps that relate to the same map
7249 /// expression.
Kelvin Lief579432018-12-18 22:18:41 +00007250 OpenMPOffloadMappingFlags getMapTypeBits(
7251 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
7252 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const {
Alexey Bataevb3638132018-07-19 16:34:13 +00007253 OpenMPOffloadMappingFlags Bits =
7254 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE;
Samuel Antao86ace552016-04-27 22:40:57 +00007255 switch (MapType) {
7256 case OMPC_MAP_alloc:
Samuel Antao6782e942016-05-26 16:48:10 +00007257 case OMPC_MAP_release:
7258 // alloc and release is the default behavior in the runtime library, i.e.
7259 // if we don't pass any bits alloc/release that is what the runtime is
7260 // going to do. Therefore, we don't need to signal anything for these two
7261 // type modifiers.
Samuel Antao86ace552016-04-27 22:40:57 +00007262 break;
7263 case OMPC_MAP_to:
Alexey Bataevb3638132018-07-19 16:34:13 +00007264 Bits |= OMP_MAP_TO;
Samuel Antao86ace552016-04-27 22:40:57 +00007265 break;
7266 case OMPC_MAP_from:
Alexey Bataevb3638132018-07-19 16:34:13 +00007267 Bits |= OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007268 break;
7269 case OMPC_MAP_tofrom:
Alexey Bataevb3638132018-07-19 16:34:13 +00007270 Bits |= OMP_MAP_TO | OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007271 break;
7272 case OMPC_MAP_delete:
Alexey Bataevb3638132018-07-19 16:34:13 +00007273 Bits |= OMP_MAP_DELETE;
Samuel Antao86ace552016-04-27 22:40:57 +00007274 break;
Alexey Bataevb3638132018-07-19 16:34:13 +00007275 case OMPC_MAP_unknown:
Samuel Antao86ace552016-04-27 22:40:57 +00007276 llvm_unreachable("Unexpected map type!");
Samuel Antao86ace552016-04-27 22:40:57 +00007277 }
7278 if (AddPtrFlag)
George Rokos065755d2017-11-07 18:27:04 +00007279 Bits |= OMP_MAP_PTR_AND_OBJ;
7280 if (AddIsTargetParamFlag)
7281 Bits |= OMP_MAP_TARGET_PARAM;
Kelvin Lief579432018-12-18 22:18:41 +00007282 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always)
7283 != MapModifiers.end())
Samuel Antao86ace552016-04-27 22:40:57 +00007284 Bits |= OMP_MAP_ALWAYS;
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007285 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close)
7286 != MapModifiers.end())
7287 Bits |= OMP_MAP_CLOSE;
Samuel Antao86ace552016-04-27 22:40:57 +00007288 return Bits;
7289 }
7290
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007291 /// Return true if the provided expression is a final array section. A
Samuel Antao86ace552016-04-27 22:40:57 +00007292 /// final array section, is one whose length can't be proved to be one.
7293 bool isFinalArraySectionExpression(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007294 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
Samuel Antao86ace552016-04-27 22:40:57 +00007295
7296 // It is not an array section and therefore not a unity-size one.
7297 if (!OASE)
7298 return false;
7299
7300 // An array section with no colon always refer to a single element.
7301 if (OASE->getColonLoc().isInvalid())
7302 return false;
7303
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007304 const Expr *Length = OASE->getLength();
Samuel Antao86ace552016-04-27 22:40:57 +00007305
7306 // If we don't have a length we have to check if the array has size 1
7307 // for this dimension. Also, we should always expect a length if the
7308 // base type is pointer.
7309 if (!Length) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007310 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType(
7311 OASE->getBase()->IgnoreParenImpCasts())
7312 .getCanonicalType();
7313 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
Samuel Antao86ace552016-04-27 22:40:57 +00007314 return ATy->getSize().getSExtValue() != 1;
7315 // If we don't have a constant dimension length, we have to consider
7316 // the current section as having any size, so it is not necessarily
7317 // unitary. If it happen to be unity size, that's user fault.
7318 return true;
7319 }
7320
7321 // Check if the length evaluates to 1.
Fangrui Song407659a2018-11-30 23:41:18 +00007322 Expr::EvalResult Result;
7323 if (!Length->EvaluateAsInt(Result, CGF.getContext()))
Samuel Antao86ace552016-04-27 22:40:57 +00007324 return true; // Can have more that size 1.
7325
Fangrui Song407659a2018-11-30 23:41:18 +00007326 llvm::APSInt ConstLength = Result.Val.getInt();
Samuel Antao86ace552016-04-27 22:40:57 +00007327 return ConstLength.getSExtValue() != 1;
7328 }
7329
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007330 /// Generate the base pointers, section pointers, sizes and map type
Samuel Antao86ace552016-04-27 22:40:57 +00007331 /// bits for the provided map type, map modifier, and expression components.
7332 /// \a IsFirstComponent should be set to true if the provided set of
7333 /// components is the first associated with a capture.
7334 void generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00007335 OpenMPMapClauseKind MapType,
7336 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Samuel Antao86ace552016-04-27 22:40:57 +00007337 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Samuel Antaocc10b852016-07-28 14:23:26 +00007338 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007339 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
Alexey Bataevb3638132018-07-19 16:34:13 +00007340 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007341 bool IsImplicit,
7342 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7343 OverlappedElements = llvm::None) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007344 // The following summarizes what has to be generated for each map and the
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00007345 // types below. The generated information is expressed in this order:
Samuel Antao86ace552016-04-27 22:40:57 +00007346 // base pointer, section pointer, size, flags
7347 // (to add to the ones that come from the map type and modifier).
7348 //
7349 // double d;
7350 // int i[100];
7351 // float *p;
7352 //
7353 // struct S1 {
7354 // int i;
7355 // float f[50];
7356 // }
7357 // struct S2 {
7358 // int i;
7359 // float f[50];
7360 // S1 s;
7361 // double *p;
7362 // struct S2 *ps;
7363 // }
7364 // S2 s;
7365 // S2 *ps;
7366 //
7367 // map(d)
Alexey Bataevb3638132018-07-19 16:34:13 +00007368 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007369 //
7370 // map(i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007371 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007372 //
7373 // map(i[1:23])
Alexey Bataevb3638132018-07-19 16:34:13 +00007374 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007375 //
7376 // map(p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007377 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007378 //
7379 // map(p[1:24])
Alexey Bataevb3638132018-07-19 16:34:13 +00007380 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007381 //
7382 // map(s)
Alexey Bataevb3638132018-07-19 16:34:13 +00007383 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007384 //
7385 // map(s.i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007386 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007387 //
7388 // map(s.s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007389 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007390 //
7391 // map(s.p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007392 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007393 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007394 // map(to: s.p[:22])
7395 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*)
7396 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**)
7397 // &(s.p), &(s.p[0]), 22*sizeof(double),
7398 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***)
7399 // (*) alloc space for struct members, only this is a target parameter
7400 // (**) map the pointer (nothing to be mapped in this example) (the compiler
7401 // optimizes this entry out, same in the examples below)
7402 // (***) map the pointee (map: to)
Samuel Antao86ace552016-04-27 22:40:57 +00007403 //
7404 // map(s.ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007405 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007406 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007407 // map(from: s.ps->s.i)
7408 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7409 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7410 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007411 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007412 // map(to: s.ps->ps)
7413 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7414 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7415 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007416 //
7417 // map(s.ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007418 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7419 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7420 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7421 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007422 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007423 // map(to: s.ps->ps->s.f[:22])
7424 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7425 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7426 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7427 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007428 //
7429 // map(ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007430 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007431 //
7432 // map(ps->i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007433 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007434 //
7435 // map(ps->s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007436 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007437 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007438 // map(from: ps->p)
7439 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007440 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007441 // map(to: ps->p[:22])
7442 // ps, &(ps->p), sizeof(double*), TARGET_PARAM
7443 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1)
7444 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007445 //
7446 // map(ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007447 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007448 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007449 // map(from: ps->ps->s.i)
7450 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7451 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7452 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007453 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007454 // map(from: ps->ps->ps)
7455 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7456 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7457 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007458 //
7459 // map(ps->ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007460 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7461 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7462 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7463 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007464 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007465 // map(to: ps->ps->ps->s.f[:22])
7466 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7467 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7468 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7469 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
7470 //
7471 // map(to: s.f[:22]) map(from: s.p[:33])
7472 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) +
7473 // sizeof(double*) (**), TARGET_PARAM
7474 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO
7475 // &s, &(s.p), sizeof(double*), MEMBER_OF(1)
7476 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7477 // (*) allocate contiguous space needed to fit all mapped members even if
7478 // we allocate space for members not mapped (in this example,
7479 // s.f[22..49] and s.s are not mapped, yet we must allocate space for
7480 // them as well because they fall between &s.f[0] and &s.p)
7481 //
7482 // map(from: s.f[:22]) map(to: ps->p[:33])
7483 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM
7484 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7485 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*)
7486 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO
7487 // (*) the struct this entry pertains to is the 2nd element in the list of
7488 // arguments, hence MEMBER_OF(2)
7489 //
7490 // map(from: s.f[:22], s.s) map(to: ps->p[:33])
7491 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM
7492 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM
7493 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM
7494 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7495 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*)
7496 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO
7497 // (*) the struct this entry pertains to is the 4th element in the list
7498 // of arguments, hence MEMBER_OF(4)
Samuel Antao86ace552016-04-27 22:40:57 +00007499
7500 // Track if the map information being generated is the first for a capture.
7501 bool IsCaptureFirstInfo = IsFirstComponentList;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007502 // When the variable is on a declare target link or in a to clause with
7503 // unified memory, a reference is needed to hold the host/device address
7504 // of the variable.
7505 bool RequiresReference = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007506
7507 // Scan the components from the base to the complete expression.
7508 auto CI = Components.rbegin();
7509 auto CE = Components.rend();
7510 auto I = CI;
7511
7512 // Track if the map information being generated is the first for a list of
7513 // components.
7514 bool IsExpressionFirstInfo = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00007515 Address BP = Address::invalid();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007516 const Expr *AssocExpr = I->getAssociatedExpression();
7517 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7518 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
Samuel Antao86ace552016-04-27 22:40:57 +00007519
Patrick Lystere13b1e32019-01-02 19:28:48 +00007520 if (isa<MemberExpr>(AssocExpr)) {
Samuel Antao86ace552016-04-27 22:40:57 +00007521 // The base is the 'this' pointer. The content of the pointer is going
7522 // to be the base of the field being mapped.
Alexey Bataevb3638132018-07-19 16:34:13 +00007523 BP = CGF.LoadCXXThisAddress();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007524 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7525 (OASE &&
7526 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08007527 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF);
Samuel Antao86ace552016-04-27 22:40:57 +00007528 } else {
7529 // The base is the reference to the variable.
7530 // BP = &Var.
Akira Hatanakaf139ae32019-12-03 15:17:01 -08007531 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF);
Alexey Bataev92327c52018-03-26 16:40:55 +00007532 if (const auto *VD =
7533 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7534 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007535 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7536 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7537 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
7538 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) {
7539 RequiresReference = true;
7540 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataev2c1dffe2018-04-16 20:34:41 +00007541 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007542 }
Alexey Bataev92327c52018-03-26 16:40:55 +00007543 }
Samuel Antao86ace552016-04-27 22:40:57 +00007544
7545 // If the variable is a pointer and is being dereferenced (i.e. is not
Nico Webera6916892016-06-10 18:53:04 +00007546 // the last component), the base has to be the pointer itself, not its
Samuel Antao403ffd42016-07-27 22:49:49 +00007547 // reference. References are ignored for mapping purposes.
7548 QualType Ty =
7549 I->getAssociatedDeclaration()->getType().getNonReferenceType();
7550 if (Ty->isAnyPointerType() && std::next(I) != CE) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007551 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
Samuel Antao86ace552016-04-27 22:40:57 +00007552
7553 // We do not need to generate individual map information for the
7554 // pointer, it can be associated with the combined storage.
7555 ++I;
7556 }
7557 }
7558
Alexey Bataevb3638132018-07-19 16:34:13 +00007559 // Track whether a component of the list should be marked as MEMBER_OF some
7560 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry
7561 // in a component list should be marked as MEMBER_OF, all subsequent entries
7562 // do not belong to the base struct. E.g.
7563 // struct S2 s;
7564 // s.ps->ps->ps->f[:]
7565 // (1) (2) (3) (4)
7566 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a
7567 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3)
7568 // is the pointee of ps(2) which is not member of struct s, so it should not
7569 // be marked as such (it is still PTR_AND_OBJ).
7570 // The variable is initialized to false so that PTR_AND_OBJ entries which
7571 // are not struct members are not considered (e.g. array of pointers to
7572 // data).
7573 bool ShouldBeMemberOf = false;
7574
7575 // Variable keeping track of whether or not we have encountered a component
7576 // in the component list which is a member expression. Useful when we have a
7577 // pointer or a final array section, in which case it is the previous
7578 // component in the list which tells us whether we have a member expression.
7579 // E.g. X.f[:]
7580 // While processing the final array section "[:]" it is "f" which tells us
7581 // whether we are dealing with a member of a declared struct.
7582 const MemberExpr *EncounteredME = nullptr;
7583
Samuel Antao86ace552016-04-27 22:40:57 +00007584 for (; I != CE; ++I) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007585 // If the current component is member of a struct (parent struct) mark it.
7586 if (!EncounteredME) {
7587 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7588 // If we encounter a PTR_AND_OBJ entry from now on it should be marked
7589 // as MEMBER_OF the parent struct.
7590 if (EncounteredME)
7591 ShouldBeMemberOf = true;
7592 }
7593
Samuel Antao86ace552016-04-27 22:40:57 +00007594 auto Next = std::next(I);
7595
7596 // We need to generate the addresses and sizes if this is the last
7597 // component, if the component is a pointer or if it is an array section
7598 // whose length can't be proved to be one. If this is a pointer, it
7599 // becomes the base address for the following components.
7600
7601 // A final array section, is one whose length can't be proved to be one.
7602 bool IsFinalArraySection =
7603 isFinalArraySectionExpression(I->getAssociatedExpression());
7604
7605 // Get information on whether the element is a pointer. Have to do a
7606 // special treatment for array sections given that they are built-in
7607 // types.
7608 const auto *OASE =
7609 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression());
7610 bool IsPointer =
Alexey Bataevb3638132018-07-19 16:34:13 +00007611 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE)
7612 .getCanonicalType()
7613 ->isAnyPointerType()) ||
Samuel Antao86ace552016-04-27 22:40:57 +00007614 I->getAssociatedExpression()->getType()->isAnyPointerType();
7615
7616 if (Next == CE || IsPointer || IsFinalArraySection) {
Samuel Antao86ace552016-04-27 22:40:57 +00007617 // If this is not the last component, we expect the pointer to be
7618 // associated with an array expression or member expression.
7619 assert((Next == CE ||
7620 isa<MemberExpr>(Next->getAssociatedExpression()) ||
7621 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||
7622 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) &&
7623 "Unexpected expression");
7624
Akira Hatanakaf139ae32019-12-03 15:17:01 -08007625 Address LB = CGF.EmitOMPSharedLValue(I->getAssociatedExpression())
7626 .getAddress(CGF);
Samuel Antao86ace552016-04-27 22:40:57 +00007627
Alexey Bataevb3638132018-07-19 16:34:13 +00007628 // If this component is a pointer inside the base struct then we don't
7629 // need to create any entry for it - it will be combined with the object
7630 // it is pointing to into a single PTR_AND_OBJ entry.
7631 bool IsMemberPointer =
7632 IsPointer && EncounteredME &&
7633 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) ==
7634 EncounteredME);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007635 if (!OverlappedElements.empty()) {
7636 // Handle base element with the info for overlapped elements.
7637 assert(!PartialStruct.Base.isValid() && "The base element is set.");
7638 assert(Next == CE &&
7639 "Expected last element for the overlapped elements.");
7640 assert(!IsPointer &&
7641 "Unexpected base element with the pointer type.");
7642 // Mark the whole struct as the struct that requires allocation on the
7643 // device.
7644 PartialStruct.LowestElem = {0, LB};
7645 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(
7646 I->getAssociatedExpression()->getType());
7647 Address HB = CGF.Builder.CreateConstGEP(
7648 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB,
7649 CGF.VoidPtrTy),
James Y Knight751fe282019-02-09 22:22:28 +00007650 TypeSize.getQuantity() - 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007651 PartialStruct.HighestElem = {
7652 std::numeric_limits<decltype(
7653 PartialStruct.HighestElem.first)>::max(),
7654 HB};
7655 PartialStruct.Base = BP;
7656 // Emit data for non-overlapped data.
7657 OpenMPOffloadMappingFlags Flags =
7658 OMP_MAP_MEMBER_OF |
Kelvin Lief579432018-12-18 22:18:41 +00007659 getMapTypeBits(MapType, MapModifiers, IsImplicit,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007660 /*AddPtrFlag=*/false,
7661 /*AddIsTargetParamFlag=*/false);
7662 LB = BP;
7663 llvm::Value *Size = nullptr;
7664 // Do bitcopy of all non-overlapped structure elements.
7665 for (OMPClauseMappableExprCommon::MappableExprComponentListRef
7666 Component : OverlappedElements) {
7667 Address ComponentLB = Address::invalid();
7668 for (const OMPClauseMappableExprCommon::MappableComponent &MC :
7669 Component) {
7670 if (MC.getAssociatedDeclaration()) {
7671 ComponentLB =
7672 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
Akira Hatanakaf139ae32019-12-03 15:17:01 -08007673 .getAddress(CGF);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007674 Size = CGF.Builder.CreatePtrDiff(
7675 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()),
7676 CGF.EmitCastToVoidPtr(LB.getPointer()));
7677 break;
7678 }
7679 }
7680 BasePointers.push_back(BP.getPointer());
7681 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007682 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty,
7683 /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007684 Types.push_back(Flags);
James Y Knight751fe282019-02-09 22:22:28 +00007685 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007686 }
7687 BasePointers.push_back(BP.getPointer());
7688 Pointers.push_back(LB.getPointer());
7689 Size = CGF.Builder.CreatePtrDiff(
7690 CGF.EmitCastToVoidPtr(
James Y Knight751fe282019-02-09 22:22:28 +00007691 CGF.Builder.CreateConstGEP(HB, 1).getPointer()),
Alexey Bataeve82445f2018-09-20 13:54:02 +00007692 CGF.EmitCastToVoidPtr(LB.getPointer()));
Alexey Bataeva90fc662019-06-25 16:00:43 +00007693 Sizes.push_back(
7694 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007695 Types.push_back(Flags);
7696 break;
7697 }
7698 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
Alexey Bataevb3638132018-07-19 16:34:13 +00007699 if (!IsMemberPointer) {
7700 BasePointers.push_back(BP.getPointer());
7701 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007702 Sizes.push_back(
7703 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Samuel Antao03a3cec2016-07-27 22:52:16 +00007704
Alexey Bataevb3638132018-07-19 16:34:13 +00007705 // We need to add a pointer flag for each map that comes from the
7706 // same expression except for the first one. We also need to signal
7707 // this map is the first one that relates with the current capture
7708 // (there is a set of entries for each capture).
7709 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
Kelvin Lief579432018-12-18 22:18:41 +00007710 MapType, MapModifiers, IsImplicit,
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007711 !IsExpressionFirstInfo || RequiresReference,
7712 IsCaptureFirstInfo && !RequiresReference);
Alexey Bataevb3638132018-07-19 16:34:13 +00007713
7714 if (!IsExpressionFirstInfo) {
7715 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007716 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags.
Alexey Bataevb3638132018-07-19 16:34:13 +00007717 if (IsPointer)
7718 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS |
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007719 OMP_MAP_DELETE | OMP_MAP_CLOSE);
Alexey Bataevb3638132018-07-19 16:34:13 +00007720
7721 if (ShouldBeMemberOf) {
7722 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag
7723 // should be later updated with the correct value of MEMBER_OF.
7724 Flags |= OMP_MAP_MEMBER_OF;
7725 // From now on, all subsequent PTR_AND_OBJ entries should not be
7726 // marked as MEMBER_OF.
7727 ShouldBeMemberOf = false;
7728 }
7729 }
7730
7731 Types.push_back(Flags);
Samuel Antao03a3cec2016-07-27 22:52:16 +00007732 }
7733
Alexey Bataevb3638132018-07-19 16:34:13 +00007734 // If we have encountered a member expression so far, keep track of the
7735 // mapped member. If the parent is "*this", then the value declaration
7736 // is nullptr.
7737 if (EncounteredME) {
7738 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl());
7739 unsigned FieldIndex = FD->getFieldIndex();
Samuel Antao03a3cec2016-07-27 22:52:16 +00007740
Alexey Bataevb3638132018-07-19 16:34:13 +00007741 // Update info about the lowest and highest elements for this struct
7742 if (!PartialStruct.Base.isValid()) {
7743 PartialStruct.LowestElem = {FieldIndex, LB};
7744 PartialStruct.HighestElem = {FieldIndex, LB};
7745 PartialStruct.Base = BP;
7746 } else if (FieldIndex < PartialStruct.LowestElem.first) {
7747 PartialStruct.LowestElem = {FieldIndex, LB};
7748 } else if (FieldIndex > PartialStruct.HighestElem.first) {
7749 PartialStruct.HighestElem = {FieldIndex, LB};
7750 }
7751 }
Samuel Antao86ace552016-04-27 22:40:57 +00007752
7753 // If we have a final array section, we are done with this expression.
7754 if (IsFinalArraySection)
7755 break;
7756
7757 // The pointer becomes the base for the next element.
7758 if (Next != CE)
7759 BP = LB;
7760
7761 IsExpressionFirstInfo = false;
7762 IsCaptureFirstInfo = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007763 }
7764 }
7765 }
7766
Alexey Bataevb3638132018-07-19 16:34:13 +00007767 /// Return the adjusted map modifiers if the declaration a capture refers to
7768 /// appears in a first-private clause. This is expected to be used only with
7769 /// directives that start with 'target'.
7770 MappableExprsHandler::OpenMPOffloadMappingFlags
7771 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const {
7772 assert(Cap.capturesVariable() && "Expected capture by reference only!");
7773
7774 // A first private variable captured by reference will use only the
7775 // 'private ptr' and 'map to' flag. Return the right flags if the captured
7776 // declaration is known as first-private in this handler.
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007777 if (FirstPrivateDecls.count(Cap.getCapturedVar())) {
7778 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) &&
7779 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef)
7780 return MappableExprsHandler::OMP_MAP_ALWAYS |
7781 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataevc2b831f2019-04-02 16:03:40 +00007782 if (Cap.getCapturedVar()->getType()->isAnyPointerType())
7783 return MappableExprsHandler::OMP_MAP_TO |
7784 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ;
Alexey Bataevb3638132018-07-19 16:34:13 +00007785 return MappableExprsHandler::OMP_MAP_PRIVATE |
7786 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007787 }
Alexey Bataevb3638132018-07-19 16:34:13 +00007788 return MappableExprsHandler::OMP_MAP_TO |
7789 MappableExprsHandler::OMP_MAP_FROM;
7790 }
7791
7792 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) {
Michael Krused47b9432019-08-05 18:43:21 +00007793 // Rotate by getFlagMemberOffset() bits.
Alexey Bataevb3638132018-07-19 16:34:13 +00007794 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1)
Michael Krused47b9432019-08-05 18:43:21 +00007795 << getFlagMemberOffset());
Alexey Bataevb3638132018-07-19 16:34:13 +00007796 }
7797
7798 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags,
7799 OpenMPOffloadMappingFlags MemberOfFlag) {
7800 // If the entry is PTR_AND_OBJ but has not been marked with the special
7801 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be
7802 // marked as MEMBER_OF.
7803 if ((Flags & OMP_MAP_PTR_AND_OBJ) &&
7804 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF))
7805 return;
7806
7807 // Reset the placeholder value to prepare the flag for the assignment of the
7808 // proper MEMBER_OF value.
7809 Flags &= ~OMP_MAP_MEMBER_OF;
7810 Flags |= MemberOfFlag;
7811 }
7812
Alexey Bataeve82445f2018-09-20 13:54:02 +00007813 void getPlainLayout(const CXXRecordDecl *RD,
7814 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
7815 bool AsBase) const {
7816 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD);
7817
7818 llvm::StructType *St =
7819 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType();
7820
7821 unsigned NumElements = St->getNumElements();
7822 llvm::SmallVector<
7823 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
7824 RecordLayout(NumElements);
7825
7826 // Fill bases.
7827 for (const auto &I : RD->bases()) {
7828 if (I.isVirtual())
7829 continue;
7830 const auto *Base = I.getType()->getAsCXXRecordDecl();
7831 // Ignore empty bases.
7832 if (Base->isEmpty() || CGF.getContext()
7833 .getASTRecordLayout(Base)
7834 .getNonVirtualSize()
7835 .isZero())
7836 continue;
7837
7838 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
7839 RecordLayout[FieldIndex] = Base;
7840 }
7841 // Fill in virtual bases.
7842 for (const auto &I : RD->vbases()) {
7843 const auto *Base = I.getType()->getAsCXXRecordDecl();
7844 // Ignore empty bases.
7845 if (Base->isEmpty())
7846 continue;
7847 unsigned FieldIndex = RL.getVirtualBaseIndex(Base);
7848 if (RecordLayout[FieldIndex])
7849 continue;
7850 RecordLayout[FieldIndex] = Base;
7851 }
7852 // Fill in all the fields.
7853 assert(!RD->isUnion() && "Unexpected union.");
7854 for (const auto *Field : RD->fields()) {
7855 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
7856 // will fill in later.)
Richard Smith78b239e2019-06-20 20:44:45 +00007857 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) {
Alexey Bataeve82445f2018-09-20 13:54:02 +00007858 unsigned FieldIndex = RL.getLLVMFieldNo(Field);
7859 RecordLayout[FieldIndex] = Field;
7860 }
7861 }
7862 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
7863 &Data : RecordLayout) {
7864 if (Data.isNull())
7865 continue;
7866 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>())
7867 getPlainLayout(Base, Layout, /*AsBase=*/true);
7868 else
7869 Layout.push_back(Data.get<const FieldDecl *>());
7870 }
7871 }
7872
Alexey Bataevb3638132018-07-19 16:34:13 +00007873public:
7874 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
Michael Krused47b9432019-08-05 18:43:21 +00007875 : CurDir(&Dir), CGF(CGF) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007876 // Extract firstprivate clause information.
7877 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>())
7878 for (const auto *D : C->varlists())
Alexey Bataevf288cf92019-06-27 18:53:07 +00007879 FirstPrivateDecls.try_emplace(
7880 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit());
Alexey Bataevb3638132018-07-19 16:34:13 +00007881 // Extract device pointer clause information.
7882 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
7883 for (auto L : C->component_lists())
7884 DevPointersMap[L.first].push_back(L.second);
7885 }
7886
Michael Krused47b9432019-08-05 18:43:21 +00007887 /// Constructor for the declare mapper directive.
7888 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF)
7889 : CurDir(&Dir), CGF(CGF) {}
7890
Alexey Bataevb3638132018-07-19 16:34:13 +00007891 /// Generate code for the combined entry if we have a partially mapped struct
7892 /// and take care of the mapping flags of the arguments corresponding to
7893 /// individual struct members.
7894 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers,
7895 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7896 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes,
7897 const StructRangeInfoTy &PartialStruct) const {
7898 // Base is the base of the struct
7899 BasePointers.push_back(PartialStruct.Base.getPointer());
7900 // Pointer is the address of the lowest element
7901 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer();
7902 Pointers.push_back(LB);
7903 // Size is (addr of {highest+1} element) - (addr of lowest element)
7904 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer();
7905 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1);
7906 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy);
7907 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy);
7908 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00007909 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00007910 /*isSigned=*/false);
Alexey Bataevb3638132018-07-19 16:34:13 +00007911 Sizes.push_back(Size);
7912 // Map type is always TARGET_PARAM
7913 Types.push_back(OMP_MAP_TARGET_PARAM);
7914 // Remove TARGET_PARAM flag from the first element
7915 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM;
7916
7917 // All other current entries will be MEMBER_OF the combined entry
7918 // (except for PTR_AND_OBJ entries which do not have a placeholder value
7919 // 0xFFFF in the MEMBER_OF field).
7920 OpenMPOffloadMappingFlags MemberOfFlag =
7921 getMemberOfFlag(BasePointers.size() - 1);
7922 for (auto &M : CurTypes)
7923 setCorrectMemberOfFlag(M, MemberOfFlag);
7924 }
7925
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007926 /// Generate all the base pointers, section pointers, sizes and map
Samuel Antaocc10b852016-07-28 14:23:26 +00007927 /// types for the extracted mappable expressions. Also, for each item that
7928 /// relates with a device pointer, a pair of the relevant declaration and
7929 /// index where it occurs is appended to the device pointers info array.
7930 void generateAllInfo(MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007931 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7932 MapFlagsArrayTy &Types) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007933 // We have to process the component lists that relate with the same
7934 // declaration in a single chunk so that we can generate the map flags
7935 // correctly. Therefore, we organize all lists in a map.
Alexey Bataev5d1c3f62017-06-27 15:46:42 +00007936 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
Samuel Antao8d2d7302016-05-26 18:30:22 +00007937
7938 // Helper function to fill the information map for the different supported
7939 // clauses.
Samuel Antaocc10b852016-07-28 14:23:26 +00007940 auto &&InfoGen = [&Info](
7941 const ValueDecl *D,
7942 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
Kelvin Lief579432018-12-18 22:18:41 +00007943 OpenMPMapClauseKind MapType,
7944 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007945 bool ReturnDevicePointer, bool IsImplicit) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007946 const ValueDecl *VD =
7947 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
Kelvin Lief579432018-12-18 22:18:41 +00007948 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007949 IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00007950 };
Samuel Antao8d2d7302016-05-26 18:30:22 +00007951
Michael Krused47b9432019-08-05 18:43:21 +00007952 assert(CurDir.is<const OMPExecutableDirective *>() &&
7953 "Expect a executable directive");
7954 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
7955 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>())
Mark de Wever51abceb2019-11-12 20:48:11 +01007956 for (const auto L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007957 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(),
Alexey Bataevb3638132018-07-19 16:34:13 +00007958 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007959 }
Michael Krused47b9432019-08-05 18:43:21 +00007960 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>())
Mark de Wever51abceb2019-11-12 20:48:11 +01007961 for (const auto L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007962 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007963 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007964 }
Michael Krused47b9432019-08-05 18:43:21 +00007965 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>())
Mark de Wever51abceb2019-11-12 20:48:11 +01007966 for (const auto L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007967 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007968 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007969 }
Samuel Antao86ace552016-04-27 22:40:57 +00007970
Samuel Antaocc10b852016-07-28 14:23:26 +00007971 // Look at the use_device_ptr clause information and mark the existing map
7972 // entries as such. If there is no map information for an entry in the
7973 // use_device_ptr list, we create one with map type 'alloc' and zero size
Alexey Bataevb3638132018-07-19 16:34:13 +00007974 // section. It is the user fault if that was not mapped before. If there is
7975 // no map information and the pointer is a struct member, then we defer the
7976 // emission of that entry until the whole struct has been processed.
7977 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>>
7978 DeferredInfo;
7979
Alexey Bataevb3638132018-07-19 16:34:13 +00007980 for (const auto *C :
Michael Krused47b9432019-08-05 18:43:21 +00007981 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) {
Mark de Wever51abceb2019-11-12 20:48:11 +01007982 for (const auto L : C->component_lists()) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007983 assert(!L.second.empty() && "Not expecting empty list of components!");
7984 const ValueDecl *VD = L.second.back().getAssociatedDeclaration();
7985 VD = cast<ValueDecl>(VD->getCanonicalDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007986 const Expr *IE = L.second.back().getAssociatedExpression();
Samuel Antaocc10b852016-07-28 14:23:26 +00007987 // If the first component is a member expression, we have to look into
7988 // 'this', which maps to null in the map of map information. Otherwise
7989 // look directly for the information.
7990 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
7991
7992 // We potentially have map information for this declaration already.
7993 // Look for the first set of components that refer to it.
7994 if (It != Info.end()) {
7995 auto CI = std::find_if(
7996 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) {
7997 return MI.Components.back().getAssociatedDeclaration() == VD;
7998 });
7999 // If we found a map entry, signal that the pointer has to be returned
8000 // and move on to the next declaration.
8001 if (CI != It->second.end()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00008002 CI->ReturnDevicePointer = true;
Samuel Antaocc10b852016-07-28 14:23:26 +00008003 continue;
8004 }
8005 }
8006
8007 // We didn't find any match in our map information - generate a zero
Alexey Bataevb3638132018-07-19 16:34:13 +00008008 // size array section - if the pointer is a struct member we defer this
8009 // action until the whole struct has been processed.
Alexey Bataevb3638132018-07-19 16:34:13 +00008010 if (isa<MemberExpr>(IE)) {
8011 // Insert the pointer into Info to be processed by
8012 // generateInfoForComponentList. Because it is a member pointer
8013 // without a pointee, no entry will be generated for it, therefore
8014 // we need to generate one after the whole struct has been processed.
8015 // Nonetheless, generateInfoForComponentList must be called to take
8016 // the pointer into account for the calculation of the range of the
8017 // partial struct.
Kelvin Lief579432018-12-18 22:18:41 +00008018 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00008019 /*ReturnDevicePointer=*/false, C->isImplicit());
8020 DeferredInfo[nullptr].emplace_back(IE, VD);
8021 } else {
Michael Krused47b9432019-08-05 18:43:21 +00008022 llvm::Value *Ptr =
8023 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc());
Alexey Bataevb3638132018-07-19 16:34:13 +00008024 BasePointers.emplace_back(Ptr, VD);
8025 Pointers.push_back(Ptr);
Michael Krused47b9432019-08-05 18:43:21 +00008026 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00008027 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM);
8028 }
Samuel Antaocc10b852016-07-28 14:23:26 +00008029 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008030 }
Samuel Antaocc10b852016-07-28 14:23:26 +00008031
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008032 for (const auto &M : Info) {
Samuel Antao86ace552016-04-27 22:40:57 +00008033 // We need to know when we generate information for the first component
8034 // associated with a capture, because the mapping flags depend on it.
8035 bool IsFirstComponentList = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00008036
8037 // Temporary versions of arrays
8038 MapBaseValuesArrayTy CurBasePointers;
8039 MapValuesArrayTy CurPointers;
8040 MapValuesArrayTy CurSizes;
8041 MapFlagsArrayTy CurTypes;
8042 StructRangeInfoTy PartialStruct;
8043
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008044 for (const MapInfo &L : M.second) {
Samuel Antao86ace552016-04-27 22:40:57 +00008045 assert(!L.Components.empty() &&
8046 "Not expecting declaration with no component lists.");
Samuel Antaocc10b852016-07-28 14:23:26 +00008047
8048 // Remember the current base pointer index.
Alexey Bataevb3638132018-07-19 16:34:13 +00008049 unsigned CurrentBasePointersIdx = CurBasePointers.size();
Michael Krused47b9432019-08-05 18:43:21 +00008050 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8051 CurBasePointers, CurPointers, CurSizes,
8052 CurTypes, PartialStruct,
8053 IsFirstComponentList, L.IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00008054
8055 // If this entry relates with a device pointer, set the relevant
8056 // declaration and add the 'return pointer' flag.
Alexey Bataevb3638132018-07-19 16:34:13 +00008057 if (L.ReturnDevicePointer) {
8058 assert(CurBasePointers.size() > CurrentBasePointersIdx &&
Samuel Antaocc10b852016-07-28 14:23:26 +00008059 "Unexpected number of mapped base pointers.");
8060
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008061 const ValueDecl *RelevantVD =
8062 L.Components.back().getAssociatedDeclaration();
Samuel Antaocc10b852016-07-28 14:23:26 +00008063 assert(RelevantVD &&
8064 "No relevant declaration related with device pointer??");
8065
Alexey Bataevb3638132018-07-19 16:34:13 +00008066 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD);
8067 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008068 }
Samuel Antao86ace552016-04-27 22:40:57 +00008069 IsFirstComponentList = false;
8070 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008071
8072 // Append any pending zero-length pointers which are struct members and
8073 // used with use_device_ptr.
8074 auto CI = DeferredInfo.find(M.first);
8075 if (CI != DeferredInfo.end()) {
8076 for (const DeferredDevicePtrEntryTy &L : CI->second) {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008077 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF);
Alexey Bataevb3638132018-07-19 16:34:13 +00008078 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar(
8079 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc());
8080 CurBasePointers.emplace_back(BasePtr, L.VD);
8081 CurPointers.push_back(Ptr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008082 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00008083 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder
8084 // value MEMBER_OF=FFFF so that the entry is later updated with the
8085 // correct value of MEMBER_OF.
8086 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM |
8087 OMP_MAP_MEMBER_OF);
8088 }
8089 }
8090
8091 // If there is an entry in PartialStruct it means we have a struct with
8092 // individual members mapped. Emit an extra combined entry.
8093 if (PartialStruct.Base.isValid())
8094 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8095 PartialStruct);
8096
8097 // We need to append the results of this capture to what we already have.
8098 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8099 Pointers.append(CurPointers.begin(), CurPointers.end());
8100 Sizes.append(CurSizes.begin(), CurSizes.end());
8101 Types.append(CurTypes.begin(), CurTypes.end());
Samuel Antao86ace552016-04-27 22:40:57 +00008102 }
8103 }
8104
Michael Krused47b9432019-08-05 18:43:21 +00008105 /// Generate all the base pointers, section pointers, sizes and map types for
8106 /// the extracted map clauses of user-defined mapper.
8107 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers,
8108 MapValuesArrayTy &Pointers,
8109 MapValuesArrayTy &Sizes,
8110 MapFlagsArrayTy &Types) const {
8111 assert(CurDir.is<const OMPDeclareMapperDecl *>() &&
8112 "Expect a declare mapper directive");
8113 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>();
8114 // We have to process the component lists that relate with the same
8115 // declaration in a single chunk so that we can generate the map flags
8116 // correctly. Therefore, we organize all lists in a map.
8117 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
8118
8119 // Helper function to fill the information map for the different supported
8120 // clauses.
8121 auto &&InfoGen = [&Info](
8122 const ValueDecl *D,
8123 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
8124 OpenMPMapClauseKind MapType,
8125 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8126 bool ReturnDevicePointer, bool IsImplicit) {
8127 const ValueDecl *VD =
8128 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
8129 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
8130 IsImplicit);
8131 };
8132
8133 for (const auto *C : CurMapperDir->clauselists()) {
8134 const auto *MC = cast<OMPMapClause>(C);
Mark de Wever51abceb2019-11-12 20:48:11 +01008135 for (const auto L : MC->component_lists()) {
Michael Krused47b9432019-08-05 18:43:21 +00008136 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(),
8137 /*ReturnDevicePointer=*/false, MC->isImplicit());
8138 }
8139 }
8140
8141 for (const auto &M : Info) {
8142 // We need to know when we generate information for the first component
8143 // associated with a capture, because the mapping flags depend on it.
8144 bool IsFirstComponentList = true;
8145
8146 // Temporary versions of arrays
8147 MapBaseValuesArrayTy CurBasePointers;
8148 MapValuesArrayTy CurPointers;
8149 MapValuesArrayTy CurSizes;
8150 MapFlagsArrayTy CurTypes;
8151 StructRangeInfoTy PartialStruct;
8152
8153 for (const MapInfo &L : M.second) {
8154 assert(!L.Components.empty() &&
8155 "Not expecting declaration with no component lists.");
8156 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8157 CurBasePointers, CurPointers, CurSizes,
8158 CurTypes, PartialStruct,
8159 IsFirstComponentList, L.IsImplicit);
8160 IsFirstComponentList = false;
8161 }
8162
8163 // If there is an entry in PartialStruct it means we have a struct with
8164 // individual members mapped. Emit an extra combined entry.
8165 if (PartialStruct.Base.isValid())
8166 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8167 PartialStruct);
8168
8169 // We need to append the results of this capture to what we already have.
8170 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8171 Pointers.append(CurPointers.begin(), CurPointers.end());
8172 Sizes.append(CurSizes.begin(), CurSizes.end());
8173 Types.append(CurTypes.begin(), CurTypes.end());
8174 }
8175 }
8176
Alexey Bataev60705422018-10-30 15:50:12 +00008177 /// Emit capture info for lambdas for variables captured by reference.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008178 void generateInfoForLambdaCaptures(
8179 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers,
8180 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
8181 MapFlagsArrayTy &Types,
8182 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008183 const auto *RD = VD->getType()
8184 .getCanonicalType()
8185 .getNonReferenceType()
8186 ->getAsCXXRecordDecl();
8187 if (!RD || !RD->isLambda())
8188 return;
8189 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD));
8190 LValue VDLVal = CGF.MakeAddrLValue(
8191 VDAddr, VD->getType().getCanonicalType().getNonReferenceType());
8192 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
8193 FieldDecl *ThisCapture = nullptr;
8194 RD->getCaptureFields(Captures, ThisCapture);
8195 if (ThisCapture) {
8196 LValue ThisLVal =
8197 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture);
Alexey Bataev969dbc02018-11-08 15:47:39 +00008198 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008199 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
8200 VDLVal.getPointer(CGF));
8201 BasePointers.push_back(ThisLVal.getPointer(CGF));
8202 Pointers.push_back(ThisLValVal.getPointer(CGF));
Alexey Bataeva90fc662019-06-25 16:00:43 +00008203 Sizes.push_back(
8204 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8205 CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008206 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008207 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8208 }
8209 for (const LambdaCapture &LC : RD->captures()) {
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008210 if (!LC.capturesVariable())
Alexey Bataev60705422018-10-30 15:50:12 +00008211 continue;
8212 const VarDecl *VD = LC.getCapturedVar();
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008213 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType())
8214 continue;
Alexey Bataev60705422018-10-30 15:50:12 +00008215 auto It = Captures.find(VD);
8216 assert(It != Captures.end() && "Found lambda capture without field.");
8217 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second);
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008218 if (LC.getCaptureKind() == LCK_ByRef) {
8219 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008220 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
8221 VDLVal.getPointer(CGF));
8222 BasePointers.push_back(VarLVal.getPointer(CGF));
8223 Pointers.push_back(VarLValVal.getPointer(CGF));
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008224 Sizes.push_back(CGF.Builder.CreateIntCast(
8225 CGF.getTypeSize(
8226 VD->getType().getCanonicalType().getNonReferenceType()),
8227 CGF.Int64Ty, /*isSigned=*/true));
8228 } else {
8229 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008230 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
8231 VDLVal.getPointer(CGF));
8232 BasePointers.push_back(VarLVal.getPointer(CGF));
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008233 Pointers.push_back(VarRVal.getScalarVal());
8234 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0));
8235 }
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008236 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008237 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8238 }
8239 }
8240
8241 /// Set correct indices for lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008242 void adjustMemberOfForLambdaCaptures(
8243 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
8244 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
8245 MapFlagsArrayTy &Types) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008246 for (unsigned I = 0, E = Types.size(); I < E; ++I) {
8247 // Set correct member_of idx for all implicit lambda captures.
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008248 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008249 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT))
8250 continue;
Alexey Bataev969dbc02018-11-08 15:47:39 +00008251 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]);
8252 assert(BasePtr && "Unable to find base lambda address.");
Alexey Bataev60705422018-10-30 15:50:12 +00008253 int TgtIdx = -1;
8254 for (unsigned J = I; J > 0; --J) {
8255 unsigned Idx = J - 1;
8256 if (Pointers[Idx] != BasePtr)
8257 continue;
8258 TgtIdx = Idx;
8259 break;
8260 }
8261 assert(TgtIdx != -1 && "Unable to find parent lambda.");
8262 // All other current entries will be MEMBER_OF the combined entry
8263 // (except for PTR_AND_OBJ entries which do not have a placeholder value
8264 // 0xFFFF in the MEMBER_OF field).
8265 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx);
8266 setCorrectMemberOfFlag(Types[I], MemberOfFlag);
8267 }
8268 }
8269
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008270 /// Generate the base pointers, section pointers, sizes and map types
Samuel Antao86ace552016-04-27 22:40:57 +00008271 /// associated to a given capture.
8272 void generateInfoForCapture(const CapturedStmt::Capture *Cap,
Samuel Antao6890b092016-07-28 14:25:09 +00008273 llvm::Value *Arg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008274 MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00008275 MapValuesArrayTy &Pointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008276 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
8277 StructRangeInfoTy &PartialStruct) const {
Samuel Antao86ace552016-04-27 22:40:57 +00008278 assert(!Cap->capturesVariableArrayType() &&
8279 "Not expecting to generate map info for a variable array type!");
8280
Samuel Antao6890b092016-07-28 14:25:09 +00008281 // We need to know when we generating information for the first component
Alexey Bataevb3638132018-07-19 16:34:13 +00008282 const ValueDecl *VD = Cap->capturesThis()
8283 ? nullptr
8284 : Cap->getCapturedVar()->getCanonicalDecl();
Samuel Antao86ace552016-04-27 22:40:57 +00008285
Samuel Antao6890b092016-07-28 14:25:09 +00008286 // If this declaration appears in a is_device_ptr clause we just have to
8287 // pass the pointer by value. If it is a reference to a declaration, we just
Alexey Bataevb3638132018-07-19 16:34:13 +00008288 // pass its value.
8289 if (DevPointersMap.count(VD)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008290 BasePointers.emplace_back(Arg, VD);
Samuel Antao6890b092016-07-28 14:25:09 +00008291 Pointers.push_back(Arg);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008292 Sizes.push_back(
8293 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8294 CGF.Int64Ty, /*isSigned=*/true));
George Rokos065755d2017-11-07 18:27:04 +00008295 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM);
Samuel Antao6890b092016-07-28 14:25:09 +00008296 return;
8297 }
8298
Alexey Bataeve82445f2018-09-20 13:54:02 +00008299 using MapData =
8300 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
Kelvin Lief579432018-12-18 22:18:41 +00008301 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008302 SmallVector<MapData, 4> DeclComponentLists;
Michael Krused47b9432019-08-05 18:43:21 +00008303 assert(CurDir.is<const OMPExecutableDirective *>() &&
8304 "Expect a executable directive");
8305 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
8306 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
Mark de Wever51abceb2019-11-12 20:48:11 +01008307 for (const auto L : C->decl_component_lists(VD)) {
Samuel Antao86ace552016-04-27 22:40:57 +00008308 assert(L.first == VD &&
8309 "We got information for the wrong declaration??");
8310 assert(!L.second.empty() &&
8311 "Not expecting declaration with no component lists.");
Alexey Bataeve82445f2018-09-20 13:54:02 +00008312 DeclComponentLists.emplace_back(L.second, C->getMapType(),
Kelvin Lief579432018-12-18 22:18:41 +00008313 C->getMapTypeModifiers(),
Alexey Bataeve82445f2018-09-20 13:54:02 +00008314 C->isImplicit());
Samuel Antao86ace552016-04-27 22:40:57 +00008315 }
Alexey Bataeve82445f2018-09-20 13:54:02 +00008316 }
8317
8318 // Find overlapping elements (including the offset from the base element).
8319 llvm::SmallDenseMap<
8320 const MapData *,
8321 llvm::SmallVector<
8322 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>,
8323 4>
8324 OverlappedData;
8325 size_t Count = 0;
8326 for (const MapData &L : DeclComponentLists) {
8327 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8328 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008329 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008330 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008331 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008332 ++Count;
8333 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) {
8334 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1;
Kelvin Lief579432018-12-18 22:18:41 +00008335 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008336 auto CI = Components.rbegin();
8337 auto CE = Components.rend();
8338 auto SI = Components1.rbegin();
8339 auto SE = Components1.rend();
8340 for (; CI != CE && SI != SE; ++CI, ++SI) {
8341 if (CI->getAssociatedExpression()->getStmtClass() !=
8342 SI->getAssociatedExpression()->getStmtClass())
8343 break;
8344 // Are we dealing with different variables/fields?
8345 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
8346 break;
8347 }
8348 // Found overlapping if, at least for one component, reached the head of
8349 // the components list.
8350 if (CI == CE || SI == SE) {
8351 assert((CI != CE || SI != SE) &&
8352 "Unexpected full match of the mapping components.");
8353 const MapData &BaseData = CI == CE ? L : L1;
8354 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData =
8355 SI == SE ? Components : Components1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008356 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData);
8357 OverlappedElements.getSecond().push_back(SubData);
8358 }
8359 }
8360 }
8361 // Sort the overlapped elements for each item.
8362 llvm::SmallVector<const FieldDecl *, 4> Layout;
8363 if (!OverlappedData.empty()) {
8364 if (const auto *CRD =
8365 VD->getType().getCanonicalType()->getAsCXXRecordDecl())
8366 getPlainLayout(CRD, Layout, /*AsBase=*/false);
8367 else {
8368 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl();
8369 Layout.append(RD->field_begin(), RD->field_end());
8370 }
8371 }
8372 for (auto &Pair : OverlappedData) {
8373 llvm::sort(
8374 Pair.getSecond(),
8375 [&Layout](
8376 OMPClauseMappableExprCommon::MappableExprComponentListRef First,
8377 OMPClauseMappableExprCommon::MappableExprComponentListRef
8378 Second) {
8379 auto CI = First.rbegin();
8380 auto CE = First.rend();
8381 auto SI = Second.rbegin();
8382 auto SE = Second.rend();
8383 for (; CI != CE && SI != SE; ++CI, ++SI) {
8384 if (CI->getAssociatedExpression()->getStmtClass() !=
8385 SI->getAssociatedExpression()->getStmtClass())
8386 break;
8387 // Are we dealing with different variables/fields?
8388 if (CI->getAssociatedDeclaration() !=
8389 SI->getAssociatedDeclaration())
8390 break;
8391 }
Richard Trieu5061e832018-09-21 21:20:33 +00008392
8393 // Lists contain the same elements.
8394 if (CI == CE && SI == SE)
8395 return false;
8396
8397 // List with less elements is less than list with more elements.
8398 if (CI == CE || SI == SE)
8399 return CI == CE;
8400
Alexey Bataeve82445f2018-09-20 13:54:02 +00008401 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
8402 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
8403 if (FD1->getParent() == FD2->getParent())
8404 return FD1->getFieldIndex() < FD2->getFieldIndex();
8405 const auto It =
8406 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) {
8407 return FD == FD1 || FD == FD2;
8408 });
8409 return *It == FD1;
8410 });
8411 }
8412
8413 // Associated with a capture, because the mapping flags depend on it.
8414 // Go through all of the elements with the overlapped elements.
8415 for (const auto &Pair : OverlappedData) {
8416 const MapData &L = *Pair.getFirst();
8417 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8418 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008419 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008420 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008421 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008422 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
8423 OverlappedComponents = Pair.getSecond();
8424 bool IsFirstComponentList = true;
Kelvin Lief579432018-12-18 22:18:41 +00008425 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008426 BasePointers, Pointers, Sizes, Types,
8427 PartialStruct, IsFirstComponentList,
8428 IsImplicit, OverlappedComponents);
8429 }
8430 // Go through other elements without overlapped elements.
8431 bool IsFirstComponentList = OverlappedData.empty();
8432 for (const MapData &L : DeclComponentLists) {
8433 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8434 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008435 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008436 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008437 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008438 auto It = OverlappedData.find(&L);
8439 if (It == OverlappedData.end())
Kelvin Lief579432018-12-18 22:18:41 +00008440 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008441 BasePointers, Pointers, Sizes, Types,
8442 PartialStruct, IsFirstComponentList,
8443 IsImplicit);
8444 IsFirstComponentList = false;
8445 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008446 }
Samuel Antao86ace552016-04-27 22:40:57 +00008447
Alexey Bataevb3638132018-07-19 16:34:13 +00008448 /// Generate the base pointers, section pointers, sizes and map types
8449 /// associated with the declare target link variables.
8450 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers,
8451 MapValuesArrayTy &Pointers,
8452 MapValuesArrayTy &Sizes,
8453 MapFlagsArrayTy &Types) const {
Michael Krused47b9432019-08-05 18:43:21 +00008454 assert(CurDir.is<const OMPExecutableDirective *>() &&
8455 "Expect a executable directive");
8456 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
Alexey Bataevb3638132018-07-19 16:34:13 +00008457 // Map other list items in the map clause which are not captured variables
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00008458 // but "declare target link" global variables.
Michael Krused47b9432019-08-05 18:43:21 +00008459 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
Mark de Wever51abceb2019-11-12 20:48:11 +01008460 for (const auto L : C->component_lists()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00008461 if (!L.first)
8462 continue;
8463 const auto *VD = dyn_cast<VarDecl>(L.first);
8464 if (!VD)
8465 continue;
8466 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00008467 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00008468 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
8469 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)
Alexey Bataevb3638132018-07-19 16:34:13 +00008470 continue;
8471 StructRangeInfoTy PartialStruct;
8472 generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00008473 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008474 Pointers, Sizes, Types, PartialStruct,
8475 /*IsFirstComponentList=*/true, C->isImplicit());
8476 assert(!PartialStruct.Base.isValid() &&
8477 "No partial structs for declare target link expected.");
8478 }
8479 }
Samuel Antao86ace552016-04-27 22:40:57 +00008480 }
Samuel Antaod486f842016-05-26 16:53:38 +00008481
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008482 /// Generate the default map information for a given capture \a CI,
Samuel Antaod486f842016-05-26 16:53:38 +00008483 /// record field declaration \a RI and captured value \a CV.
Samuel Antaocc10b852016-07-28 14:23:26 +00008484 void generateDefaultMapInfo(const CapturedStmt::Capture &CI,
8485 const FieldDecl &RI, llvm::Value *CV,
8486 MapBaseValuesArrayTy &CurBasePointers,
8487 MapValuesArrayTy &CurPointers,
8488 MapValuesArrayTy &CurSizes,
Alexey Bataevb3638132018-07-19 16:34:13 +00008489 MapFlagsArrayTy &CurMapTypes) const {
Alexey Bataevf288cf92019-06-27 18:53:07 +00008490 bool IsImplicit = true;
Samuel Antaod486f842016-05-26 16:53:38 +00008491 // Do the default mapping.
8492 if (CI.capturesThis()) {
8493 CurBasePointers.push_back(CV);
8494 CurPointers.push_back(CV);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008495 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr());
Alexey Bataeva90fc662019-06-25 16:00:43 +00008496 CurSizes.push_back(
8497 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()),
8498 CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008499 // Default map type.
Samuel Antaocc10b852016-07-28 14:23:26 +00008500 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM);
Samuel Antaod486f842016-05-26 16:53:38 +00008501 } else if (CI.capturesVariableByCopy()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008502 CurBasePointers.push_back(CV);
8503 CurPointers.push_back(CV);
Samuel Antaod486f842016-05-26 16:53:38 +00008504 if (!RI.getType()->isAnyPointerType()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008505 // We have to signal to the runtime captures passed by value that are
8506 // not pointers.
George Rokos065755d2017-11-07 18:27:04 +00008507 CurMapTypes.push_back(OMP_MAP_LITERAL);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008508 CurSizes.push_back(CGF.Builder.CreateIntCast(
8509 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008510 } else {
8511 // Pointers are implicitly mapped with a zero size and no flags
8512 // (other than first map that is added for all implicit maps).
Alexey Bataevb3638132018-07-19 16:34:13 +00008513 CurMapTypes.push_back(OMP_MAP_NONE);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008514 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
Samuel Antaod486f842016-05-26 16:53:38 +00008515 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008516 const VarDecl *VD = CI.getCapturedVar();
8517 auto I = FirstPrivateDecls.find(VD);
8518 if (I != FirstPrivateDecls.end())
8519 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008520 } else {
8521 assert(CI.capturesVariable() && "Expected captured reference.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008522 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr());
Samuel Antaod486f842016-05-26 16:53:38 +00008523 QualType ElementType = PtrTy->getPointeeType();
Alexey Bataeva90fc662019-06-25 16:00:43 +00008524 CurSizes.push_back(CGF.Builder.CreateIntCast(
8525 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008526 // The default map type for a scalar/complex type is 'to' because by
8527 // default the value doesn't have to be retrieved. For an aggregate
8528 // type, the default is 'tofrom'.
Alexey Bataevb3638132018-07-19 16:34:13 +00008529 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI));
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008530 const VarDecl *VD = CI.getCapturedVar();
Alexey Bataevf288cf92019-06-27 18:53:07 +00008531 auto I = FirstPrivateDecls.find(VD);
8532 if (I != FirstPrivateDecls.end() &&
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008533 VD->getType().isConstant(CGF.getContext())) {
8534 llvm::Constant *Addr =
8535 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD);
8536 // Copy the value of the original variable to the new global copy.
8537 CGF.Builder.CreateMemCpy(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008538 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(CGF),
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008539 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)),
Rui Ueyama49a3ad22019-07-16 04:46:31 +00008540 CurSizes.back(), /*IsVolatile=*/false);
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008541 // Use new global variable as the base pointers.
8542 CurBasePointers.push_back(Addr);
8543 CurPointers.push_back(Addr);
8544 } else {
8545 CurBasePointers.push_back(CV);
Alexey Bataevf288cf92019-06-27 18:53:07 +00008546 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) {
Alexey Bataevc2b831f2019-04-02 16:03:40 +00008547 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue(
8548 CV, ElementType, CGF.getContext().getDeclAlign(VD),
8549 AlignmentSource::Decl));
8550 CurPointers.push_back(PtrAddr.getPointer());
8551 } else {
8552 CurPointers.push_back(CV);
8553 }
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008554 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008555 if (I != FirstPrivateDecls.end())
8556 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008557 }
George Rokos065755d2017-11-07 18:27:04 +00008558 // Every default map produces a single argument which is a target parameter.
8559 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM;
Alexey Bataevb3638132018-07-19 16:34:13 +00008560
8561 // Add flag stating this is an implicit map.
Alexey Bataevf288cf92019-06-27 18:53:07 +00008562 if (IsImplicit)
8563 CurMapTypes.back() |= OMP_MAP_IMPLICIT;
Samuel Antaod486f842016-05-26 16:53:38 +00008564 }
Samuel Antao86ace552016-04-27 22:40:57 +00008565};
Samuel Antaodf158d52016-04-27 22:58:19 +00008566} // anonymous namespace
8567
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008568/// Emit the arrays used to pass the captures and map information to the
Samuel Antaodf158d52016-04-27 22:58:19 +00008569/// offloading runtime library. If there is no map or capture information,
8570/// return nullptr by reference.
8571static void
Samuel Antaocc10b852016-07-28 14:23:26 +00008572emitOffloadingArrays(CodeGenFunction &CGF,
8573 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers,
Samuel Antaodf158d52016-04-27 22:58:19 +00008574 MappableExprsHandler::MapValuesArrayTy &Pointers,
8575 MappableExprsHandler::MapValuesArrayTy &Sizes,
Samuel Antaocc10b852016-07-28 14:23:26 +00008576 MappableExprsHandler::MapFlagsArrayTy &MapTypes,
8577 CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008578 CodeGenModule &CGM = CGF.CGM;
8579 ASTContext &Ctx = CGF.getContext();
Samuel Antaodf158d52016-04-27 22:58:19 +00008580
Samuel Antaocc10b852016-07-28 14:23:26 +00008581 // Reset the array information.
8582 Info.clearArrayInfo();
8583 Info.NumberOfPtrs = BasePointers.size();
Samuel Antaodf158d52016-04-27 22:58:19 +00008584
Samuel Antaocc10b852016-07-28 14:23:26 +00008585 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008586 // Detect if we have any capture size requiring runtime evaluation of the
8587 // size so that a constant array could be eventually used.
8588 bool hasRuntimeEvaluationCaptureSize = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008589 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008590 if (!isa<llvm::Constant>(S)) {
8591 hasRuntimeEvaluationCaptureSize = true;
8592 break;
8593 }
8594
Samuel Antaocc10b852016-07-28 14:23:26 +00008595 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true);
Richard Smith772e2662019-10-04 01:25:59 +00008596 QualType PointerArrayType = Ctx.getConstantArrayType(
8597 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal,
8598 /*IndexTypeQuals=*/0);
Samuel Antaodf158d52016-04-27 22:58:19 +00008599
Samuel Antaocc10b852016-07-28 14:23:26 +00008600 Info.BasePointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008601 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
Samuel Antaocc10b852016-07-28 14:23:26 +00008602 Info.PointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008603 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
8604
8605 // If we don't have any VLA types or other types that require runtime
8606 // evaluation, we can use a constant array for the map sizes, otherwise we
8607 // need to fill up the arrays as we do for the pointers.
Alexey Bataeva90fc662019-06-25 16:00:43 +00008608 QualType Int64Ty =
8609 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Samuel Antaodf158d52016-04-27 22:58:19 +00008610 if (hasRuntimeEvaluationCaptureSize) {
Richard Smith772e2662019-10-04 01:25:59 +00008611 QualType SizeArrayType = Ctx.getConstantArrayType(
8612 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal,
8613 /*IndexTypeQuals=*/0);
Samuel Antaocc10b852016-07-28 14:23:26 +00008614 Info.SizesArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008615 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
8616 } else {
8617 // We expect all the sizes to be constant, so we collect them to create
8618 // a constant array.
8619 SmallVector<llvm::Constant *, 16> ConstSizes;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008620 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008621 ConstSizes.push_back(cast<llvm::Constant>(S));
8622
8623 auto *SizesArrayInit = llvm::ConstantArray::get(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008624 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008625 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008626 auto *SizesArrayGbl = new llvm::GlobalVariable(
8627 CGM.getModule(), SizesArrayInit->getType(),
8628 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008629 SizesArrayInit, Name);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008630 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008631 Info.SizesArray = SizesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008632 }
8633
8634 // The map types are always constant so we don't need to generate code to
8635 // fill arrays. Instead, we create an array constant.
Alexey Bataevb3638132018-07-19 16:34:13 +00008636 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0);
8637 llvm::copy(MapTypes, Mapping.begin());
Samuel Antaodf158d52016-04-27 22:58:19 +00008638 llvm::Constant *MapTypesArrayInit =
Alexey Bataevb3638132018-07-19 16:34:13 +00008639 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008640 std::string MaptypesName =
8641 CGM.getOpenMPRuntime().getName({"offload_maptypes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008642 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
8643 CGM.getModule(), MapTypesArrayInit->getType(),
8644 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008645 MapTypesArrayInit, MaptypesName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008646 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008647 Info.MapTypesArray = MapTypesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008648
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008649 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) {
8650 llvm::Value *BPVal = *BasePointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008651 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008652 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008653 Info.BasePointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008654 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8655 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008656 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8657 CGF.Builder.CreateStore(BPVal, BPAddr);
8658
Samuel Antaocc10b852016-07-28 14:23:26 +00008659 if (Info.requiresDevicePointerInfo())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008660 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl())
Alexey Bataev43a919f2018-04-13 17:48:43 +00008661 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr);
Samuel Antaocc10b852016-07-28 14:23:26 +00008662
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008663 llvm::Value *PVal = Pointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008664 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008665 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008666 Info.PointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008667 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8668 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008669 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8670 CGF.Builder.CreateStore(PVal, PAddr);
8671
8672 if (hasRuntimeEvaluationCaptureSize) {
8673 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008674 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008675 Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008676 /*Idx0=*/0,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008677 /*Idx1=*/I);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008678 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty));
Samuel Antaodf158d52016-04-27 22:58:19 +00008679 CGF.Builder.CreateStore(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008680 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true),
Samuel Antaodf158d52016-04-27 22:58:19 +00008681 SAddr);
8682 }
8683 }
8684 }
8685}
Michael Krused47b9432019-08-05 18:43:21 +00008686
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008687/// Emit the arguments to be passed to the runtime library based on the
Samuel Antaodf158d52016-04-27 22:58:19 +00008688/// arrays of pointers, sizes and map types.
8689static void emitOffloadingArraysArgument(
8690 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg,
8691 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008692 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008693 CodeGenModule &CGM = CGF.CGM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008694 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008695 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008696 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8697 Info.BasePointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008698 /*Idx0=*/0, /*Idx1=*/0);
8699 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008700 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8701 Info.PointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008702 /*Idx0=*/0,
8703 /*Idx1=*/0);
8704 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008705 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008706 /*Idx0=*/0, /*Idx1=*/0);
8707 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
George Rokos63bc9d62017-11-21 18:25:12 +00008708 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008709 Info.MapTypesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008710 /*Idx0=*/0,
8711 /*Idx1=*/0);
8712 } else {
8713 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
8714 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008715 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008716 MapTypesArrayArg =
George Rokos63bc9d62017-11-21 18:25:12 +00008717 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008718 }
Samuel Antao86ace552016-04-27 22:40:57 +00008719}
8720
Alexey Bataev7bb33532019-01-07 21:30:43 +00008721/// Check for inner distribute directive.
8722static const OMPExecutableDirective *
8723getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
8724 const auto *CS = D.getInnermostCapturedStmt();
8725 const auto *Body =
8726 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00008727 const Stmt *ChildStmt =
8728 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
Alexey Bataev7bb33532019-01-07 21:30:43 +00008729
Alexey Bataev5c427362019-04-10 19:11:33 +00008730 if (const auto *NestedDir =
8731 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008732 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind();
8733 switch (D.getDirectiveKind()) {
8734 case OMPD_target:
8735 if (isOpenMPDistributeDirective(DKind))
8736 return NestedDir;
8737 if (DKind == OMPD_teams) {
8738 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
8739 /*IgnoreCaptured=*/true);
8740 if (!Body)
8741 return nullptr;
Alexey Bataev5c427362019-04-10 19:11:33 +00008742 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
8743 if (const auto *NND =
8744 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008745 DKind = NND->getDirectiveKind();
8746 if (isOpenMPDistributeDirective(DKind))
8747 return NND;
8748 }
8749 }
8750 return nullptr;
8751 case OMPD_target_teams:
8752 if (isOpenMPDistributeDirective(DKind))
8753 return NestedDir;
8754 return nullptr;
8755 case OMPD_target_parallel:
8756 case OMPD_target_simd:
8757 case OMPD_target_parallel_for:
8758 case OMPD_target_parallel_for_simd:
8759 return nullptr;
8760 case OMPD_target_teams_distribute:
8761 case OMPD_target_teams_distribute_simd:
8762 case OMPD_target_teams_distribute_parallel_for:
8763 case OMPD_target_teams_distribute_parallel_for_simd:
8764 case OMPD_parallel:
8765 case OMPD_for:
8766 case OMPD_parallel_for:
cchen47d60942019-12-05 13:43:48 -05008767 case OMPD_parallel_master:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008768 case OMPD_parallel_sections:
8769 case OMPD_for_simd:
8770 case OMPD_parallel_for_simd:
8771 case OMPD_cancel:
8772 case OMPD_cancellation_point:
8773 case OMPD_ordered:
8774 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00008775 case OMPD_allocate:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008776 case OMPD_task:
8777 case OMPD_simd:
8778 case OMPD_sections:
8779 case OMPD_section:
8780 case OMPD_single:
8781 case OMPD_master:
8782 case OMPD_critical:
8783 case OMPD_taskyield:
8784 case OMPD_barrier:
8785 case OMPD_taskwait:
8786 case OMPD_taskgroup:
8787 case OMPD_atomic:
8788 case OMPD_flush:
8789 case OMPD_teams:
8790 case OMPD_target_data:
8791 case OMPD_target_exit_data:
8792 case OMPD_target_enter_data:
8793 case OMPD_distribute:
8794 case OMPD_distribute_simd:
8795 case OMPD_distribute_parallel_for:
8796 case OMPD_distribute_parallel_for_simd:
8797 case OMPD_teams_distribute:
8798 case OMPD_teams_distribute_simd:
8799 case OMPD_teams_distribute_parallel_for:
8800 case OMPD_teams_distribute_parallel_for_simd:
8801 case OMPD_target_update:
8802 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00008803 case OMPD_declare_variant:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008804 case OMPD_declare_target:
8805 case OMPD_end_declare_target:
8806 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00008807 case OMPD_declare_mapper:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008808 case OMPD_taskloop:
8809 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00008810 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00008811 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00008812 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04008813 case OMPD_parallel_master_taskloop_simd:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008814 case OMPD_requires:
8815 case OMPD_unknown:
8816 llvm_unreachable("Unexpected directive.");
8817 }
8818 }
8819
8820 return nullptr;
8821}
8822
Michael Krused47b9432019-08-05 18:43:21 +00008823/// Emit the user-defined mapper function. The code generation follows the
8824/// pattern in the example below.
8825/// \code
8826/// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle,
8827/// void *base, void *begin,
8828/// int64_t size, int64_t type) {
8829/// // Allocate space for an array section first.
8830/// if (size > 1 && !maptype.IsDelete)
8831/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
8832/// size*sizeof(Ty), clearToFrom(type));
8833/// // Map members.
8834/// for (unsigned i = 0; i < size; i++) {
8835/// // For each component specified by this mapper:
8836/// for (auto c : all_components) {
8837/// if (c.hasMapper())
8838/// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size,
8839/// c.arg_type);
8840/// else
8841/// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base,
8842/// c.arg_begin, c.arg_size, c.arg_type);
8843/// }
8844/// }
8845/// // Delete the array section.
8846/// if (size > 1 && maptype.IsDelete)
8847/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
8848/// size*sizeof(Ty), clearToFrom(type));
8849/// }
8850/// \endcode
8851void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D,
8852 CodeGenFunction *CGF) {
8853 if (UDMMap.count(D) > 0)
8854 return;
8855 ASTContext &C = CGM.getContext();
8856 QualType Ty = D->getType();
8857 QualType PtrTy = C.getPointerType(Ty).withRestrict();
8858 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
8859 auto *MapperVarDecl =
8860 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl());
8861 SourceLocation Loc = D->getLocation();
8862 CharUnits ElementSize = C.getTypeSizeInChars(Ty);
8863
8864 // Prepare mapper function arguments and attributes.
8865 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
8866 C.VoidPtrTy, ImplicitParamDecl::Other);
8867 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
8868 ImplicitParamDecl::Other);
8869 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
8870 C.VoidPtrTy, ImplicitParamDecl::Other);
8871 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
8872 ImplicitParamDecl::Other);
8873 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
8874 ImplicitParamDecl::Other);
8875 FunctionArgList Args;
8876 Args.push_back(&HandleArg);
8877 Args.push_back(&BaseArg);
8878 Args.push_back(&BeginArg);
8879 Args.push_back(&SizeArg);
8880 Args.push_back(&TypeArg);
8881 const CGFunctionInfo &FnInfo =
8882 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
8883 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
8884 SmallString<64> TyStr;
8885 llvm::raw_svector_ostream Out(TyStr);
8886 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out);
8887 std::string Name = getName({"omp_mapper", TyStr, D->getName()});
8888 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
8889 Name, &CGM.getModule());
8890 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
8891 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
8892 // Start the mapper function code generation.
8893 CodeGenFunction MapperCGF(CGM);
8894 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
8895 // Compute the starting and end addreses of array elements.
8896 llvm::Value *Size = MapperCGF.EmitLoadOfScalar(
8897 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false,
8898 C.getPointerType(Int64Ty), Loc);
8899 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast(
8900 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(),
8901 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy)));
8902 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size);
8903 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar(
8904 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false,
8905 C.getPointerType(Int64Ty), Loc);
8906 // Prepare common arguments for array initiation and deletion.
8907 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar(
8908 MapperCGF.GetAddrOfLocalVar(&HandleArg),
8909 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8910 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar(
8911 MapperCGF.GetAddrOfLocalVar(&BaseArg),
8912 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8913 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar(
8914 MapperCGF.GetAddrOfLocalVar(&BeginArg),
8915 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8916
8917 // Emit array initiation if this is an array section and \p MapType indicates
8918 // that memory allocation is required.
8919 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head");
8920 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
8921 ElementSize, HeadBB, /*IsInit=*/true);
8922
8923 // Emit a for loop to iterate through SizeArg of elements and map all of them.
8924
8925 // Emit the loop header block.
8926 MapperCGF.EmitBlock(HeadBB);
8927 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body");
8928 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done");
8929 // Evaluate whether the initial condition is satisfied.
8930 llvm::Value *IsEmpty =
8931 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty");
8932 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
8933 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock();
8934
8935 // Emit the loop body block.
8936 MapperCGF.EmitBlock(BodyBB);
8937 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI(
8938 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent");
8939 PtrPHI->addIncoming(PtrBegin, EntryBB);
8940 Address PtrCurrent =
8941 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg)
8942 .getAlignment()
8943 .alignmentOfArrayElement(ElementSize));
8944 // Privatize the declared variable of mapper to be the current array element.
8945 CodeGenFunction::OMPPrivateScope Scope(MapperCGF);
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08008946 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() {
Michael Krused47b9432019-08-05 18:43:21 +00008947 return MapperCGF
8948 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>())
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008949 .getAddress(MapperCGF);
Michael Krused47b9432019-08-05 18:43:21 +00008950 });
8951 (void)Scope.Privatize();
8952
8953 // Get map clause information. Fill up the arrays with all mapped variables.
8954 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
8955 MappableExprsHandler::MapValuesArrayTy Pointers;
8956 MappableExprsHandler::MapValuesArrayTy Sizes;
8957 MappableExprsHandler::MapFlagsArrayTy MapTypes;
8958 MappableExprsHandler MEHandler(*D, MapperCGF);
8959 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes);
8960
8961 // Call the runtime API __tgt_mapper_num_components to get the number of
8962 // pre-existing components.
8963 llvm::Value *OffloadingArgs[] = {Handle};
8964 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall(
8965 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs);
8966 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl(
8967 PreviousSize,
8968 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset()));
8969
8970 // Fill up the runtime mapper handle for all components.
8971 for (unsigned I = 0; I < BasePointers.size(); ++I) {
8972 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast(
8973 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
8974 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast(
8975 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
8976 llvm::Value *CurSizeArg = Sizes[I];
8977
8978 // Extract the MEMBER_OF field from the map type.
8979 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member");
8980 MapperCGF.EmitBlock(MemberBB);
8981 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]);
8982 llvm::Value *Member = MapperCGF.Builder.CreateAnd(
8983 OriMapType,
8984 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF));
8985 llvm::BasicBlock *MemberCombineBB =
8986 MapperCGF.createBasicBlock("omp.member.combine");
8987 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type");
8988 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member);
8989 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB);
8990 // Add the number of pre-existing components to the MEMBER_OF field if it
8991 // is valid.
8992 MapperCGF.EmitBlock(MemberCombineBB);
8993 llvm::Value *CombinedMember =
8994 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
8995 // Do nothing if it is not a member of previous components.
8996 MapperCGF.EmitBlock(TypeBB);
8997 llvm::PHINode *MemberMapType =
8998 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype");
8999 MemberMapType->addIncoming(OriMapType, MemberBB);
9000 MemberMapType->addIncoming(CombinedMember, MemberCombineBB);
9001
9002 // Combine the map type inherited from user-defined mapper with that
9003 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM
9004 // bits of the \a MapType, which is the input argument of the mapper
9005 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM
9006 // bits of MemberMapType.
9007 // [OpenMP 5.0], 1.2.6. map-type decay.
9008 // | alloc | to | from | tofrom | release | delete
9009 // ----------------------------------------------------------
9010 // alloc | alloc | alloc | alloc | alloc | release | delete
9011 // to | alloc | to | alloc | to | release | delete
9012 // from | alloc | alloc | from | from | release | delete
9013 // tofrom | alloc | to | from | tofrom | release | delete
9014 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd(
9015 MapType,
9016 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO |
9017 MappableExprsHandler::OMP_MAP_FROM));
9018 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc");
9019 llvm::BasicBlock *AllocElseBB =
9020 MapperCGF.createBasicBlock("omp.type.alloc.else");
9021 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to");
9022 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else");
9023 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from");
9024 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end");
9025 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom);
9026 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
9027 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM.
9028 MapperCGF.EmitBlock(AllocBB);
9029 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd(
9030 MemberMapType,
9031 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9032 MappableExprsHandler::OMP_MAP_FROM)));
9033 MapperCGF.Builder.CreateBr(EndBB);
9034 MapperCGF.EmitBlock(AllocElseBB);
9035 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ(
9036 LeftToFrom,
9037 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO));
9038 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
9039 // In case of to, clear OMP_MAP_FROM.
9040 MapperCGF.EmitBlock(ToBB);
9041 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd(
9042 MemberMapType,
9043 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM));
9044 MapperCGF.Builder.CreateBr(EndBB);
9045 MapperCGF.EmitBlock(ToElseBB);
9046 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ(
9047 LeftToFrom,
9048 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM));
9049 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB);
9050 // In case of from, clear OMP_MAP_TO.
9051 MapperCGF.EmitBlock(FromBB);
9052 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd(
9053 MemberMapType,
9054 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO));
9055 // In case of tofrom, do nothing.
9056 MapperCGF.EmitBlock(EndBB);
9057 llvm::PHINode *CurMapType =
9058 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype");
9059 CurMapType->addIncoming(AllocMapType, AllocBB);
9060 CurMapType->addIncoming(ToMapType, ToBB);
9061 CurMapType->addIncoming(FromMapType, FromBB);
9062 CurMapType->addIncoming(MemberMapType, ToElseBB);
9063
9064 // TODO: call the corresponding mapper function if a user-defined mapper is
9065 // associated with this map clause.
9066 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9067 // data structure.
9068 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg,
9069 CurSizeArg, CurMapType};
9070 MapperCGF.EmitRuntimeCall(
9071 createRuntimeFunction(OMPRTL__tgt_push_mapper_component),
9072 OffloadingArgs);
9073 }
9074
9075 // Update the pointer to point to the next element that needs to be mapped,
9076 // and check whether we have mapped all elements.
9077 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32(
9078 PtrPHI, /*Idx0=*/1, "omp.arraymap.next");
9079 PtrPHI->addIncoming(PtrNext, BodyBB);
9080 llvm::Value *IsDone =
9081 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone");
9082 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit");
9083 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
9084
9085 MapperCGF.EmitBlock(ExitBB);
9086 // Emit array deletion if this is an array section and \p MapType indicates
9087 // that deletion is required.
9088 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
9089 ElementSize, DoneBB, /*IsInit=*/false);
9090
9091 // Emit the function exit block.
9092 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true);
9093 MapperCGF.FinishFunction();
9094 UDMMap.try_emplace(D, Fn);
9095 if (CGF) {
9096 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn);
9097 Decls.second.push_back(D);
9098 }
9099}
9100
9101/// Emit the array initialization or deletion portion for user-defined mapper
9102/// code generation. First, it evaluates whether an array section is mapped and
9103/// whether the \a MapType instructs to delete this section. If \a IsInit is
9104/// true, and \a MapType indicates to not delete this array, array
9105/// initialization code is generated. If \a IsInit is false, and \a MapType
9106/// indicates to not this array, array deletion code is generated.
9107void CGOpenMPRuntime::emitUDMapperArrayInitOrDel(
9108 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base,
9109 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType,
9110 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) {
9111 StringRef Prefix = IsInit ? ".init" : ".del";
9112
9113 // Evaluate if this is an array section.
9114 llvm::BasicBlock *IsDeleteBB =
9115 MapperCGF.createBasicBlock("omp.array" + Prefix + ".evaldelete");
9116 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.array" + Prefix);
9117 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE(
9118 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray");
9119 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB);
9120
9121 // Evaluate if we are going to delete this section.
9122 MapperCGF.EmitBlock(IsDeleteBB);
9123 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd(
9124 MapType,
9125 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE));
9126 llvm::Value *DeleteCond;
9127 if (IsInit) {
9128 DeleteCond = MapperCGF.Builder.CreateIsNull(
9129 DeleteBit, "omp.array" + Prefix + ".delete");
9130 } else {
9131 DeleteCond = MapperCGF.Builder.CreateIsNotNull(
9132 DeleteBit, "omp.array" + Prefix + ".delete");
9133 }
9134 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB);
9135
9136 MapperCGF.EmitBlock(BodyBB);
9137 // Get the array size by multiplying element size and element number (i.e., \p
9138 // Size).
9139 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul(
9140 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
9141 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves
9142 // memory allocation/deletion purpose only.
9143 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd(
9144 MapType,
9145 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9146 MappableExprsHandler::OMP_MAP_FROM)));
9147 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9148 // data structure.
9149 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg};
9150 MapperCGF.EmitRuntimeCall(
9151 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs);
9152}
9153
Alexey Bataev7bb33532019-01-07 21:30:43 +00009154void CGOpenMPRuntime::emitTargetNumIterationsCall(
Alexey Bataevec7946e2019-09-23 14:06:51 +00009155 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9156 llvm::Value *DeviceID,
9157 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9158 const OMPLoopDirective &D)>
9159 SizeEmitter) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00009160 OpenMPDirectiveKind Kind = D.getDirectiveKind();
9161 const OMPExecutableDirective *TD = &D;
9162 // Get nested teams distribute kind directive, if any.
9163 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind))
9164 TD = getNestedDistributeDirective(CGM.getContext(), D);
9165 if (!TD)
9166 return;
9167 const auto *LD = cast<OMPLoopDirective>(TD);
Alexey Bataevec7946e2019-09-23 14:06:51 +00009168 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF,
Alexey Bataev7bb33532019-01-07 21:30:43 +00009169 PrePostActionTy &) {
Alexey Bataevec7946e2019-09-23 14:06:51 +00009170 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) {
9171 llvm::Value *Args[] = {DeviceID, NumIterations};
9172 CGF.EmitRuntimeCall(
9173 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args);
9174 }
Alexey Bataev7bb33532019-01-07 21:30:43 +00009175 };
9176 emitInlinedDirective(CGF, OMPD_unknown, CodeGen);
9177}
9178
Alexey Bataevec7946e2019-09-23 14:06:51 +00009179void CGOpenMPRuntime::emitTargetCall(
9180 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9181 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
9182 const Expr *Device,
9183 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9184 const OMPLoopDirective &D)>
9185 SizeEmitter) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00009186 if (!CGF.HaveInsertPoint())
9187 return;
Samuel Antaobed3c462015-10-02 16:14:20 +00009188
Samuel Antaoee8fb302016-01-06 13:42:12 +00009189 assert(OutlinedFn && "Invalid outlined function!");
9190
Alexey Bataev8451efa2018-01-15 19:06:12 +00009191 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>();
9192 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
Alexey Bataev475a7442018-01-12 19:39:11 +00009193 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009194 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF,
9195 PrePostActionTy &) {
9196 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9197 };
9198 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen);
Samuel Antao86ace552016-04-27 22:40:57 +00009199
Alexey Bataev8451efa2018-01-15 19:06:12 +00009200 CodeGenFunction::OMPTargetDataInfo InputInfo;
9201 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobed3c462015-10-02 16:14:20 +00009202 // Fill up the pointer arrays and transfer execution to the device.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009203 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo,
Alexey Bataevec7946e2019-09-23 14:06:51 +00009204 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars,
9205 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobed3c462015-10-02 16:14:20 +00009206 // On top of the arrays that were filled up, the target offloading call
9207 // takes as arguments the device id as well as the host pointer. The host
9208 // pointer is used by the runtime library to identify the current target
9209 // region, so it only has to be unique and not necessarily point to
9210 // anything. It could be the pointer to the outlined function that
9211 // implements the target region, but we aren't using that so that the
9212 // compiler doesn't need to keep that, and could therefore inline the host
9213 // function if proven worthwhile during optimization.
9214
Samuel Antaoee8fb302016-01-06 13:42:12 +00009215 // From this point on, we need to have an ID of the target region defined.
9216 assert(OutlinedFnID && "Invalid outlined function ID!");
Samuel Antaobed3c462015-10-02 16:14:20 +00009217
9218 // Emit device ID if any.
9219 llvm::Value *DeviceID;
George Rokos63bc9d62017-11-21 18:25:12 +00009220 if (Device) {
Samuel Antaobed3c462015-10-02 16:14:20 +00009221 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009222 CGF.Int64Ty, /*isSigned=*/true);
9223 } else {
9224 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9225 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009226
Samuel Antaodf158d52016-04-27 22:58:19 +00009227 // Emit the number of elements in the offloading arrays.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009228 llvm::Value *PointerNum =
9229 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaodf158d52016-04-27 22:58:19 +00009230
Samuel Antaob68e2db2016-03-03 16:20:23 +00009231 // Return value of the runtime offloading call.
9232 llvm::Value *Return;
9233
Alexey Bataev5c427362019-04-10 19:11:33 +00009234 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D);
9235 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009236
Alexey Bataevec7946e2019-09-23 14:06:51 +00009237 // Emit tripcount for the target loop-based directive.
9238 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter);
9239
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009240 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00009241 // The target region is an outlined function launched by the runtime
9242 // via calls __tgt_target() or __tgt_target_teams().
9243 //
9244 // __tgt_target() launches a target region with one team and one thread,
9245 // executing a serial region. This master thread may in turn launch
9246 // more threads within its team upon encountering a parallel region,
9247 // however, no additional teams can be launched on the device.
9248 //
9249 // __tgt_target_teams() launches a target region with one or more teams,
9250 // each with one or more threads. This call is required for target
9251 // constructs such as:
9252 // 'target teams'
9253 // 'target' / 'teams'
9254 // 'target teams distribute parallel for'
9255 // 'target parallel'
9256 // and so on.
9257 //
9258 // Note that on the host and CPU targets, the runtime implementation of
9259 // these calls simply call the outlined function without forking threads.
9260 // The outlined functions themselves have runtime calls to
9261 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by
9262 // the compiler in emitTeamsCall() and emitParallelCall().
9263 //
9264 // In contrast, on the NVPTX target, the implementation of
9265 // __tgt_target_teams() launches a GPU kernel with the requested number
9266 // of teams and threads so no additional calls to the runtime are required.
Samuel Antaob68e2db2016-03-03 16:20:23 +00009267 if (NumTeams) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00009268 // If we have NumTeams defined this means that we have an enclosed teams
9269 // region. Therefore we also expect to have NumThreads defined. These two
9270 // values should be defined in the presence of a teams directive,
9271 // regardless of having any clauses associated. If the user is using teams
9272 // but no clauses, these two values will be the default that should be
9273 // passed to the runtime library - a 32-bit integer with the value zero.
9274 assert(NumThreads && "Thread limit expression should be available along "
9275 "with number of teams.");
Alexey Bataev8451efa2018-01-15 19:06:12 +00009276 llvm::Value *OffloadingArgs[] = {DeviceID,
9277 OutlinedFnID,
9278 PointerNum,
9279 InputInfo.BasePointersArray.getPointer(),
9280 InputInfo.PointersArray.getPointer(),
9281 InputInfo.SizesArray.getPointer(),
9282 MapTypesArray,
9283 NumTeams,
9284 NumThreads};
Samuel Antaob68e2db2016-03-03 16:20:23 +00009285 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00009286 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait
9287 : OMPRTL__tgt_target_teams),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009288 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009289 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009290 llvm::Value *OffloadingArgs[] = {DeviceID,
9291 OutlinedFnID,
9292 PointerNum,
9293 InputInfo.BasePointersArray.getPointer(),
9294 InputInfo.PointersArray.getPointer(),
9295 InputInfo.SizesArray.getPointer(),
9296 MapTypesArray};
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009297 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00009298 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait
9299 : OMPRTL__tgt_target),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009300 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009301 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009302
Alexey Bataev2a007e02017-10-02 14:20:58 +00009303 // Check the error code and execute the host version if required.
9304 llvm::BasicBlock *OffloadFailedBlock =
9305 CGF.createBasicBlock("omp_offload.failed");
9306 llvm::BasicBlock *OffloadContBlock =
9307 CGF.createBasicBlock("omp_offload.cont");
9308 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return);
9309 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
9310
9311 CGF.EmitBlock(OffloadFailedBlock);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009312 if (RequiresOuterTask) {
9313 CapturedVars.clear();
9314 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9315 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009316 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev2a007e02017-10-02 14:20:58 +00009317 CGF.EmitBranch(OffloadContBlock);
9318
9319 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00009320 };
9321
Samuel Antaoee8fb302016-01-06 13:42:12 +00009322 // Notify that the host version must be executed.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009323 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars,
9324 RequiresOuterTask](CodeGenFunction &CGF,
9325 PrePostActionTy &) {
9326 if (RequiresOuterTask) {
9327 CapturedVars.clear();
9328 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9329 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009330 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009331 };
9332
9333 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray,
9334 &CapturedVars, RequiresOuterTask,
9335 &CS](CodeGenFunction &CGF, PrePostActionTy &) {
9336 // Fill up the arrays with all the captured variables.
9337 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
9338 MappableExprsHandler::MapValuesArrayTy Pointers;
9339 MappableExprsHandler::MapValuesArrayTy Sizes;
9340 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9341
Alexey Bataev8451efa2018-01-15 19:06:12 +00009342 // Get mappable expression information.
9343 MappableExprsHandler MEHandler(D, CGF);
Alexey Bataev969dbc02018-11-08 15:47:39 +00009344 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
Alexey Bataev8451efa2018-01-15 19:06:12 +00009345
9346 auto RI = CS.getCapturedRecordDecl()->field_begin();
9347 auto CV = CapturedVars.begin();
9348 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
9349 CE = CS.capture_end();
9350 CI != CE; ++CI, ++RI, ++CV) {
Alexey Bataevb3638132018-07-19 16:34:13 +00009351 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers;
9352 MappableExprsHandler::MapValuesArrayTy CurPointers;
9353 MappableExprsHandler::MapValuesArrayTy CurSizes;
9354 MappableExprsHandler::MapFlagsArrayTy CurMapTypes;
9355 MappableExprsHandler::StructRangeInfoTy PartialStruct;
Alexey Bataev8451efa2018-01-15 19:06:12 +00009356
9357 // VLA sizes are passed to the outlined region by copy and do not have map
9358 // information associated.
9359 if (CI->capturesVariableArrayType()) {
9360 CurBasePointers.push_back(*CV);
9361 CurPointers.push_back(*CV);
Alexey Bataeva90fc662019-06-25 16:00:43 +00009362 CurSizes.push_back(CGF.Builder.CreateIntCast(
9363 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev8451efa2018-01-15 19:06:12 +00009364 // Copy to the device as an argument. No need to retrieve it.
9365 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL |
Alexey Bataevf288cf92019-06-27 18:53:07 +00009366 MappableExprsHandler::OMP_MAP_TARGET_PARAM |
9367 MappableExprsHandler::OMP_MAP_IMPLICIT);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009368 } else {
9369 // If we have any information in the map clause, we use it, otherwise we
9370 // just do a default mapping.
9371 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00009372 CurSizes, CurMapTypes, PartialStruct);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009373 if (CurBasePointers.empty())
9374 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers,
9375 CurPointers, CurSizes, CurMapTypes);
Alexey Bataev60705422018-10-30 15:50:12 +00009376 // Generate correct mapping for variables captured by reference in
9377 // lambdas.
9378 if (CI->capturesVariable())
Alexey Bataev969dbc02018-11-08 15:47:39 +00009379 MEHandler.generateInfoForLambdaCaptures(
9380 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes,
9381 CurMapTypes, LambdaPointers);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009382 }
9383 // We expect to have at least an element of information for this capture.
9384 assert(!CurBasePointers.empty() &&
9385 "Non-existing map pointer for capture!");
9386 assert(CurBasePointers.size() == CurPointers.size() &&
9387 CurBasePointers.size() == CurSizes.size() &&
9388 CurBasePointers.size() == CurMapTypes.size() &&
9389 "Inconsistent map information sizes!");
9390
Alexey Bataevb3638132018-07-19 16:34:13 +00009391 // If there is an entry in PartialStruct it means we have a struct with
9392 // individual members mapped. Emit an extra combined entry.
9393 if (PartialStruct.Base.isValid())
9394 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes,
9395 CurMapTypes, PartialStruct);
9396
Alexey Bataev8451efa2018-01-15 19:06:12 +00009397 // We need to append the results of this capture to what we already have.
9398 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
9399 Pointers.append(CurPointers.begin(), CurPointers.end());
9400 Sizes.append(CurSizes.begin(), CurSizes.end());
9401 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end());
9402 }
Alexey Bataev60705422018-10-30 15:50:12 +00009403 // Adjust MEMBER_OF flags for the lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00009404 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers,
9405 Pointers, MapTypes);
Alexey Bataev92327c52018-03-26 16:40:55 +00009406 // Map other list items in the map clause which are not captured variables
9407 // but "declare target link" global variables.
Alexey Bataevb3638132018-07-19 16:34:13 +00009408 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes,
9409 MapTypes);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009410
9411 TargetDataInfo Info;
9412 // Fill up the arrays and create the arguments.
9413 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
9414 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
9415 Info.PointersArray, Info.SizesArray,
9416 Info.MapTypesArray, Info);
9417 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
9418 InputInfo.BasePointersArray =
9419 Address(Info.BasePointersArray, CGM.getPointerAlign());
9420 InputInfo.PointersArray =
9421 Address(Info.PointersArray, CGM.getPointerAlign());
9422 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign());
9423 MapTypesArray = Info.MapTypesArray;
9424 if (RequiresOuterTask)
9425 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
9426 else
9427 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
9428 };
9429
9430 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask](
9431 CodeGenFunction &CGF, PrePostActionTy &) {
9432 if (RequiresOuterTask) {
9433 CodeGenFunction::OMPTargetDataInfo InputInfo;
9434 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo);
9435 } else {
9436 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen);
9437 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009438 };
9439
9440 // If we have a target function ID it means that we need to support
9441 // offloading, otherwise, just execute on the host. We need to execute on host
9442 // regardless of the conditional in the if clause if, e.g., the user do not
9443 // specify target triples.
9444 if (OutlinedFnID) {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009445 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -05009446 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009447 } else {
9448 RegionCodeGenTy ThenRCG(TargetThenGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00009449 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00009450 }
9451 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009452 RegionCodeGenTy ElseRCG(TargetElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00009453 ElseRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00009454 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009455}
Samuel Antaoee8fb302016-01-06 13:42:12 +00009456
9457void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
9458 StringRef ParentName) {
9459 if (!S)
9460 return;
9461
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009462 // Codegen OMP target directives that offload compute to the device.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009463 bool RequiresDeviceCodegen =
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009464 isa<OMPExecutableDirective>(S) &&
9465 isOpenMPTargetExecutionDirective(
9466 cast<OMPExecutableDirective>(S)->getDirectiveKind());
Samuel Antaoee8fb302016-01-06 13:42:12 +00009467
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009468 if (RequiresDeviceCodegen) {
9469 const auto &E = *cast<OMPExecutableDirective>(S);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009470 unsigned DeviceID;
9471 unsigned FileID;
9472 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009473 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID,
Samuel Antao2de62b02016-02-13 23:35:10 +00009474 FileID, Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009475
9476 // Is this a target region that should not be emitted as an entry point? If
9477 // so just signal we are done with this target region.
Samuel Antao2de62b02016-02-13 23:35:10 +00009478 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
9479 ParentName, Line))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009480 return;
9481
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009482 switch (E.getDirectiveKind()) {
9483 case OMPD_target:
9484 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName,
9485 cast<OMPTargetDirective>(E));
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009486 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009487 case OMPD_target_parallel:
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009488 CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009489 CGM, ParentName, cast<OMPTargetParallelDirective>(E));
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009490 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009491 case OMPD_target_teams:
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009492 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009493 CGM, ParentName, cast<OMPTargetTeamsDirective>(E));
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009494 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009495 case OMPD_target_teams_distribute:
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009496 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009497 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E));
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009498 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009499 case OMPD_target_teams_distribute_simd:
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009500 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009501 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E));
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009502 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009503 case OMPD_target_parallel_for:
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009504 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009505 CGM, ParentName, cast<OMPTargetParallelForDirective>(E));
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009506 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009507 case OMPD_target_parallel_for_simd:
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009508 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009509 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E));
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009510 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009511 case OMPD_target_simd:
Alexey Bataevf8365372017-11-17 17:57:25 +00009512 CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009513 CGM, ParentName, cast<OMPTargetSimdDirective>(E));
Alexey Bataevf8365372017-11-17 17:57:25 +00009514 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009515 case OMPD_target_teams_distribute_parallel_for:
Carlo Bertolli52978c32018-01-03 21:12:44 +00009516 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
9517 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009518 cast<OMPTargetTeamsDistributeParallelForDirective>(E));
Carlo Bertolli52978c32018-01-03 21:12:44 +00009519 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009520 case OMPD_target_teams_distribute_parallel_for_simd:
Alexey Bataev647dd842018-01-15 20:59:40 +00009521 CodeGenFunction::
9522 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
9523 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009524 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E));
Alexey Bataev647dd842018-01-15 20:59:40 +00009525 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009526 case OMPD_parallel:
9527 case OMPD_for:
9528 case OMPD_parallel_for:
cchen47d60942019-12-05 13:43:48 -05009529 case OMPD_parallel_master:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009530 case OMPD_parallel_sections:
9531 case OMPD_for_simd:
9532 case OMPD_parallel_for_simd:
9533 case OMPD_cancel:
9534 case OMPD_cancellation_point:
9535 case OMPD_ordered:
9536 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00009537 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009538 case OMPD_task:
9539 case OMPD_simd:
9540 case OMPD_sections:
9541 case OMPD_section:
9542 case OMPD_single:
9543 case OMPD_master:
9544 case OMPD_critical:
9545 case OMPD_taskyield:
9546 case OMPD_barrier:
9547 case OMPD_taskwait:
9548 case OMPD_taskgroup:
9549 case OMPD_atomic:
9550 case OMPD_flush:
9551 case OMPD_teams:
9552 case OMPD_target_data:
9553 case OMPD_target_exit_data:
9554 case OMPD_target_enter_data:
9555 case OMPD_distribute:
9556 case OMPD_distribute_simd:
9557 case OMPD_distribute_parallel_for:
9558 case OMPD_distribute_parallel_for_simd:
9559 case OMPD_teams_distribute:
9560 case OMPD_teams_distribute_simd:
9561 case OMPD_teams_distribute_parallel_for:
9562 case OMPD_teams_distribute_parallel_for_simd:
9563 case OMPD_target_update:
9564 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00009565 case OMPD_declare_variant:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009566 case OMPD_declare_target:
9567 case OMPD_end_declare_target:
9568 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00009569 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009570 case OMPD_taskloop:
9571 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00009572 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00009573 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00009574 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04009575 case OMPD_parallel_master_taskloop_simd:
Kelvin Li1408f912018-09-26 04:28:39 +00009576 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009577 case OMPD_unknown:
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009578 llvm_unreachable("Unknown target directive for OpenMP device codegen.");
9579 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009580 return;
9581 }
9582
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009583 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
Alexey Bataev475a7442018-01-12 19:39:11 +00009584 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009585 return;
9586
9587 scanForTargetRegionsFunctions(
Alexey Bataev475a7442018-01-12 19:39:11 +00009588 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009589 return;
9590 }
9591
9592 // If this is a lambda function, look into its body.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009593 if (const auto *L = dyn_cast<LambdaExpr>(S))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009594 S = L->getBody();
9595
9596 // Keep looking for target regions recursively.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009597 for (const Stmt *II : S->children())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009598 scanForTargetRegionsFunctions(II, ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009599}
9600
9601bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009602 // If emitting code for the host, we do not process FD here. Instead we do
9603 // the normal code generation.
Alexey Bataev729e2422019-08-23 16:11:14 +00009604 if (!CGM.getLangOpts().OpenMPIsDevice) {
9605 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) {
9606 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9607 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9608 // Do not emit device_type(nohost) functions for the host.
9609 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
9610 return true;
9611 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009612 return false;
Alexey Bataev729e2422019-08-23 16:11:14 +00009613 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009614
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009615 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009616 StringRef Name = CGM.getMangledName(GD);
9617 // Try to detect target regions in the function.
Alexey Bataev729e2422019-08-23 16:11:14 +00009618 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009619 scanForTargetRegionsFunctions(FD->getBody(), Name);
Alexey Bataev729e2422019-08-23 16:11:14 +00009620 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9621 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9622 // Do not emit device_type(nohost) functions for the host.
9623 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
9624 return true;
9625 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009626
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009627 // Do not to emit function if it is not marked as declare target.
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009628 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009629 AlreadyEmittedTargetFunctions.count(Name) == 0;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009630}
9631
9632bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
9633 if (!CGM.getLangOpts().OpenMPIsDevice)
9634 return false;
9635
9636 // Check if there are Ctors/Dtors in this declaration and look for target
9637 // regions in it. We use the complete variant to produce the kernel name
9638 // mangling.
9639 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009640 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
9641 for (const CXXConstructorDecl *Ctor : RD->ctors()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009642 StringRef ParentName =
9643 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
9644 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
9645 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009646 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009647 StringRef ParentName =
9648 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
9649 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
9650 }
9651 }
9652
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009653 // Do not to emit variable if it is not marked as declare target.
Alexey Bataev92327c52018-03-26 16:40:55 +00009654 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009655 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
9656 cast<VarDecl>(GD.getDecl()));
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009657 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
9658 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9659 HasRequiresUnifiedSharedMemory)) {
Alexey Bataevd01b7492018-08-15 19:45:12 +00009660 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009661 return true;
9662 }
9663 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009664}
9665
Alexey Bataev1af5bd52019-03-05 17:47:18 +00009666llvm::Constant *
9667CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF,
9668 const VarDecl *VD) {
9669 assert(VD->getType().isConstant(CGM.getContext()) &&
9670 "Expected constant variable.");
9671 StringRef VarName;
9672 llvm::Constant *Addr;
9673 llvm::GlobalValue::LinkageTypes Linkage;
9674 QualType Ty = VD->getType();
9675 SmallString<128> Buffer;
9676 {
9677 unsigned DeviceID;
9678 unsigned FileID;
9679 unsigned Line;
9680 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID,
9681 FileID, Line);
9682 llvm::raw_svector_ostream OS(Buffer);
9683 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID)
9684 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
9685 VarName = OS.str();
9686 }
9687 Linkage = llvm::GlobalValue::InternalLinkage;
9688 Addr =
9689 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName,
9690 getDefaultFirstprivateAddressSpace());
9691 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage);
9692 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty);
9693 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr));
9694 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9695 VarName, Addr, VarSize,
9696 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage);
9697 return Addr;
9698}
9699
Alexey Bataev03f270c2018-03-30 18:31:07 +00009700void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
9701 llvm::Constant *Addr) {
Alexey Bataev36724b72019-10-03 16:46:49 +00009702 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
9703 !CGM.getLangOpts().OpenMPIsDevice)
Alexey Bataev4db9dc62019-09-23 15:53:51 +00009704 return;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009705 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9706 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
9707 if (!Res) {
9708 if (CGM.getLangOpts().OpenMPIsDevice) {
9709 // Register non-target variables being emitted in device code (debug info
9710 // may cause this).
9711 StringRef VarName = CGM.getMangledName(VD);
9712 EmittedNonTargetVariables.try_emplace(VarName, Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009713 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009714 return;
Alexey Bataev03f270c2018-03-30 18:31:07 +00009715 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009716 // Register declare target variables.
9717 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
9718 StringRef VarName;
9719 CharUnits VarSize;
9720 llvm::GlobalValue::LinkageTypes Linkage;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009721
9722 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9723 !HasRequiresUnifiedSharedMemory) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009724 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9725 VarName = CGM.getMangledName(VD);
9726 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) {
9727 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType());
9728 assert(!VarSize.isZero() && "Expected non-zero size of the variable");
9729 } else {
9730 VarSize = CharUnits::Zero();
9731 }
9732 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
9733 // Temp solution to prevent optimizations of the internal variables.
9734 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) {
9735 std::string RefName = getName({VarName, "ref"});
9736 if (!CGM.GetGlobalValue(RefName)) {
9737 llvm::Constant *AddrRef =
9738 getOrCreateInternalVariable(Addr->getType(), RefName);
9739 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef);
9740 GVAddrRef->setConstant(/*Val=*/true);
9741 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage);
9742 GVAddrRef->setInitializer(Addr);
9743 CGM.addCompilerUsedGlobal(GVAddrRef);
9744 }
9745 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009746 } else {
9747 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
9748 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9749 HasRequiresUnifiedSharedMemory)) &&
9750 "Declare target attribute must link or to with unified memory.");
9751 if (*Res == OMPDeclareTargetDeclAttr::MT_Link)
9752 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink;
9753 else
9754 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9755
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009756 if (CGM.getLangOpts().OpenMPIsDevice) {
9757 VarName = Addr->getName();
9758 Addr = nullptr;
9759 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009760 VarName = getAddrOfDeclareTargetVar(VD).getName();
9761 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009762 }
9763 VarSize = CGM.getPointerSize();
9764 Linkage = llvm::GlobalValue::WeakAnyLinkage;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009765 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009766
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009767 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9768 VarName, Addr, VarSize, Flags, Linkage);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009769}
9770
Samuel Antaoee8fb302016-01-06 13:42:12 +00009771bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009772 if (isa<FunctionDecl>(GD.getDecl()) ||
9773 isa<OMPDeclareReductionDecl>(GD.getDecl()))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009774 return emitTargetFunctions(GD);
9775
9776 return emitTargetGlobalVariable(GD);
9777}
9778
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009779void CGOpenMPRuntime::emitDeferredTargetDecls() const {
9780 for (const VarDecl *VD : DeferredGlobalVariables) {
9781 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009782 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009783 if (!Res)
9784 continue;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009785 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9786 !HasRequiresUnifiedSharedMemory) {
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009787 CGM.EmitGlobal(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009788 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009789 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
9790 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9791 HasRequiresUnifiedSharedMemory)) &&
9792 "Expected link clause or to clause with unified memory.");
9793 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009794 }
9795 }
9796}
9797
Alexey Bataev60705422018-10-30 15:50:12 +00009798void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas(
9799 CodeGenFunction &CGF, const OMPExecutableDirective &D) const {
9800 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) &&
9801 " Expected target-based directive.");
9802}
9803
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009804void CGOpenMPRuntime::checkArchForUnifiedAddressing(
9805 const OMPRequiresDecl *D) {
9806 for (const OMPClause *Clause : D->clauselists()) {
9807 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
9808 HasRequiresUnifiedSharedMemory = true;
9809 break;
9810 }
9811 }
9812}
9813
Alexey Bataevc5687252019-03-21 19:35:27 +00009814bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD,
9815 LangAS &AS) {
9816 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())
9817 return false;
9818 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
9819 switch(A->getAllocatorType()) {
9820 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
9821 // Not supported, fallback to the default mem space.
9822 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
9823 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
9824 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
9825 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
9826 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
9827 case OMPAllocateDeclAttr::OMPConstMemAlloc:
9828 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
9829 AS = LangAS::Default;
9830 return true;
9831 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
9832 llvm_unreachable("Expected predefined allocator for the variables with the "
9833 "static storage.");
9834 }
9835 return false;
9836}
9837
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00009838bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const {
9839 return HasRequiresUnifiedSharedMemory;
9840}
9841
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009842CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
9843 CodeGenModule &CGM)
9844 : CGM(CGM) {
9845 if (CGM.getLangOpts().OpenMPIsDevice) {
9846 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
9847 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
9848 }
9849}
9850
9851CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() {
9852 if (CGM.getLangOpts().OpenMPIsDevice)
9853 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
9854}
9855
Alexey Bataev6d944102018-05-02 15:45:28 +00009856bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009857 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal)
9858 return true;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009859
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009860 StringRef Name = CGM.getMangledName(GD);
Alexey Bataev6d944102018-05-02 15:45:28 +00009861 const auto *D = cast<FunctionDecl>(GD.getDecl());
Alexey Bataev34f8a702018-03-28 14:28:54 +00009862 // Do not to emit function if it is marked as declare target as it was already
9863 // emitted.
Alexey Bataev97b72212018-08-14 18:31:20 +00009864 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009865 if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) {
9866 if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name)))
Alexey Bataev34f8a702018-03-28 14:28:54 +00009867 return !F->isDeclaration();
9868 return false;
9869 }
9870 return true;
9871 }
9872
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009873 return !AlreadyEmittedTargetFunctions.insert(Name).second;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009874}
9875
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009876llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() {
9877 // If we don't have entries or if we are emitting code for the device, we
9878 // don't need to do anything.
9879 if (CGM.getLangOpts().OMPTargetTriples.empty() ||
9880 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice ||
9881 (OffloadEntriesInfoManager.empty() &&
9882 !HasEmittedDeclareTargetRegion &&
9883 !HasEmittedTargetRegion))
9884 return nullptr;
9885
9886 // Create and register the function that handles the requires directives.
9887 ASTContext &C = CGM.getContext();
9888
9889 llvm::Function *RequiresRegFn;
9890 {
9891 CodeGenFunction CGF(CGM);
9892 const auto &FI = CGM.getTypes().arrangeNullaryFunction();
9893 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
9894 std::string ReqName = getName({"omp_offloading", "requires_reg"});
9895 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI);
9896 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {});
9897 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE;
9898 // TODO: check for other requires clauses.
9899 // The requires directive takes effect only when a target region is
9900 // present in the compilation unit. Otherwise it is ignored and not
9901 // passed to the runtime. This avoids the runtime from throwing an error
9902 // for mismatching requires clauses across compilation units that don't
9903 // contain at least 1 target region.
9904 assert((HasEmittedTargetRegion ||
9905 HasEmittedDeclareTargetRegion ||
9906 !OffloadEntriesInfoManager.empty()) &&
9907 "Target or declare target region expected.");
9908 if (HasRequiresUnifiedSharedMemory)
9909 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY;
9910 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires),
9911 llvm::ConstantInt::get(CGM.Int64Ty, Flags));
9912 CGF.FinishFunction();
9913 }
9914 return RequiresRegFn;
9915}
9916
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009917void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
9918 const OMPExecutableDirective &D,
9919 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00009920 llvm::Function *OutlinedFn,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009921 ArrayRef<llvm::Value *> CapturedVars) {
9922 if (!CGF.HaveInsertPoint())
9923 return;
9924
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009925 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009926 CodeGenFunction::RunCleanupsScope Scope(CGF);
9927
9928 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
9929 llvm::Value *Args[] = {
9930 RTLoc,
9931 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
9932 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
9933 llvm::SmallVector<llvm::Value *, 16> RealArgs;
9934 RealArgs.append(std::begin(Args), std::end(Args));
9935 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
9936
James Y Knight9871db02019-02-05 16:42:33 +00009937 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009938 CGF.EmitRuntimeCall(RTLFn, RealArgs);
9939}
9940
9941void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
Carlo Bertollic6872252016-04-04 15:55:02 +00009942 const Expr *NumTeams,
9943 const Expr *ThreadLimit,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009944 SourceLocation Loc) {
9945 if (!CGF.HaveInsertPoint())
9946 return;
9947
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009948 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009949
Carlo Bertollic6872252016-04-04 15:55:02 +00009950 llvm::Value *NumTeamsVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009951 NumTeams
Carlo Bertollic6872252016-04-04 15:55:02 +00009952 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
9953 CGF.CGM.Int32Ty, /* isSigned = */ true)
9954 : CGF.Builder.getInt32(0);
9955
9956 llvm::Value *ThreadLimitVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009957 ThreadLimit
Carlo Bertollic6872252016-04-04 15:55:02 +00009958 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
9959 CGF.CGM.Int32Ty, /* isSigned = */ true)
9960 : CGF.Builder.getInt32(0);
9961
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009962 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
Carlo Bertollic6872252016-04-04 15:55:02 +00009963 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
9964 ThreadLimitVal};
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009965 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams),
9966 PushNumTeamsArgs);
9967}
Samuel Antaodf158d52016-04-27 22:58:19 +00009968
Samuel Antaocc10b852016-07-28 14:23:26 +00009969void CGOpenMPRuntime::emitTargetDataCalls(
9970 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
9971 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009972 if (!CGF.HaveInsertPoint())
9973 return;
9974
Samuel Antaocc10b852016-07-28 14:23:26 +00009975 // Action used to replace the default codegen action and turn privatization
9976 // off.
9977 PrePostActionTy NoPrivAction;
Samuel Antaodf158d52016-04-27 22:58:19 +00009978
9979 // Generate the code for the opening of the data environment. Capture all the
9980 // arguments of the runtime call by reference because they are used in the
9981 // closing of the region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009982 auto &&BeginThenGen = [this, &D, Device, &Info,
9983 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009984 // Fill up the arrays with all the mapped variables.
Samuel Antaocc10b852016-07-28 14:23:26 +00009985 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
Samuel Antaodf158d52016-04-27 22:58:19 +00009986 MappableExprsHandler::MapValuesArrayTy Pointers;
9987 MappableExprsHandler::MapValuesArrayTy Sizes;
9988 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9989
9990 // Get map clause information.
9991 MappableExprsHandler MCHandler(D, CGF);
9992 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
Samuel Antaodf158d52016-04-27 22:58:19 +00009993
9994 // Fill up the arrays and create the arguments.
Samuel Antaocc10b852016-07-28 14:23:26 +00009995 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +00009996
9997 llvm::Value *BasePointersArrayArg = nullptr;
9998 llvm::Value *PointersArrayArg = nullptr;
9999 llvm::Value *SizesArrayArg = nullptr;
10000 llvm::Value *MapTypesArrayArg = nullptr;
10001 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +000010002 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +000010003
10004 // Emit device ID if any.
10005 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010006 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +000010007 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010008 CGF.Int64Ty, /*isSigned=*/true);
10009 } else {
10010 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10011 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010012
10013 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010014 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +000010015
10016 llvm::Value *OffloadingArgs[] = {
10017 DeviceID, PointerNum, BasePointersArrayArg,
10018 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010019 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin),
Samuel Antaodf158d52016-04-27 22:58:19 +000010020 OffloadingArgs);
Samuel Antaocc10b852016-07-28 14:23:26 +000010021
10022 // If device pointer privatization is required, emit the body of the region
10023 // here. It will have to be duplicated: with and without privatization.
10024 if (!Info.CaptureDeviceAddrMap.empty())
10025 CodeGen(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010026 };
10027
10028 // Generate code for the closing of the data region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010029 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF,
10030 PrePostActionTy &) {
Samuel Antaocc10b852016-07-28 14:23:26 +000010031 assert(Info.isValid() && "Invalid data environment closing arguments.");
Samuel Antaodf158d52016-04-27 22:58:19 +000010032
10033 llvm::Value *BasePointersArrayArg = nullptr;
10034 llvm::Value *PointersArrayArg = nullptr;
10035 llvm::Value *SizesArrayArg = nullptr;
10036 llvm::Value *MapTypesArrayArg = nullptr;
10037 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +000010038 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +000010039
10040 // Emit device ID if any.
10041 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010042 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +000010043 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010044 CGF.Int64Ty, /*isSigned=*/true);
10045 } else {
10046 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10047 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010048
10049 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010050 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +000010051
10052 llvm::Value *OffloadingArgs[] = {
10053 DeviceID, PointerNum, BasePointersArrayArg,
10054 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010055 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end),
Samuel Antaodf158d52016-04-27 22:58:19 +000010056 OffloadingArgs);
10057 };
10058
Samuel Antaocc10b852016-07-28 14:23:26 +000010059 // If we need device pointer privatization, we need to emit the body of the
10060 // region with no privatization in the 'else' branch of the conditional.
10061 // Otherwise, we don't have to do anything.
10062 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF,
10063 PrePostActionTy &) {
10064 if (!Info.CaptureDeviceAddrMap.empty()) {
10065 CodeGen.setAction(NoPrivAction);
10066 CodeGen(CGF);
10067 }
10068 };
10069
10070 // We don't have to do anything to close the region if the if clause evaluates
10071 // to false.
10072 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
Samuel Antaodf158d52016-04-27 22:58:19 +000010073
10074 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -050010075 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +000010076 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +000010077 RegionCodeGenTy RCG(BeginThenGen);
10078 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010079 }
10080
Samuel Antaocc10b852016-07-28 14:23:26 +000010081 // If we don't require privatization of device pointers, we emit the body in
10082 // between the runtime calls. This avoids duplicating the body code.
10083 if (Info.CaptureDeviceAddrMap.empty()) {
10084 CodeGen.setAction(NoPrivAction);
10085 CodeGen(CGF);
10086 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010087
10088 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -050010089 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +000010090 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +000010091 RegionCodeGenTy RCG(EndThenGen);
10092 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010093 }
10094}
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010095
Samuel Antao8d2d7302016-05-26 18:30:22 +000010096void CGOpenMPRuntime::emitTargetDataStandAloneCall(
Samuel Antao8dd66282016-04-27 23:14:30 +000010097 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10098 const Expr *Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010099 if (!CGF.HaveInsertPoint())
10100 return;
10101
Samuel Antao8dd66282016-04-27 23:14:30 +000010102 assert((isa<OMPTargetEnterDataDirective>(D) ||
Samuel Antao8d2d7302016-05-26 18:30:22 +000010103 isa<OMPTargetExitDataDirective>(D) ||
10104 isa<OMPTargetUpdateDirective>(D)) &&
10105 "Expecting either target enter, exit data, or update directives.");
Samuel Antao8dd66282016-04-27 23:14:30 +000010106
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010107 CodeGenFunction::OMPTargetDataInfo InputInfo;
10108 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010109 // Generate the code for the opening of the data environment.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010110 auto &&ThenGen = [this, &D, Device, &InputInfo,
10111 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010112 // Emit device ID if any.
10113 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010114 if (Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010115 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010116 CGF.Int64Ty, /*isSigned=*/true);
10117 } else {
10118 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10119 }
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010120
10121 // Emit the number of elements in the offloading arrays.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010122 llvm::Constant *PointerNum =
10123 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010124
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010125 llvm::Value *OffloadingArgs[] = {DeviceID,
10126 PointerNum,
10127 InputInfo.BasePointersArray.getPointer(),
10128 InputInfo.PointersArray.getPointer(),
10129 InputInfo.SizesArray.getPointer(),
10130 MapTypesArray};
Samuel Antao8d2d7302016-05-26 18:30:22 +000010131
Samuel Antao8d2d7302016-05-26 18:30:22 +000010132 // Select the right runtime function call for each expected standalone
10133 // directive.
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010134 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Samuel Antao8d2d7302016-05-26 18:30:22 +000010135 OpenMPRTLFunction RTLFn;
10136 switch (D.getDirectiveKind()) {
Samuel Antao8d2d7302016-05-26 18:30:22 +000010137 case OMPD_target_enter_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010138 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait
10139 : OMPRTL__tgt_target_data_begin;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010140 break;
10141 case OMPD_target_exit_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010142 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait
10143 : OMPRTL__tgt_target_data_end;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010144 break;
10145 case OMPD_target_update:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010146 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait
10147 : OMPRTL__tgt_target_data_update;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010148 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010149 case OMPD_parallel:
10150 case OMPD_for:
10151 case OMPD_parallel_for:
cchen47d60942019-12-05 13:43:48 -050010152 case OMPD_parallel_master:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010153 case OMPD_parallel_sections:
10154 case OMPD_for_simd:
10155 case OMPD_parallel_for_simd:
10156 case OMPD_cancel:
10157 case OMPD_cancellation_point:
10158 case OMPD_ordered:
10159 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +000010160 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010161 case OMPD_task:
10162 case OMPD_simd:
10163 case OMPD_sections:
10164 case OMPD_section:
10165 case OMPD_single:
10166 case OMPD_master:
10167 case OMPD_critical:
10168 case OMPD_taskyield:
10169 case OMPD_barrier:
10170 case OMPD_taskwait:
10171 case OMPD_taskgroup:
10172 case OMPD_atomic:
10173 case OMPD_flush:
10174 case OMPD_teams:
10175 case OMPD_target_data:
10176 case OMPD_distribute:
10177 case OMPD_distribute_simd:
10178 case OMPD_distribute_parallel_for:
10179 case OMPD_distribute_parallel_for_simd:
10180 case OMPD_teams_distribute:
10181 case OMPD_teams_distribute_simd:
10182 case OMPD_teams_distribute_parallel_for:
10183 case OMPD_teams_distribute_parallel_for_simd:
10184 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +000010185 case OMPD_declare_variant:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010186 case OMPD_declare_target:
10187 case OMPD_end_declare_target:
10188 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +000010189 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010190 case OMPD_taskloop:
10191 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +000010192 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +000010193 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +000010194 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -040010195 case OMPD_parallel_master_taskloop_simd:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010196 case OMPD_target:
10197 case OMPD_target_simd:
10198 case OMPD_target_teams_distribute:
10199 case OMPD_target_teams_distribute_simd:
10200 case OMPD_target_teams_distribute_parallel_for:
10201 case OMPD_target_teams_distribute_parallel_for_simd:
10202 case OMPD_target_teams:
10203 case OMPD_target_parallel:
10204 case OMPD_target_parallel_for:
10205 case OMPD_target_parallel_for_simd:
Kelvin Li1408f912018-09-26 04:28:39 +000010206 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010207 case OMPD_unknown:
10208 llvm_unreachable("Unexpected standalone target data directive.");
10209 break;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010210 }
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010211 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010212 };
10213
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010214 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray](
10215 CodeGenFunction &CGF, PrePostActionTy &) {
10216 // Fill up the arrays with all the mapped variables.
10217 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
10218 MappableExprsHandler::MapValuesArrayTy Pointers;
10219 MappableExprsHandler::MapValuesArrayTy Sizes;
10220 MappableExprsHandler::MapFlagsArrayTy MapTypes;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010221
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010222 // Get map clause information.
10223 MappableExprsHandler MEHandler(D, CGF);
10224 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
10225
10226 TargetDataInfo Info;
10227 // Fill up the arrays and create the arguments.
10228 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
10229 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
10230 Info.PointersArray, Info.SizesArray,
10231 Info.MapTypesArray, Info);
10232 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
10233 InputInfo.BasePointersArray =
10234 Address(Info.BasePointersArray, CGM.getPointerAlign());
10235 InputInfo.PointersArray =
10236 Address(Info.PointersArray, CGM.getPointerAlign());
10237 InputInfo.SizesArray =
10238 Address(Info.SizesArray, CGM.getPointerAlign());
10239 MapTypesArray = Info.MapTypesArray;
10240 if (D.hasClausesOfKind<OMPDependClause>())
10241 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
10242 else
Alexey Bataev768f1f22018-01-09 19:59:25 +000010243 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010244 };
10245
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010246 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -050010247 emitIfClause(CGF, IfCond, TargetThenGen,
10248 [](CodeGenFunction &CGF, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010249 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010250 RegionCodeGenTy ThenRCG(TargetThenGen);
10251 ThenRCG(CGF);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010252 }
10253}
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010254
10255namespace {
10256 /// Kind of parameter in a function with 'declare simd' directive.
10257 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector };
10258 /// Attribute set of the parameter.
10259 struct ParamAttrTy {
10260 ParamKindTy Kind = Vector;
10261 llvm::APSInt StrideOrArg;
10262 llvm::APSInt Alignment;
10263 };
10264} // namespace
10265
10266static unsigned evaluateCDTSize(const FunctionDecl *FD,
10267 ArrayRef<ParamAttrTy> ParamAttrs) {
10268 // Every vector variant of a SIMD-enabled function has a vector length (VLEN).
10269 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument
10270 // of that clause. The VLEN value must be power of 2.
10271 // In other case the notion of the function`s "characteristic data type" (CDT)
10272 // is used to compute the vector length.
10273 // CDT is defined in the following order:
10274 // a) For non-void function, the CDT is the return type.
10275 // b) If the function has any non-uniform, non-linear parameters, then the
10276 // CDT is the type of the first such parameter.
10277 // c) If the CDT determined by a) or b) above is struct, union, or class
10278 // type which is pass-by-value (except for the type that maps to the
10279 // built-in complex data type), the characteristic data type is int.
10280 // d) If none of the above three cases is applicable, the CDT is int.
10281 // The VLEN is then determined based on the CDT and the size of vector
10282 // register of that ISA for which current vector version is generated. The
10283 // VLEN is computed using the formula below:
10284 // VLEN = sizeof(vector_register) / sizeof(CDT),
10285 // where vector register size specified in section 3.2.1 Registers and the
10286 // Stack Frame of original AMD64 ABI document.
10287 QualType RetType = FD->getReturnType();
10288 if (RetType.isNull())
10289 return 0;
10290 ASTContext &C = FD->getASTContext();
10291 QualType CDT;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010292 if (!RetType.isNull() && !RetType->isVoidType()) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010293 CDT = RetType;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010294 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010295 unsigned Offset = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010296 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010297 if (ParamAttrs[Offset].Kind == Vector)
10298 CDT = C.getPointerType(C.getRecordType(MD->getParent()));
10299 ++Offset;
10300 }
10301 if (CDT.isNull()) {
10302 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10303 if (ParamAttrs[I + Offset].Kind == Vector) {
10304 CDT = FD->getParamDecl(I)->getType();
10305 break;
10306 }
10307 }
10308 }
10309 }
10310 if (CDT.isNull())
10311 CDT = C.IntTy;
10312 CDT = CDT->getCanonicalTypeUnqualified();
10313 if (CDT->isRecordType() || CDT->isUnionType())
10314 CDT = C.IntTy;
10315 return C.getTypeSize(CDT);
10316}
10317
10318static void
10319emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
Benjamin Kramer81cb4b72016-11-24 16:01:20 +000010320 const llvm::APSInt &VLENVal,
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010321 ArrayRef<ParamAttrTy> ParamAttrs,
10322 OMPDeclareSimdDeclAttr::BranchStateTy State) {
10323 struct ISADataTy {
10324 char ISA;
10325 unsigned VecRegSize;
10326 };
10327 ISADataTy ISAData[] = {
10328 {
10329 'b', 128
10330 }, // SSE
10331 {
10332 'c', 256
10333 }, // AVX
10334 {
10335 'd', 256
10336 }, // AVX2
10337 {
10338 'e', 512
10339 }, // AVX512
10340 };
10341 llvm::SmallVector<char, 2> Masked;
10342 switch (State) {
10343 case OMPDeclareSimdDeclAttr::BS_Undefined:
10344 Masked.push_back('N');
10345 Masked.push_back('M');
10346 break;
10347 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10348 Masked.push_back('N');
10349 break;
10350 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10351 Masked.push_back('M');
10352 break;
10353 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010354 for (char Mask : Masked) {
10355 for (const ISADataTy &Data : ISAData) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010356 SmallString<256> Buffer;
10357 llvm::raw_svector_ostream Out(Buffer);
10358 Out << "_ZGV" << Data.ISA << Mask;
10359 if (!VLENVal) {
Simon Pilgrim823a99c2019-05-22 13:02:19 +000010360 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs);
10361 assert(NumElts && "Non-zero simdlen/cdtsize expected");
10362 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010363 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010364 Out << VLENVal;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010365 }
10366 for (const ParamAttrTy &ParamAttr : ParamAttrs) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010367 switch (ParamAttr.Kind){
10368 case LinearWithVarStride:
10369 Out << 's' << ParamAttr.StrideOrArg;
10370 break;
10371 case Linear:
10372 Out << 'l';
10373 if (!!ParamAttr.StrideOrArg)
10374 Out << ParamAttr.StrideOrArg;
10375 break;
10376 case Uniform:
10377 Out << 'u';
10378 break;
10379 case Vector:
10380 Out << 'v';
10381 break;
10382 }
10383 if (!!ParamAttr.Alignment)
10384 Out << 'a' << ParamAttr.Alignment;
10385 }
10386 Out << '_' << Fn->getName();
10387 Fn->addFnAttr(Out.str());
10388 }
10389 }
10390}
10391
Alexey Bataeva0a22642019-04-16 13:56:21 +000010392// This are the Functions that are needed to mangle the name of the
10393// vector functions generated by the compiler, according to the rules
10394// defined in the "Vector Function ABI specifications for AArch64",
10395// available at
10396// https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi.
10397
10398/// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI.
10399///
10400/// TODO: Need to implement the behavior for reference marked with a
10401/// var or no linear modifiers (1.b in the section). For this, we
10402/// need to extend ParamKindTy to support the linear modifiers.
10403static bool getAArch64MTV(QualType QT, ParamKindTy Kind) {
10404 QT = QT.getCanonicalType();
10405
10406 if (QT->isVoidType())
10407 return false;
10408
10409 if (Kind == ParamKindTy::Uniform)
10410 return false;
10411
10412 if (Kind == ParamKindTy::Linear)
10413 return false;
10414
10415 // TODO: Handle linear references with modifiers
10416
10417 if (Kind == ParamKindTy::LinearWithVarStride)
10418 return false;
10419
10420 return true;
10421}
10422
10423/// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
10424static bool getAArch64PBV(QualType QT, ASTContext &C) {
10425 QT = QT.getCanonicalType();
10426 unsigned Size = C.getTypeSize(QT);
10427
10428 // Only scalars and complex within 16 bytes wide set PVB to true.
10429 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
10430 return false;
10431
10432 if (QT->isFloatingType())
10433 return true;
10434
10435 if (QT->isIntegerType())
10436 return true;
10437
10438 if (QT->isPointerType())
10439 return true;
10440
10441 // TODO: Add support for complex types (section 3.1.2, item 2).
10442
10443 return false;
10444}
10445
10446/// Computes the lane size (LS) of a return type or of an input parameter,
10447/// as defined by `LS(P)` in 3.2.1 of the AAVFABI.
10448/// TODO: Add support for references, section 3.2.1, item 1.
10449static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) {
10450 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) {
10451 QualType PTy = QT.getCanonicalType()->getPointeeType();
10452 if (getAArch64PBV(PTy, C))
10453 return C.getTypeSize(PTy);
10454 }
10455 if (getAArch64PBV(QT, C))
10456 return C.getTypeSize(QT);
10457
10458 return C.getTypeSize(C.getUIntPtrType());
10459}
10460
10461// Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the
10462// signature of the scalar function, as defined in 3.2.2 of the
10463// AAVFABI.
10464static std::tuple<unsigned, unsigned, bool>
10465getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) {
10466 QualType RetType = FD->getReturnType().getCanonicalType();
10467
10468 ASTContext &C = FD->getASTContext();
10469
10470 bool OutputBecomesInput = false;
10471
10472 llvm::SmallVector<unsigned, 8> Sizes;
10473 if (!RetType->isVoidType()) {
10474 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C));
10475 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {}))
10476 OutputBecomesInput = true;
10477 }
10478 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10479 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType();
10480 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C));
10481 }
10482
10483 assert(!Sizes.empty() && "Unable to determine NDS and WDS.");
10484 // The LS of a function parameter / return value can only be a power
10485 // of 2, starting from 8 bits, up to 128.
10486 assert(std::all_of(Sizes.begin(), Sizes.end(),
10487 [](unsigned Size) {
10488 return Size == 8 || Size == 16 || Size == 32 ||
10489 Size == 64 || Size == 128;
10490 }) &&
10491 "Invalid size");
10492
10493 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)),
10494 *std::max_element(std::begin(Sizes), std::end(Sizes)),
10495 OutputBecomesInput);
10496}
10497
10498/// Mangle the parameter part of the vector function name according to
10499/// their OpenMP classification. The mangling function is defined in
10500/// section 3.5 of the AAVFABI.
10501static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) {
10502 SmallString<256> Buffer;
10503 llvm::raw_svector_ostream Out(Buffer);
10504 for (const auto &ParamAttr : ParamAttrs) {
10505 switch (ParamAttr.Kind) {
10506 case LinearWithVarStride:
10507 Out << "ls" << ParamAttr.StrideOrArg;
10508 break;
10509 case Linear:
10510 Out << 'l';
10511 // Don't print the step value if it is not present or if it is
10512 // equal to 1.
10513 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1)
10514 Out << ParamAttr.StrideOrArg;
10515 break;
10516 case Uniform:
10517 Out << 'u';
10518 break;
10519 case Vector:
10520 Out << 'v';
10521 break;
10522 }
10523
10524 if (!!ParamAttr.Alignment)
10525 Out << 'a' << ParamAttr.Alignment;
10526 }
10527
10528 return Out.str();
10529}
10530
10531// Function used to add the attribute. The parameter `VLEN` is
10532// templated to allow the use of "x" when targeting scalable functions
10533// for SVE.
10534template <typename T>
10535static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix,
10536 char ISA, StringRef ParSeq,
10537 StringRef MangledName, bool OutputBecomesInput,
10538 llvm::Function *Fn) {
10539 SmallString<256> Buffer;
10540 llvm::raw_svector_ostream Out(Buffer);
10541 Out << Prefix << ISA << LMask << VLEN;
10542 if (OutputBecomesInput)
10543 Out << "v";
10544 Out << ParSeq << "_" << MangledName;
10545 Fn->addFnAttr(Out.str());
10546}
10547
10548// Helper function to generate the Advanced SIMD names depending on
10549// the value of the NDS when simdlen is not present.
10550static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask,
10551 StringRef Prefix, char ISA,
10552 StringRef ParSeq, StringRef MangledName,
10553 bool OutputBecomesInput,
10554 llvm::Function *Fn) {
10555 switch (NDS) {
10556 case 8:
10557 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10558 OutputBecomesInput, Fn);
10559 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName,
10560 OutputBecomesInput, Fn);
10561 break;
10562 case 16:
10563 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10564 OutputBecomesInput, Fn);
10565 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10566 OutputBecomesInput, Fn);
10567 break;
10568 case 32:
10569 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10570 OutputBecomesInput, Fn);
10571 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10572 OutputBecomesInput, Fn);
10573 break;
10574 case 64:
10575 case 128:
10576 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10577 OutputBecomesInput, Fn);
10578 break;
10579 default:
10580 llvm_unreachable("Scalar type is too wide.");
10581 }
10582}
10583
10584/// Emit vector function attributes for AArch64, as defined in the AAVFABI.
10585static void emitAArch64DeclareSimdFunction(
10586 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN,
10587 ArrayRef<ParamAttrTy> ParamAttrs,
10588 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
10589 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) {
10590
10591 // Get basic data for building the vector signature.
10592 const auto Data = getNDSWDS(FD, ParamAttrs);
10593 const unsigned NDS = std::get<0>(Data);
10594 const unsigned WDS = std::get<1>(Data);
10595 const bool OutputBecomesInput = std::get<2>(Data);
10596
10597 // Check the values provided via `simdlen` by the user.
10598 // 1. A `simdlen(1)` doesn't produce vector signatures,
10599 if (UserVLEN == 1) {
10600 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10601 DiagnosticsEngine::Warning,
10602 "The clause simdlen(1) has no effect when targeting aarch64.");
10603 CGM.getDiags().Report(SLoc, DiagID);
10604 return;
10605 }
10606
10607 // 2. Section 3.3.1, item 1: user input must be a power of 2 for
10608 // Advanced SIMD output.
10609 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
10610 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10611 DiagnosticsEngine::Warning, "The value specified in simdlen must be a "
10612 "power of 2 when targeting Advanced SIMD.");
10613 CGM.getDiags().Report(SLoc, DiagID);
10614 return;
10615 }
10616
10617 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural
10618 // limits.
10619 if (ISA == 's' && UserVLEN != 0) {
10620 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
10621 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10622 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit "
10623 "lanes in the architectural constraints "
10624 "for SVE (min is 128-bit, max is "
10625 "2048-bit, by steps of 128-bit)");
10626 CGM.getDiags().Report(SLoc, DiagID) << WDS;
10627 return;
10628 }
10629 }
10630
10631 // Sort out parameter sequence.
10632 const std::string ParSeq = mangleVectorParameters(ParamAttrs);
10633 StringRef Prefix = "_ZGV";
10634 // Generate simdlen from user input (if any).
10635 if (UserVLEN) {
10636 if (ISA == 's') {
10637 // SVE generates only a masked function.
10638 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10639 OutputBecomesInput, Fn);
10640 } else {
10641 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10642 // Advanced SIMD generates one or two functions, depending on
10643 // the `[not]inbranch` clause.
10644 switch (State) {
10645 case OMPDeclareSimdDeclAttr::BS_Undefined:
10646 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10647 OutputBecomesInput, Fn);
10648 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10649 OutputBecomesInput, Fn);
10650 break;
10651 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10652 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10653 OutputBecomesInput, Fn);
10654 break;
10655 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10656 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10657 OutputBecomesInput, Fn);
10658 break;
10659 }
10660 }
10661 } else {
10662 // If no user simdlen is provided, follow the AAVFABI rules for
10663 // generating the vector length.
10664 if (ISA == 's') {
10665 // SVE, section 3.4.1, item 1.
10666 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName,
10667 OutputBecomesInput, Fn);
10668 } else {
10669 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10670 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or
10671 // two vector names depending on the use of the clause
10672 // `[not]inbranch`.
10673 switch (State) {
10674 case OMPDeclareSimdDeclAttr::BS_Undefined:
10675 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10676 OutputBecomesInput, Fn);
10677 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10678 OutputBecomesInput, Fn);
10679 break;
10680 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10681 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10682 OutputBecomesInput, Fn);
10683 break;
10684 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10685 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10686 OutputBecomesInput, Fn);
10687 break;
10688 }
10689 }
10690 }
10691}
10692
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010693void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
10694 llvm::Function *Fn) {
10695 ASTContext &C = CGM.getContext();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010696 FD = FD->getMostRecentDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010697 // Map params to their positions in function decl.
10698 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
10699 if (isa<CXXMethodDecl>(FD))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010700 ParamPositions.try_emplace(FD, 0);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010701 unsigned ParamPos = ParamPositions.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010702 for (const ParmVarDecl *P : FD->parameters()) {
10703 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010704 ++ParamPos;
10705 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010706 while (FD) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010707 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010708 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
10709 // Mark uniform parameters.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010710 for (const Expr *E : Attr->uniforms()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010711 E = E->IgnoreParenImpCasts();
10712 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010713 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010714 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010715 } else {
10716 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10717 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010718 Pos = ParamPositions[PVD];
10719 }
10720 ParamAttrs[Pos].Kind = Uniform;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010721 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010722 // Get alignment info.
10723 auto NI = Attr->alignments_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010724 for (const Expr *E : Attr->aligneds()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010725 E = E->IgnoreParenImpCasts();
10726 unsigned Pos;
10727 QualType ParmTy;
10728 if (isa<CXXThisExpr>(E)) {
10729 Pos = ParamPositions[FD];
10730 ParmTy = E->getType();
10731 } else {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010732 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10733 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010734 Pos = ParamPositions[PVD];
10735 ParmTy = PVD->getType();
10736 }
10737 ParamAttrs[Pos].Alignment =
10738 (*NI)
10739 ? (*NI)->EvaluateKnownConstInt(C)
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010740 : llvm::APSInt::getUnsigned(
10741 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy))
10742 .getQuantity());
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010743 ++NI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010744 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010745 // Mark linear parameters.
10746 auto SI = Attr->steps_begin();
10747 auto MI = Attr->modifiers_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010748 for (const Expr *E : Attr->linears()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010749 E = E->IgnoreParenImpCasts();
10750 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010751 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010752 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010753 } else {
10754 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10755 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010756 Pos = ParamPositions[PVD];
10757 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010758 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010759 ParamAttr.Kind = Linear;
10760 if (*SI) {
Fangrui Song407659a2018-11-30 23:41:18 +000010761 Expr::EvalResult Result;
10762 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010763 if (const auto *DRE =
10764 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
10765 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010766 ParamAttr.Kind = LinearWithVarStride;
10767 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(
10768 ParamPositions[StridePVD->getCanonicalDecl()]);
10769 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010770 }
Fangrui Song407659a2018-11-30 23:41:18 +000010771 } else {
10772 ParamAttr.StrideOrArg = Result.Val.getInt();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010773 }
10774 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010775 ++SI;
10776 ++MI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010777 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010778 llvm::APSInt VLENVal;
Alexey Bataeva0a22642019-04-16 13:56:21 +000010779 SourceLocation ExprLoc;
10780 const Expr *VLENExpr = Attr->getSimdlen();
10781 if (VLENExpr) {
10782 VLENVal = VLENExpr->EvaluateKnownConstInt(C);
10783 ExprLoc = VLENExpr->getExprLoc();
10784 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010785 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
10786 if (CGM.getTriple().getArch() == llvm::Triple::x86 ||
Alexey Bataeva0a22642019-04-16 13:56:21 +000010787 CGM.getTriple().getArch() == llvm::Triple::x86_64) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010788 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
Alexey Bataeva0a22642019-04-16 13:56:21 +000010789 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) {
10790 unsigned VLEN = VLENVal.getExtValue();
10791 StringRef MangledName = Fn->getName();
10792 if (CGM.getTarget().hasFeature("sve"))
10793 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10794 MangledName, 's', 128, Fn, ExprLoc);
10795 if (CGM.getTarget().hasFeature("neon"))
10796 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10797 MangledName, 'n', 128, Fn, ExprLoc);
10798 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010799 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010800 FD = FD->getPreviousDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010801 }
10802}
Alexey Bataev8b427062016-05-25 12:36:08 +000010803
10804namespace {
10805/// Cleanup action for doacross support.
10806class DoacrossCleanupTy final : public EHScopeStack::Cleanup {
10807public:
10808 static const int DoacrossFinArgs = 2;
10809
10810private:
James Y Knight9871db02019-02-05 16:42:33 +000010811 llvm::FunctionCallee RTLFn;
Alexey Bataev8b427062016-05-25 12:36:08 +000010812 llvm::Value *Args[DoacrossFinArgs];
10813
10814public:
James Y Knight9871db02019-02-05 16:42:33 +000010815 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
10816 ArrayRef<llvm::Value *> CallArgs)
Alexey Bataev8b427062016-05-25 12:36:08 +000010817 : RTLFn(RTLFn) {
10818 assert(CallArgs.size() == DoacrossFinArgs);
10819 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10820 }
10821 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10822 if (!CGF.HaveInsertPoint())
10823 return;
10824 CGF.EmitRuntimeCall(RTLFn, Args);
10825 }
10826};
10827} // namespace
10828
10829void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000010830 const OMPLoopDirective &D,
10831 ArrayRef<Expr *> NumIterations) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010832 if (!CGF.HaveInsertPoint())
10833 return;
10834
10835 ASTContext &C = CGM.getContext();
10836 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
10837 RecordDecl *RD;
10838 if (KmpDimTy.isNull()) {
10839 // Build struct kmp_dim { // loop bounds info casted to kmp_int64
10840 // kmp_int64 lo; // lower
10841 // kmp_int64 up; // upper
10842 // kmp_int64 st; // stride
10843 // };
10844 RD = C.buildImplicitRecord("kmp_dim");
10845 RD->startDefinition();
10846 addFieldToRecordDecl(C, RD, Int64Ty);
10847 addFieldToRecordDecl(C, RD, Int64Ty);
10848 addFieldToRecordDecl(C, RD, Int64Ty);
10849 RD->completeDefinition();
10850 KmpDimTy = C.getRecordType(RD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010851 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010852 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010853 }
Alexey Bataevf138fda2018-08-13 19:04:24 +000010854 llvm::APInt Size(/*numBits=*/32, NumIterations.size());
10855 QualType ArrayTy =
Richard Smith772e2662019-10-04 01:25:59 +000010856 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0);
Alexey Bataev8b427062016-05-25 12:36:08 +000010857
Alexey Bataevf138fda2018-08-13 19:04:24 +000010858 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
10859 CGF.EmitNullInitialization(DimsAddr, ArrayTy);
Alexey Bataev8b427062016-05-25 12:36:08 +000010860 enum { LowerFD = 0, UpperFD, StrideFD };
10861 // Fill dims with data.
Alexey Bataevf138fda2018-08-13 19:04:24 +000010862 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +000010863 LValue DimsLVal = CGF.MakeAddrLValue(
10864 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010865 // dims.upper = num_iterations;
10866 LValue UpperLVal = CGF.EmitLValueForField(
10867 DimsLVal, *std::next(RD->field_begin(), UpperFD));
10868 llvm::Value *NumIterVal =
10869 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]),
10870 D.getNumIterations()->getType(), Int64Ty,
10871 D.getNumIterations()->getExprLoc());
10872 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
10873 // dims.stride = 1;
10874 LValue StrideLVal = CGF.EmitLValueForField(
10875 DimsLVal, *std::next(RD->field_begin(), StrideFD));
10876 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
10877 StrideLVal);
10878 }
Alexey Bataev8b427062016-05-25 12:36:08 +000010879
10880 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
10881 // kmp_int32 num_dims, struct kmp_dim * dims);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010882 llvm::Value *Args[] = {
10883 emitUpdateLocation(CGF, D.getBeginLoc()),
10884 getThreadID(CGF, D.getBeginLoc()),
10885 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()),
10886 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knight751fe282019-02-09 22:22:28 +000010887 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(),
Alexey Bataevf138fda2018-08-13 19:04:24 +000010888 CGM.VoidPtrTy)};
Alexey Bataev8b427062016-05-25 12:36:08 +000010889
James Y Knight9871db02019-02-05 16:42:33 +000010890 llvm::FunctionCallee RTLFn =
10891 createRuntimeFunction(OMPRTL__kmpc_doacross_init);
Alexey Bataev8b427062016-05-25 12:36:08 +000010892 CGF.EmitRuntimeCall(RTLFn, Args);
10893 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
Stephen Kelly1c301dc2018-08-09 21:09:38 +000010894 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())};
James Y Knight9871db02019-02-05 16:42:33 +000010895 llvm::FunctionCallee FiniRTLFn =
10896 createRuntimeFunction(OMPRTL__kmpc_doacross_fini);
Alexey Bataev8b427062016-05-25 12:36:08 +000010897 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
10898 llvm::makeArrayRef(FiniArgs));
10899}
10900
10901void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
10902 const OMPDependClause *C) {
10903 QualType Int64Ty =
10904 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010905 llvm::APInt Size(/*numBits=*/32, C->getNumLoops());
10906 QualType ArrayTy = CGM.getContext().getConstantArrayType(
Richard Smith772e2662019-10-04 01:25:59 +000010907 Int64Ty, Size, nullptr, ArrayType::Normal, 0);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010908 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr");
10909 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) {
10910 const Expr *CounterVal = C->getLoopData(I);
10911 assert(CounterVal);
10912 llvm::Value *CntVal = CGF.EmitScalarConversion(
10913 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
10914 CounterVal->getExprLoc());
James Y Knight751fe282019-02-09 22:22:28 +000010915 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I),
10916 /*Volatile=*/false, Int64Ty);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010917 }
10918 llvm::Value *Args[] = {
10919 emitUpdateLocation(CGF, C->getBeginLoc()),
10920 getThreadID(CGF, C->getBeginLoc()),
James Y Knight751fe282019-02-09 22:22:28 +000010921 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()};
James Y Knight9871db02019-02-05 16:42:33 +000010922 llvm::FunctionCallee RTLFn;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010923 if (C->getDependencyKind() == OMPC_DEPEND_source) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010924 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010925 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010926 assert(C->getDependencyKind() == OMPC_DEPEND_sink);
10927 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait);
10928 }
10929 CGF.EmitRuntimeCall(RTLFn, Args);
10930}
10931
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010932void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000010933 llvm::FunctionCallee Callee,
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010934 ArrayRef<llvm::Value *> Args) const {
10935 assert(Loc.isValid() && "Outlined function call location must be valid.");
Alexey Bataev3c595a62017-08-14 15:01:03 +000010936 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
10937
James Y Knight9871db02019-02-05 16:42:33 +000010938 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010939 if (Fn->doesNotThrow()) {
Alexey Bataev3c595a62017-08-14 15:01:03 +000010940 CGF.EmitNounwindRuntimeCall(Fn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010941 return;
10942 }
10943 }
Alexey Bataev3c595a62017-08-14 15:01:03 +000010944 CGF.EmitRuntimeCall(Callee, Args);
10945}
10946
10947void CGOpenMPRuntime::emitOutlinedFunctionCall(
James Y Knight9871db02019-02-05 16:42:33 +000010948 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn,
Alexey Bataev3c595a62017-08-14 15:01:03 +000010949 ArrayRef<llvm::Value *> Args) const {
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010950 emitCall(CGF, Loc, OutlinedFn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010951}
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010952
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +000010953void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) {
10954 if (const auto *FD = dyn_cast<FunctionDecl>(D))
10955 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
10956 HasEmittedDeclareTargetRegion = true;
10957}
10958
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010959Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
10960 const VarDecl *NativeParam,
10961 const VarDecl *TargetParam) const {
10962 return CGF.GetAddrOfLocalVar(NativeParam);
10963}
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010964
Alexey Bataev4f680db2019-03-19 16:41:16 +000010965namespace {
10966/// Cleanup action for allocate support.
10967class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup {
10968public:
10969 static const int CleanupArgs = 3;
10970
10971private:
10972 llvm::FunctionCallee RTLFn;
10973 llvm::Value *Args[CleanupArgs];
10974
10975public:
10976 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
10977 ArrayRef<llvm::Value *> CallArgs)
10978 : RTLFn(RTLFn) {
10979 assert(CallArgs.size() == CleanupArgs &&
10980 "Size of arguments does not match.");
10981 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10982 }
10983 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10984 if (!CGF.HaveInsertPoint())
10985 return;
10986 CGF.EmitRuntimeCall(RTLFn, Args);
10987 }
10988};
10989} // namespace
10990
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000010991Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF,
10992 const VarDecl *VD) {
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010993 if (!VD)
10994 return Address::invalid();
Alexey Bataev4f680db2019-03-19 16:41:16 +000010995 const VarDecl *CVD = VD->getCanonicalDecl();
10996 if (!CVD->hasAttr<OMPAllocateDeclAttr>())
10997 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010998 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
10999 // Use the default allocation.
Alexey Bataev0fd3c682019-04-02 19:44:46 +000011000 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
11001 !AA->getAllocator())
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011002 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011003 llvm::Value *Size;
11004 CharUnits Align = CGM.getContext().getDeclAlign(CVD);
11005 if (CVD->getType()->isVariablyModifiedType()) {
11006 Size = CGF.getTypeSize(CVD->getType());
Alexey Bataev9c397812019-04-03 17:57:06 +000011007 // Align the size: ((size + align - 1) / align) * align
11008 Size = CGF.Builder.CreateNUWAdd(
11009 Size, CGM.getSize(Align - CharUnits::fromQuantity(1)));
11010 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align));
11011 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align));
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011012 } else {
11013 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType());
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011014 Size = CGM.getSize(Sz.alignTo(Align));
Alexey Bataev4f680db2019-03-19 16:41:16 +000011015 }
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011016 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc());
11017 assert(AA->getAllocator() &&
11018 "Expected allocator expression for non-default allocator.");
11019 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator());
Alexey Bataev6cf7b712019-04-08 19:06:42 +000011020 // According to the standard, the original allocator type is a enum (integer).
11021 // Convert to pointer type, if required.
11022 if (Allocator->getType()->isIntegerTy())
11023 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy);
11024 else if (Allocator->getType()->isPointerTy())
11025 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator,
11026 CGM.VoidPtrTy);
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011027 llvm::Value *Args[] = {ThreadID, Size, Allocator};
11028
11029 llvm::Value *Addr =
11030 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args,
11031 CVD->getName() + ".void.addr");
11032 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr,
11033 Allocator};
11034 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free);
11035
11036 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
11037 llvm::makeArrayRef(FiniArgs));
11038 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11039 Addr,
11040 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())),
11041 CVD->getName() + ".addr");
11042 return Address(Addr, Align);
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000011043}
11044
Alexey Bataevfde11e92019-11-07 11:03:10 -050011045namespace {
11046using OMPContextSelectorData =
Alexey Bataevf8ff3d72019-11-21 16:36:49 -050011047 OpenMPCtxSelectorData<ArrayRef<StringRef>, llvm::APSInt>;
Alexey Bataevfde11e92019-11-07 11:03:10 -050011048using CompleteOMPContextSelectorData = SmallVector<OMPContextSelectorData, 4>;
11049} // anonymous namespace
11050
Alexey Bataev2df5f122019-10-01 20:18:32 +000011051/// Checks current context and returns true if it matches the context selector.
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011052template <OpenMPContextSelectorSetKind CtxSet, OpenMPContextSelectorKind Ctx,
11053 typename... Arguments>
11054static bool checkContext(const OMPContextSelectorData &Data,
11055 Arguments... Params) {
Alexey Bataevfde11e92019-11-07 11:03:10 -050011056 assert(Data.CtxSet != OMP_CTX_SET_unknown && Data.Ctx != OMP_CTX_unknown &&
Alexey Bataev2df5f122019-10-01 20:18:32 +000011057 "Unknown context selector or context selector set.");
11058 return false;
11059}
11060
11061/// Checks for implementation={vendor(<vendor>)} context selector.
11062/// \returns true iff <vendor>="llvm", false otherwise.
11063template <>
Alexey Bataevfde11e92019-11-07 11:03:10 -050011064bool checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(
11065 const OMPContextSelectorData &Data) {
11066 return llvm::all_of(Data.Names,
Alexey Bataev303657a2019-10-08 19:44:16 +000011067 [](StringRef S) { return !S.compare_lower("llvm"); });
Alexey Bataev2df5f122019-10-01 20:18:32 +000011068}
11069
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011070/// Checks for device={kind(<kind>)} context selector.
11071/// \returns true if <kind>="host" and compilation is for host.
11072/// true if <kind>="nohost" and compilation is for device.
11073/// true if <kind>="cpu" and compilation is for Arm, X86 or PPC CPU.
11074/// true if <kind>="gpu" and compilation is for NVPTX or AMDGCN.
11075/// false otherwise.
11076template <>
11077bool checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>(
11078 const OMPContextSelectorData &Data, CodeGenModule &CGM) {
11079 for (StringRef Name : Data.Names) {
11080 if (!Name.compare_lower("host")) {
11081 if (CGM.getLangOpts().OpenMPIsDevice)
11082 return false;
11083 continue;
11084 }
11085 if (!Name.compare_lower("nohost")) {
11086 if (!CGM.getLangOpts().OpenMPIsDevice)
11087 return false;
11088 continue;
11089 }
11090 switch (CGM.getTriple().getArch()) {
11091 case llvm::Triple::arm:
11092 case llvm::Triple::armeb:
11093 case llvm::Triple::aarch64:
11094 case llvm::Triple::aarch64_be:
11095 case llvm::Triple::aarch64_32:
11096 case llvm::Triple::ppc:
11097 case llvm::Triple::ppc64:
11098 case llvm::Triple::ppc64le:
11099 case llvm::Triple::x86:
11100 case llvm::Triple::x86_64:
11101 if (Name.compare_lower("cpu"))
11102 return false;
11103 break;
11104 case llvm::Triple::amdgcn:
11105 case llvm::Triple::nvptx:
11106 case llvm::Triple::nvptx64:
11107 if (Name.compare_lower("gpu"))
11108 return false;
11109 break;
11110 case llvm::Triple::UnknownArch:
11111 case llvm::Triple::arc:
11112 case llvm::Triple::avr:
11113 case llvm::Triple::bpfel:
11114 case llvm::Triple::bpfeb:
11115 case llvm::Triple::hexagon:
11116 case llvm::Triple::mips:
11117 case llvm::Triple::mipsel:
11118 case llvm::Triple::mips64:
11119 case llvm::Triple::mips64el:
11120 case llvm::Triple::msp430:
11121 case llvm::Triple::r600:
11122 case llvm::Triple::riscv32:
11123 case llvm::Triple::riscv64:
11124 case llvm::Triple::sparc:
11125 case llvm::Triple::sparcv9:
11126 case llvm::Triple::sparcel:
11127 case llvm::Triple::systemz:
11128 case llvm::Triple::tce:
11129 case llvm::Triple::tcele:
11130 case llvm::Triple::thumb:
11131 case llvm::Triple::thumbeb:
11132 case llvm::Triple::xcore:
11133 case llvm::Triple::le32:
11134 case llvm::Triple::le64:
11135 case llvm::Triple::amdil:
11136 case llvm::Triple::amdil64:
11137 case llvm::Triple::hsail:
11138 case llvm::Triple::hsail64:
11139 case llvm::Triple::spir:
11140 case llvm::Triple::spir64:
11141 case llvm::Triple::kalimba:
11142 case llvm::Triple::shave:
11143 case llvm::Triple::lanai:
11144 case llvm::Triple::wasm32:
11145 case llvm::Triple::wasm64:
11146 case llvm::Triple::renderscript32:
11147 case llvm::Triple::renderscript64:
11148 return false;
11149 }
11150 }
11151 return true;
11152}
11153
11154bool matchesContext(CodeGenModule &CGM,
11155 const CompleteOMPContextSelectorData &ContextData) {
Alexey Bataevfde11e92019-11-07 11:03:10 -050011156 for (const OMPContextSelectorData &Data : ContextData) {
Alexey Bataev5459a902019-11-22 11:42:08 -050011157 switch (Data.Ctx) {
11158 case OMP_CTX_vendor:
11159 assert(Data.CtxSet == OMP_CTX_SET_implementation &&
11160 "Expected implementation context selector set.");
11161 if (!checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(Data))
11162 return false;
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011163 break;
Alexey Bataev5459a902019-11-22 11:42:08 -050011164 case OMP_CTX_kind:
11165 assert(Data.CtxSet == OMP_CTX_SET_device &&
11166 "Expected device context selector set.");
11167 if (!checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>(Data,
11168 CGM))
11169 return false;
Alexey Bataevfde11e92019-11-07 11:03:10 -050011170 break;
Alexey Bataev5459a902019-11-22 11:42:08 -050011171 case OMP_CTX_unknown:
11172 llvm_unreachable("Unknown context selector kind.");
Alexey Bataevfde11e92019-11-07 11:03:10 -050011173 }
11174 }
11175 return true;
11176}
11177
11178static CompleteOMPContextSelectorData
11179translateAttrToContextSelectorData(ASTContext &C,
11180 const OMPDeclareVariantAttr *A) {
11181 CompleteOMPContextSelectorData Data;
11182 for (unsigned I = 0, E = A->scores_size(); I < E; ++I) {
11183 Data.emplace_back();
11184 auto CtxSet = static_cast<OpenMPContextSelectorSetKind>(
11185 *std::next(A->ctxSelectorSets_begin(), I));
11186 auto Ctx = static_cast<OpenMPContextSelectorKind>(
11187 *std::next(A->ctxSelectors_begin(), I));
11188 Data.back().CtxSet = CtxSet;
11189 Data.back().Ctx = Ctx;
11190 const Expr *Score = *std::next(A->scores_begin(), I);
11191 Data.back().Score = Score->EvaluateKnownConstInt(C);
Alexey Bataev5459a902019-11-22 11:42:08 -050011192 switch (Ctx) {
11193 case OMP_CTX_vendor:
11194 assert(CtxSet == OMP_CTX_SET_implementation &&
11195 "Expected implementation context selector set.");
11196 Data.back().Names =
11197 llvm::makeArrayRef(A->implVendors_begin(), A->implVendors_end());
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011198 break;
Alexey Bataev5459a902019-11-22 11:42:08 -050011199 case OMP_CTX_kind:
11200 assert(CtxSet == OMP_CTX_SET_device &&
11201 "Expected device context selector set.");
11202 Data.back().Names =
11203 llvm::makeArrayRef(A->deviceKinds_begin(), A->deviceKinds_end());
Alexey Bataevfde11e92019-11-07 11:03:10 -050011204 break;
Alexey Bataev5459a902019-11-22 11:42:08 -050011205 case OMP_CTX_unknown:
11206 llvm_unreachable("Unknown context selector kind.");
Alexey Bataevfde11e92019-11-07 11:03:10 -050011207 }
11208 }
11209 return Data;
11210}
11211
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011212static bool isStrictSubset(const CompleteOMPContextSelectorData &LHS,
11213 const CompleteOMPContextSelectorData &RHS) {
11214 llvm::SmallDenseMap<std::pair<int, int>, llvm::StringSet<>, 4> RHSData;
11215 for (const OMPContextSelectorData &D : RHS) {
11216 auto &Pair = RHSData.FindAndConstruct(std::make_pair(D.CtxSet, D.Ctx));
11217 Pair.getSecond().insert(D.Names.begin(), D.Names.end());
11218 }
11219 bool AllSetsAreEqual = true;
11220 for (const OMPContextSelectorData &D : LHS) {
11221 auto It = RHSData.find(std::make_pair(D.CtxSet, D.Ctx));
11222 if (It == RHSData.end())
11223 return false;
11224 if (D.Names.size() > It->getSecond().size())
11225 return false;
11226 if (llvm::set_union(It->getSecond(), D.Names))
11227 return false;
11228 AllSetsAreEqual =
11229 AllSetsAreEqual && (D.Names.size() == It->getSecond().size());
11230 }
11231
11232 return LHS.size() != RHS.size() || !AllSetsAreEqual;
11233}
11234
Alexey Bataevfde11e92019-11-07 11:03:10 -050011235static bool greaterCtxScore(const CompleteOMPContextSelectorData &LHS,
11236 const CompleteOMPContextSelectorData &RHS) {
11237 // Score is calculated as sum of all scores + 1.
11238 llvm::APSInt LHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false);
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011239 bool RHSIsSubsetOfLHS = isStrictSubset(RHS, LHS);
11240 if (RHSIsSubsetOfLHS) {
11241 LHSScore = llvm::APSInt::get(0);
11242 } else {
11243 for (const OMPContextSelectorData &Data : LHS) {
11244 if (Data.Score.getBitWidth() > LHSScore.getBitWidth()) {
11245 LHSScore = LHSScore.extend(Data.Score.getBitWidth()) + Data.Score;
11246 } else if (Data.Score.getBitWidth() < LHSScore.getBitWidth()) {
11247 LHSScore += Data.Score.extend(LHSScore.getBitWidth());
11248 } else {
11249 LHSScore += Data.Score;
11250 }
Alexey Bataevfde11e92019-11-07 11:03:10 -050011251 }
11252 }
11253 llvm::APSInt RHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false);
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011254 if (!RHSIsSubsetOfLHS && isStrictSubset(LHS, RHS)) {
11255 RHSScore = llvm::APSInt::get(0);
11256 } else {
11257 for (const OMPContextSelectorData &Data : RHS) {
11258 if (Data.Score.getBitWidth() > RHSScore.getBitWidth()) {
11259 RHSScore = RHSScore.extend(Data.Score.getBitWidth()) + Data.Score;
11260 } else if (Data.Score.getBitWidth() < RHSScore.getBitWidth()) {
11261 RHSScore += Data.Score.extend(RHSScore.getBitWidth());
11262 } else {
11263 RHSScore += Data.Score;
11264 }
Alexey Bataevfde11e92019-11-07 11:03:10 -050011265 }
11266 }
11267 return llvm::APSInt::compareValues(LHSScore, RHSScore) >= 0;
Alexey Bataev0364c762019-10-03 20:49:48 +000011268}
11269
Alexey Bataev2df5f122019-10-01 20:18:32 +000011270/// Finds the variant function that matches current context with its context
11271/// selector.
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011272static const FunctionDecl *getDeclareVariantFunction(CodeGenModule &CGM,
Alexey Bataev0364c762019-10-03 20:49:48 +000011273 const FunctionDecl *FD) {
Alexey Bataev2df5f122019-10-01 20:18:32 +000011274 if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>())
11275 return FD;
11276 // Iterate through all DeclareVariant attributes and check context selectors.
Alexey Bataev0364c762019-10-03 20:49:48 +000011277 const OMPDeclareVariantAttr *TopMostAttr = nullptr;
Alexey Bataevfde11e92019-11-07 11:03:10 -050011278 CompleteOMPContextSelectorData TopMostData;
Alexey Bataev0364c762019-10-03 20:49:48 +000011279 for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) {
Alexey Bataevfde11e92019-11-07 11:03:10 -050011280 CompleteOMPContextSelectorData Data =
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011281 translateAttrToContextSelectorData(CGM.getContext(), A);
11282 if (!matchesContext(CGM, Data))
Alexey Bataevfde11e92019-11-07 11:03:10 -050011283 continue;
Alexey Bataev0364c762019-10-03 20:49:48 +000011284 // If the attribute matches the context, find the attribute with the highest
11285 // score.
Alexey Bataevfde11e92019-11-07 11:03:10 -050011286 if (!TopMostAttr || !greaterCtxScore(TopMostData, Data)) {
11287 TopMostAttr = A;
11288 TopMostData.swap(Data);
11289 }
Alexey Bataev2df5f122019-10-01 20:18:32 +000011290 }
Alexey Bataev0364c762019-10-03 20:49:48 +000011291 if (!TopMostAttr)
Alexey Bataev2df5f122019-10-01 20:18:32 +000011292 return FD;
Alexey Bataev2df5f122019-10-01 20:18:32 +000011293 return cast<FunctionDecl>(
Alexey Bataev0364c762019-10-03 20:49:48 +000011294 cast<DeclRefExpr>(TopMostAttr->getVariantFuncRef()->IgnoreParenImpCasts())
Alexey Bataev2df5f122019-10-01 20:18:32 +000011295 ->getDecl());
11296}
11297
11298bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) {
11299 const auto *D = cast<FunctionDecl>(GD.getDecl());
11300 // If the original function is defined already, use its definition.
11301 StringRef MangledName = CGM.getMangledName(GD);
11302 llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName);
11303 if (Orig && !Orig->isDeclaration())
11304 return false;
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011305 const FunctionDecl *NewFD = getDeclareVariantFunction(CGM, D);
Alexey Bataev2df5f122019-10-01 20:18:32 +000011306 // Emit original function if it does not have declare variant attribute or the
11307 // context does not match.
11308 if (NewFD == D)
11309 return false;
11310 GlobalDecl NewGD = GD.getWithDecl(NewFD);
Alexey Bataevc2cd2d42019-10-10 17:28:10 +000011311 if (tryEmitDeclareVariant(NewGD, GD, Orig, IsForDefinition)) {
Alexey Bataev2df5f122019-10-01 20:18:32 +000011312 DeferredVariantFunction.erase(D);
11313 return true;
11314 }
11315 DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD)));
11316 return true;
11317}
11318
James Y Knight9871db02019-02-05 16:42:33 +000011319llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011320 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11321 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11322 llvm_unreachable("Not supported in SIMD-only mode");
11323}
11324
James Y Knight9871db02019-02-05 16:42:33 +000011325llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011326 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11327 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11328 llvm_unreachable("Not supported in SIMD-only mode");
11329}
11330
James Y Knight9871db02019-02-05 16:42:33 +000011331llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011332 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11333 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
11334 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
11335 bool Tied, unsigned &NumberOfParts) {
11336 llvm_unreachable("Not supported in SIMD-only mode");
11337}
11338
11339void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF,
11340 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000011341 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011342 ArrayRef<llvm::Value *> CapturedVars,
11343 const Expr *IfCond) {
11344 llvm_unreachable("Not supported in SIMD-only mode");
11345}
11346
11347void CGOpenMPSIMDRuntime::emitCriticalRegion(
11348 CodeGenFunction &CGF, StringRef CriticalName,
11349 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
11350 const Expr *Hint) {
11351 llvm_unreachable("Not supported in SIMD-only mode");
11352}
11353
11354void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF,
11355 const RegionCodeGenTy &MasterOpGen,
11356 SourceLocation Loc) {
11357 llvm_unreachable("Not supported in SIMD-only mode");
11358}
11359
11360void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
11361 SourceLocation Loc) {
11362 llvm_unreachable("Not supported in SIMD-only mode");
11363}
11364
11365void CGOpenMPSIMDRuntime::emitTaskgroupRegion(
11366 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen,
11367 SourceLocation Loc) {
11368 llvm_unreachable("Not supported in SIMD-only mode");
11369}
11370
11371void CGOpenMPSIMDRuntime::emitSingleRegion(
11372 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen,
11373 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars,
11374 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs,
11375 ArrayRef<const Expr *> AssignmentOps) {
11376 llvm_unreachable("Not supported in SIMD-only mode");
11377}
11378
11379void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF,
11380 const RegionCodeGenTy &OrderedOpGen,
11381 SourceLocation Loc,
11382 bool IsThreads) {
11383 llvm_unreachable("Not supported in SIMD-only mode");
11384}
11385
11386void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF,
11387 SourceLocation Loc,
11388 OpenMPDirectiveKind Kind,
11389 bool EmitChecks,
11390 bool ForceSimpleCall) {
11391 llvm_unreachable("Not supported in SIMD-only mode");
11392}
11393
11394void CGOpenMPSIMDRuntime::emitForDispatchInit(
11395 CodeGenFunction &CGF, SourceLocation Loc,
11396 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
11397 bool Ordered, const DispatchRTInput &DispatchValues) {
11398 llvm_unreachable("Not supported in SIMD-only mode");
11399}
11400
11401void CGOpenMPSIMDRuntime::emitForStaticInit(
11402 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind,
11403 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) {
11404 llvm_unreachable("Not supported in SIMD-only mode");
11405}
11406
11407void CGOpenMPSIMDRuntime::emitDistributeStaticInit(
11408 CodeGenFunction &CGF, SourceLocation Loc,
11409 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) {
11410 llvm_unreachable("Not supported in SIMD-only mode");
11411}
11412
11413void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
11414 SourceLocation Loc,
11415 unsigned IVSize,
11416 bool IVSigned) {
11417 llvm_unreachable("Not supported in SIMD-only mode");
11418}
11419
11420void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF,
11421 SourceLocation Loc,
11422 OpenMPDirectiveKind DKind) {
11423 llvm_unreachable("Not supported in SIMD-only mode");
11424}
11425
11426llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF,
11427 SourceLocation Loc,
11428 unsigned IVSize, bool IVSigned,
11429 Address IL, Address LB,
11430 Address UB, Address ST) {
11431 llvm_unreachable("Not supported in SIMD-only mode");
11432}
11433
11434void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
11435 llvm::Value *NumThreads,
11436 SourceLocation Loc) {
11437 llvm_unreachable("Not supported in SIMD-only mode");
11438}
11439
11440void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF,
11441 OpenMPProcBindClauseKind ProcBind,
11442 SourceLocation Loc) {
11443 llvm_unreachable("Not supported in SIMD-only mode");
11444}
11445
11446Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
11447 const VarDecl *VD,
11448 Address VDAddr,
11449 SourceLocation Loc) {
11450 llvm_unreachable("Not supported in SIMD-only mode");
11451}
11452
11453llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition(
11454 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit,
11455 CodeGenFunction *CGF) {
11456 llvm_unreachable("Not supported in SIMD-only mode");
11457}
11458
11459Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate(
11460 CodeGenFunction &CGF, QualType VarType, StringRef Name) {
11461 llvm_unreachable("Not supported in SIMD-only mode");
11462}
11463
11464void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF,
11465 ArrayRef<const Expr *> Vars,
11466 SourceLocation Loc) {
11467 llvm_unreachable("Not supported in SIMD-only mode");
11468}
11469
11470void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
11471 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000011472 llvm::Function *TaskFunction,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011473 QualType SharedsTy, Address Shareds,
11474 const Expr *IfCond,
11475 const OMPTaskDataTy &Data) {
11476 llvm_unreachable("Not supported in SIMD-only mode");
11477}
11478
11479void CGOpenMPSIMDRuntime::emitTaskLoopCall(
11480 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000011481 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011482 const Expr *IfCond, const OMPTaskDataTy &Data) {
11483 llvm_unreachable("Not supported in SIMD-only mode");
11484}
11485
11486void CGOpenMPSIMDRuntime::emitReduction(
11487 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates,
11488 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
11489 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) {
11490 assert(Options.SimpleReduction && "Only simple reduction is expected.");
11491 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
11492 ReductionOps, Options);
11493}
11494
11495llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit(
11496 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
11497 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
11498 llvm_unreachable("Not supported in SIMD-only mode");
11499}
11500
11501void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
11502 SourceLocation Loc,
11503 ReductionCodeGen &RCG,
11504 unsigned N) {
11505 llvm_unreachable("Not supported in SIMD-only mode");
11506}
11507
11508Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
11509 SourceLocation Loc,
11510 llvm::Value *ReductionsPtr,
11511 LValue SharedLVal) {
11512 llvm_unreachable("Not supported in SIMD-only mode");
11513}
11514
11515void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
11516 SourceLocation Loc) {
11517 llvm_unreachable("Not supported in SIMD-only mode");
11518}
11519
11520void CGOpenMPSIMDRuntime::emitCancellationPointCall(
11521 CodeGenFunction &CGF, SourceLocation Loc,
11522 OpenMPDirectiveKind CancelRegion) {
11523 llvm_unreachable("Not supported in SIMD-only mode");
11524}
11525
11526void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF,
11527 SourceLocation Loc, const Expr *IfCond,
11528 OpenMPDirectiveKind CancelRegion) {
11529 llvm_unreachable("Not supported in SIMD-only mode");
11530}
11531
11532void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction(
11533 const OMPExecutableDirective &D, StringRef ParentName,
11534 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
11535 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
11536 llvm_unreachable("Not supported in SIMD-only mode");
11537}
11538
Alexey Bataevec7946e2019-09-23 14:06:51 +000011539void CGOpenMPSIMDRuntime::emitTargetCall(
11540 CodeGenFunction &CGF, const OMPExecutableDirective &D,
11541 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
11542 const Expr *Device,
11543 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
11544 const OMPLoopDirective &D)>
11545 SizeEmitter) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011546 llvm_unreachable("Not supported in SIMD-only mode");
11547}
11548
11549bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) {
11550 llvm_unreachable("Not supported in SIMD-only mode");
11551}
11552
11553bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
11554 llvm_unreachable("Not supported in SIMD-only mode");
11555}
11556
11557bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) {
11558 return false;
11559}
11560
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011561void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF,
11562 const OMPExecutableDirective &D,
11563 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000011564 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011565 ArrayRef<llvm::Value *> CapturedVars) {
11566 llvm_unreachable("Not supported in SIMD-only mode");
11567}
11568
11569void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
11570 const Expr *NumTeams,
11571 const Expr *ThreadLimit,
11572 SourceLocation Loc) {
11573 llvm_unreachable("Not supported in SIMD-only mode");
11574}
11575
11576void CGOpenMPSIMDRuntime::emitTargetDataCalls(
11577 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
11578 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
11579 llvm_unreachable("Not supported in SIMD-only mode");
11580}
11581
11582void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
11583 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
11584 const Expr *Device) {
11585 llvm_unreachable("Not supported in SIMD-only mode");
11586}
11587
11588void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000011589 const OMPLoopDirective &D,
11590 ArrayRef<Expr *> NumIterations) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011591 llvm_unreachable("Not supported in SIMD-only mode");
11592}
11593
11594void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
11595 const OMPDependClause *C) {
11596 llvm_unreachable("Not supported in SIMD-only mode");
11597}
11598
11599const VarDecl *
11600CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD,
11601 const VarDecl *NativeParam) const {
11602 llvm_unreachable("Not supported in SIMD-only mode");
11603}
11604
11605Address
11606CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF,
11607 const VarDecl *NativeParam,
11608 const VarDecl *TargetParam) const {
11609 llvm_unreachable("Not supported in SIMD-only mode");
11610}