blob: 2a53e9993533c10c08013666b06a19fdd313187f [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
Reid Kleckner98031782019-12-09 16:11:56 -080013#include "CGOpenMPRuntime.h"
Samuel Antaoee8fb302016-01-06 13:42:12 +000014#include "CGCXXABI.h"
15#include "CGCleanup.h"
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000016#include "CGRecordLayout.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000017#include "CodeGenFunction.h"
Reid Kleckner98031782019-12-09 16:11:56 -080018#include "clang/AST/Attr.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000019#include "clang/AST/Decl.h"
Alexey Bataev0860db92019-12-19 10:01:10 -050020#include "clang/AST/OpenMPClause.h"
Chandler Carruth0d9593d2015-01-14 11:29:14 +000021#include "clang/AST/StmtOpenMP.h"
Richard Smithbf5bcf22018-06-26 23:20:26 +000022#include "clang/Basic/BitmaskEnum.h"
Reid Kleckner98031782019-12-09 16:11:56 -080023#include "clang/CodeGen/ConstantInitBuilder.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000024#include "llvm/ADT/ArrayRef.h"
Alexey Bataev4e8231b2019-11-05 15:13:30 -050025#include "llvm/ADT/SetOperations.h"
Teresa Johnsonffc4e242016-11-11 05:35:12 +000026#include "llvm/Bitcode/BitcodeReader.h"
Johannes Doerfertb3c06db2019-11-04 23:00:36 -060027#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000028#include "llvm/IR/DerivedTypes.h"
29#include "llvm/IR/GlobalValue.h"
30#include "llvm/IR/Value.h"
Samuel Antaoee8fb302016-01-06 13:42:12 +000031#include "llvm/Support/Format.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000032#include "llvm/Support/raw_ostream.h"
Alexey Bataev23b69422014-06-18 07:08:49 +000033#include <cassert>
Alexey Bataev9959db52014-05-06 10:08:46 +000034
35using namespace clang;
36using namespace CodeGen;
Johannes Doerferteb3e81f2019-11-04 22:00:49 -060037using namespace llvm::omp;
Alexey Bataev9959db52014-05-06 10:08:46 +000038
Benjamin Kramerc52193f2014-10-10 13:57:57 +000039namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000040/// Base class for handling code generation inside OpenMP regions.
Alexey Bataev18095712014-10-10 12:19:54 +000041class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
42public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000043 /// Kinds of OpenMP regions used in codegen.
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000044 enum CGOpenMPRegionKind {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000045 /// Region with outlined function for standalone 'parallel'
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000046 /// directive.
47 ParallelOutlinedRegion,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000048 /// Region with outlined function for standalone 'task' directive.
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000049 TaskOutlinedRegion,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000050 /// Region for constructs that do not require function outlining,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000051 /// like 'for', 'sections', 'atomic' etc. directives.
52 InlinedRegion,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000053 /// Region with outlined function for standalone 'target' directive.
Samuel Antaobed3c462015-10-02 16:14:20 +000054 TargetRegion,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000055 };
Alexey Bataev18095712014-10-10 12:19:54 +000056
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000057 CGOpenMPRegionInfo(const CapturedStmt &CS,
58 const CGOpenMPRegionKind RegionKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +000059 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
60 bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000061 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
Alexey Bataev25e5b442015-09-15 12:52:43 +000062 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000063
64 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +000065 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
66 bool HasCancel)
Alexey Bataev81c7ea02015-07-03 09:56:58 +000067 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
Alexey Bataev25e5b442015-09-15 12:52:43 +000068 Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000069
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000070 /// Get a variable or parameter for storing global thread id
Alexey Bataev18095712014-10-10 12:19:54 +000071 /// inside OpenMP construct.
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000072 virtual const VarDecl *getThreadIDVariable() const = 0;
Alexey Bataev18095712014-10-10 12:19:54 +000073
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000074 /// Emit the captured statement body.
Hans Wennborg7eb54642015-09-10 17:07:54 +000075 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000076
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000077 /// Get an LValue for the current ThreadID variable.
Alexey Bataev62b63b12015-03-10 07:28:44 +000078 /// \return LValue for thread id variable. This LValue always has type int32*.
79 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
Alexey Bataev18095712014-10-10 12:19:54 +000080
Alexey Bataev48591dd2016-04-20 04:01:36 +000081 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {}
82
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000083 CGOpenMPRegionKind getRegionKind() const { return RegionKind; }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000084
Alexey Bataev81c7ea02015-07-03 09:56:58 +000085 OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
86
Alexey Bataev25e5b442015-09-15 12:52:43 +000087 bool hasCancel() const { return HasCancel; }
88
Alexey Bataev18095712014-10-10 12:19:54 +000089 static bool classof(const CGCapturedStmtInfo *Info) {
90 return Info->getKind() == CR_OpenMP;
91 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000092
Alexey Bataev48591dd2016-04-20 04:01:36 +000093 ~CGOpenMPRegionInfo() override = default;
94
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000095protected:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000096 CGOpenMPRegionKind RegionKind;
Hans Wennborg45c74392016-01-12 20:54:36 +000097 RegionCodeGenTy CodeGen;
Alexey Bataev81c7ea02015-07-03 09:56:58 +000098 OpenMPDirectiveKind Kind;
Alexey Bataev25e5b442015-09-15 12:52:43 +000099 bool HasCancel;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000100};
Alexey Bataev18095712014-10-10 12:19:54 +0000101
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000102/// API for captured statement code generation in OpenMP constructs.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000103class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000104public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000105 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000106 const RegionCodeGenTy &CodeGen,
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +0000107 OpenMPDirectiveKind Kind, bool HasCancel,
108 StringRef HelperName)
Alexey Bataev25e5b442015-09-15 12:52:43 +0000109 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind,
110 HasCancel),
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +0000111 ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000112 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
113 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000114
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000115 /// Get a variable or parameter for storing global thread id
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000116 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000117 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000118
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000119 /// Get the name of the capture helper.
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +0000120 StringRef getHelperName() const override { return HelperName; }
Alexey Bataev18095712014-10-10 12:19:54 +0000121
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000122 static bool classof(const CGCapturedStmtInfo *Info) {
123 return CGOpenMPRegionInfo::classof(Info) &&
124 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
125 ParallelOutlinedRegion;
126 }
127
Alexey Bataev18095712014-10-10 12:19:54 +0000128private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000129 /// A variable or parameter storing global thread id for OpenMP
Alexey Bataev18095712014-10-10 12:19:54 +0000130 /// constructs.
131 const VarDecl *ThreadIDVar;
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +0000132 StringRef HelperName;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000133};
134
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000135/// API for captured statement code generation in OpenMP constructs.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000136class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000137public:
Alexey Bataev48591dd2016-04-20 04:01:36 +0000138 class UntiedTaskActionTy final : public PrePostActionTy {
139 bool Untied;
140 const VarDecl *PartIDVar;
141 const RegionCodeGenTy UntiedCodeGen;
142 llvm::SwitchInst *UntiedSwitch = nullptr;
143
144 public:
145 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar,
146 const RegionCodeGenTy &UntiedCodeGen)
147 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
148 void Enter(CodeGenFunction &CGF) override {
149 if (Untied) {
150 // Emit task switching point.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000151 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue(
Alexey Bataev48591dd2016-04-20 04:01:36 +0000152 CGF.GetAddrOfLocalVar(PartIDVar),
153 PartIDVar->getType()->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000154 llvm::Value *Res =
155 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation());
156 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done.");
Alexey Bataev48591dd2016-04-20 04:01:36 +0000157 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB);
158 CGF.EmitBlock(DoneBB);
159 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
160 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
161 UntiedSwitch->addCase(CGF.Builder.getInt32(0),
162 CGF.Builder.GetInsertBlock());
163 emitUntiedSwitch(CGF);
164 }
165 }
166 void emitUntiedSwitch(CodeGenFunction &CGF) const {
167 if (Untied) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000168 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue(
Alexey Bataev48591dd2016-04-20 04:01:36 +0000169 CGF.GetAddrOfLocalVar(PartIDVar),
170 PartIDVar->getType()->castAs<PointerType>());
171 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
172 PartIdLVal);
173 UntiedCodeGen(CGF);
174 CodeGenFunction::JumpDest CurPoint =
175 CGF.getJumpDestInCurrentScope(".untied.next.");
176 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
177 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
178 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
179 CGF.Builder.GetInsertBlock());
180 CGF.EmitBranchThroughCleanup(CurPoint);
181 CGF.EmitBlock(CurPoint.getBlock());
182 }
183 }
184 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); }
185 };
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000186 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
Alexey Bataev62b63b12015-03-10 07:28:44 +0000187 const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000188 const RegionCodeGenTy &CodeGen,
Alexey Bataev48591dd2016-04-20 04:01:36 +0000189 OpenMPDirectiveKind Kind, bool HasCancel,
190 const UntiedTaskActionTy &Action)
Alexey Bataev25e5b442015-09-15 12:52:43 +0000191 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel),
Alexey Bataev48591dd2016-04-20 04:01:36 +0000192 ThreadIDVar(ThreadIDVar), Action(Action) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000193 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
194 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000195
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000196 /// Get a variable or parameter for storing global thread id
Alexey Bataev62b63b12015-03-10 07:28:44 +0000197 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000198 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000199
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000200 /// Get an LValue for the current ThreadID variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000201 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000202
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000203 /// Get the name of the capture helper.
Alexey Bataev62b63b12015-03-10 07:28:44 +0000204 StringRef getHelperName() const override { return ".omp_outlined."; }
205
Alexey Bataev48591dd2016-04-20 04:01:36 +0000206 void emitUntiedSwitch(CodeGenFunction &CGF) override {
207 Action.emitUntiedSwitch(CGF);
208 }
209
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000210 static bool classof(const CGCapturedStmtInfo *Info) {
211 return CGOpenMPRegionInfo::classof(Info) &&
212 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
213 TaskOutlinedRegion;
214 }
215
Alexey Bataev62b63b12015-03-10 07:28:44 +0000216private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000217 /// A variable or parameter storing global thread id for OpenMP
Alexey Bataev62b63b12015-03-10 07:28:44 +0000218 /// constructs.
219 const VarDecl *ThreadIDVar;
Alexey Bataev48591dd2016-04-20 04:01:36 +0000220 /// Action for emitting code for untied tasks.
221 const UntiedTaskActionTy &Action;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000222};
223
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000224/// API for inlined captured statement code generation in OpenMP
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000225/// constructs.
226class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
227public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000228 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000229 const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000230 OpenMPDirectiveKind Kind, bool HasCancel)
231 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel),
232 OldCSI(OldCSI),
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000233 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000234
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000235 // Retrieve the value of the context parameter.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000236 llvm::Value *getContextValue() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000237 if (OuterRegionInfo)
238 return OuterRegionInfo->getContextValue();
239 llvm_unreachable("No context value for inlined OpenMP region");
240 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000241
Hans Wennborg7eb54642015-09-10 17:07:54 +0000242 void setContextValue(llvm::Value *V) override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000243 if (OuterRegionInfo) {
244 OuterRegionInfo->setContextValue(V);
245 return;
246 }
247 llvm_unreachable("No context value for inlined OpenMP region");
248 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000249
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000250 /// Lookup the captured field decl for a variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000251 const FieldDecl *lookup(const VarDecl *VD) const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000252 if (OuterRegionInfo)
253 return OuterRegionInfo->lookup(VD);
Alexey Bataev69c62a92015-04-15 04:52:20 +0000254 // If there is no outer outlined region,no need to lookup in a list of
255 // captured variables, we can use the original one.
256 return nullptr;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000257 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000258
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000259 FieldDecl *getThisFieldDecl() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000260 if (OuterRegionInfo)
261 return OuterRegionInfo->getThisFieldDecl();
262 return nullptr;
263 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000264
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000265 /// Get a variable or parameter for storing global thread id
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000266 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000267 const VarDecl *getThreadIDVariable() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000268 if (OuterRegionInfo)
269 return OuterRegionInfo->getThreadIDVariable();
270 return nullptr;
271 }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000272
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000273 /// Get an LValue for the current ThreadID variable.
Alexey Bataev311a9282017-10-12 13:51:32 +0000274 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override {
275 if (OuterRegionInfo)
276 return OuterRegionInfo->getThreadIDVariableLValue(CGF);
277 llvm_unreachable("No LValue for inlined OpenMP construct");
278 }
279
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000280 /// Get the name of the capture helper.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000281 StringRef getHelperName() const override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000282 if (auto *OuterRegionInfo = getOldCSI())
283 return OuterRegionInfo->getHelperName();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000284 llvm_unreachable("No helper name for inlined OpenMP construct");
285 }
286
Alexey Bataev48591dd2016-04-20 04:01:36 +0000287 void emitUntiedSwitch(CodeGenFunction &CGF) override {
288 if (OuterRegionInfo)
289 OuterRegionInfo->emitUntiedSwitch(CGF);
290 }
291
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000292 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; }
293
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000294 static bool classof(const CGCapturedStmtInfo *Info) {
295 return CGOpenMPRegionInfo::classof(Info) &&
296 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
297 }
298
Alexey Bataev48591dd2016-04-20 04:01:36 +0000299 ~CGOpenMPInlinedRegionInfo() override = default;
300
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000301private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000302 /// CodeGen info about outer OpenMP region.
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000303 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
304 CGOpenMPRegionInfo *OuterRegionInfo;
Alexey Bataev18095712014-10-10 12:19:54 +0000305};
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000306
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000307/// API for captured statement code generation in OpenMP target
Samuel Antaobed3c462015-10-02 16:14:20 +0000308/// constructs. For this captures, implicit parameters are used instead of the
Samuel Antaoee8fb302016-01-06 13:42:12 +0000309/// captured fields. The name of the target region has to be unique in a given
310/// application so it is provided by the client, because only the client has
311/// the information to generate that.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000312class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo {
Samuel Antaobed3c462015-10-02 16:14:20 +0000313public:
314 CGOpenMPTargetRegionInfo(const CapturedStmt &CS,
Samuel Antaoee8fb302016-01-06 13:42:12 +0000315 const RegionCodeGenTy &CodeGen, StringRef HelperName)
Samuel Antaobed3c462015-10-02 16:14:20 +0000316 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
Samuel Antaoee8fb302016-01-06 13:42:12 +0000317 /*HasCancel=*/false),
318 HelperName(HelperName) {}
Samuel Antaobed3c462015-10-02 16:14:20 +0000319
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000320 /// This is unused for target regions because each starts executing
Samuel Antaobed3c462015-10-02 16:14:20 +0000321 /// with a single thread.
322 const VarDecl *getThreadIDVariable() const override { return nullptr; }
323
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000324 /// Get the name of the capture helper.
Samuel Antaoee8fb302016-01-06 13:42:12 +0000325 StringRef getHelperName() const override { return HelperName; }
Samuel Antaobed3c462015-10-02 16:14:20 +0000326
327 static bool classof(const CGCapturedStmtInfo *Info) {
328 return CGOpenMPRegionInfo::classof(Info) &&
329 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion;
330 }
Samuel Antaoee8fb302016-01-06 13:42:12 +0000331
332private:
333 StringRef HelperName;
Samuel Antaobed3c462015-10-02 16:14:20 +0000334};
335
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000336static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000337 llvm_unreachable("No codegen for expressions");
338}
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000339/// API for generation of expressions captured in a innermost OpenMP
Samuel Antaob68e2db2016-03-03 16:20:23 +0000340/// region.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000341class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000342public:
343 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS)
344 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
345 OMPD_unknown,
346 /*HasCancel=*/false),
347 PrivScope(CGF) {
348 // Make sure the globals captured in the provided statement are local by
349 // using the privatization logic. We assume the same variable is not
350 // captured more than once.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000351 for (const auto &C : CS.captures()) {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000352 if (!C.capturesVariable() && !C.capturesVariableByCopy())
353 continue;
354
355 const VarDecl *VD = C.getCapturedVar();
356 if (VD->isLocalVarDeclOrParm())
357 continue;
358
Bruno Ricci5fc4db72018-12-21 14:10:18 +0000359 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
Samuel Antaob68e2db2016-03-03 16:20:23 +0000360 /*RefersToEnclosingVariableOrCapture=*/false,
361 VD->getType().getNonReferenceType(), VK_LValue,
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000362 C.getLocation());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000363 PrivScope.addPrivate(
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800364 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(CGF); });
Samuel Antaob68e2db2016-03-03 16:20:23 +0000365 }
366 (void)PrivScope.Privatize();
367 }
368
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000369 /// Lookup the captured field decl for a variable.
Samuel Antaob68e2db2016-03-03 16:20:23 +0000370 const FieldDecl *lookup(const VarDecl *VD) const override {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000371 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
Samuel Antaob68e2db2016-03-03 16:20:23 +0000372 return FD;
373 return nullptr;
374 }
375
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000376 /// Emit the captured statement body.
Samuel Antaob68e2db2016-03-03 16:20:23 +0000377 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override {
378 llvm_unreachable("No body for expressions");
379 }
380
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000381 /// Get a variable or parameter for storing global thread id
Samuel Antaob68e2db2016-03-03 16:20:23 +0000382 /// inside OpenMP construct.
383 const VarDecl *getThreadIDVariable() const override {
384 llvm_unreachable("No thread id for expressions");
385 }
386
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000387 /// Get the name of the capture helper.
Samuel Antaob68e2db2016-03-03 16:20:23 +0000388 StringRef getHelperName() const override {
389 llvm_unreachable("No helper name for expressions");
390 }
391
392 static bool classof(const CGCapturedStmtInfo *Info) { return false; }
393
394private:
395 /// Private scope to capture global variables.
396 CodeGenFunction::OMPPrivateScope PrivScope;
397};
398
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000399/// RAII for emitting code of OpenMP constructs.
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000400class InlinedOpenMPRegionRAII {
401 CodeGenFunction &CGF;
Alexey Bataev4ba78a42016-04-27 07:56:03 +0000402 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
403 FieldDecl *LambdaThisCaptureField = nullptr;
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000404 const CodeGen::CGBlockInfo *BlockInfo = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000405
406public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000407 /// Constructs region for combined constructs.
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000408 /// \param CodeGen Code generation sequence for combined directives. Includes
409 /// a list of functions used for code generation of implicitly inlined
410 /// regions.
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000411 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000412 OpenMPDirectiveKind Kind, bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000413 : CGF(CGF) {
414 // Start emission for the construct.
Alexey Bataev25e5b442015-09-15 12:52:43 +0000415 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(
416 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
Alexey Bataev4ba78a42016-04-27 07:56:03 +0000417 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
418 LambdaThisCaptureField = CGF.LambdaThisCaptureField;
419 CGF.LambdaThisCaptureField = nullptr;
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000420 BlockInfo = CGF.BlockInfo;
421 CGF.BlockInfo = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000422 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000423
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000424 ~InlinedOpenMPRegionRAII() {
425 // Restore original CapturedStmtInfo only if we're done with code emission.
426 auto *OldCSI =
427 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
428 delete CGF.CapturedStmtInfo;
429 CGF.CapturedStmtInfo = OldCSI;
Alexey Bataev4ba78a42016-04-27 07:56:03 +0000430 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
431 CGF.LambdaThisCaptureField = LambdaThisCaptureField;
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000432 CGF.BlockInfo = BlockInfo;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000433 }
434};
435
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000436/// Values for bit flags used in the ident_t to describe the fields.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000437/// All enumeric elements are named and described in accordance with the code
James Y Knight5d71fc52019-01-29 16:37:27 +0000438/// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h
Alexey Bataev0f87dbe2017-08-14 17:56:13 +0000439enum OpenMPLocationFlags : unsigned {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000440 /// Use trampoline for internal microtask.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000441 OMP_IDENT_IMD = 0x01,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000442 /// Use c-style ident structure.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000443 OMP_IDENT_KMPC = 0x02,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000444 /// Atomic reduction option for kmpc_reduce.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000445 OMP_ATOMIC_REDUCE = 0x10,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000446 /// Explicit 'barrier' directive.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000447 OMP_IDENT_BARRIER_EXPL = 0x20,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000448 /// Implicit barrier in code.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000449 OMP_IDENT_BARRIER_IMPL = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000450 /// Implicit barrier in 'for' directive.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000451 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000452 /// Implicit barrier in 'sections' directive.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000453 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000454 /// Implicit barrier in 'single' directive.
Alexey Bataev0f87dbe2017-08-14 17:56:13 +0000455 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
456 /// Call of __kmp_for_static_init for static loop.
457 OMP_IDENT_WORK_LOOP = 0x200,
458 /// Call of __kmp_for_static_init for sections.
459 OMP_IDENT_WORK_SECTIONS = 0x400,
460 /// Call of __kmp_for_static_init for distribute.
461 OMP_IDENT_WORK_DISTRIBUTE = 0x800,
462 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE)
Alexey Bataev50b3c952016-02-19 10:38:26 +0000463};
464
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +0000465namespace {
466LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
467/// Values for bit flags for marking which requires clauses have been used.
468enum OpenMPOffloadingRequiresDirFlags : int64_t {
469 /// flag undefined.
470 OMP_REQ_UNDEFINED = 0x000,
471 /// no requires clause present.
472 OMP_REQ_NONE = 0x001,
473 /// reverse_offload clause.
474 OMP_REQ_REVERSE_OFFLOAD = 0x002,
475 /// unified_address clause.
476 OMP_REQ_UNIFIED_ADDRESS = 0x004,
477 /// unified_shared_memory clause.
478 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
479 /// dynamic_allocators clause.
480 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010,
481 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS)
482};
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +0000483
484enum OpenMPOffloadingReservedDeviceIDs {
485 /// Device ID if the device was not defined, runtime should get it
486 /// from environment variables in the spec.
487 OMP_DEVICEID_UNDEF = -1,
488};
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +0000489} // anonymous namespace
490
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000491/// Describes ident structure that describes a source location.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000492/// All descriptions are taken from
James Y Knight5d71fc52019-01-29 16:37:27 +0000493/// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h
Alexey Bataev50b3c952016-02-19 10:38:26 +0000494/// Original structure:
495/// typedef struct ident {
496/// kmp_int32 reserved_1; /**< might be used in Fortran;
497/// see above */
498/// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags;
499/// KMP_IDENT_KMPC identifies this union
500/// member */
501/// kmp_int32 reserved_2; /**< not really used in Fortran any more;
502/// see above */
503///#if USE_ITT_BUILD
504/// /* but currently used for storing
505/// region-specific ITT */
506/// /* contextual information. */
507///#endif /* USE_ITT_BUILD */
508/// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for
509/// C++ */
510/// char const *psource; /**< String describing the source location.
511/// The string is composed of semi-colon separated
512// fields which describe the source file,
513/// the function and a pair of line numbers that
514/// delimit the construct.
515/// */
516/// } ident_t;
517enum IdentFieldIndex {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000518 /// might be used in Fortran
Alexey Bataev50b3c952016-02-19 10:38:26 +0000519 IdentField_Reserved_1,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000520 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000521 IdentField_Flags,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000522 /// Not really used in Fortran any more
Alexey Bataev50b3c952016-02-19 10:38:26 +0000523 IdentField_Reserved_2,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000524 /// Source[4] in Fortran, do not use for C++
Alexey Bataev50b3c952016-02-19 10:38:26 +0000525 IdentField_Reserved_3,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000526 /// String describing the source location. The string is composed of
Alexey Bataev50b3c952016-02-19 10:38:26 +0000527 /// semi-colon separated fields which describe the source file, the function
528 /// and a pair of line numbers that delimit the construct.
529 IdentField_PSource
530};
531
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000532/// Schedule types for 'omp for' loops (these enumerators are taken from
Alexey Bataev50b3c952016-02-19 10:38:26 +0000533/// the enum sched_type in kmp.h).
534enum OpenMPSchedType {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000535 /// Lower bound for default (unordered) versions.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000536 OMP_sch_lower = 32,
537 OMP_sch_static_chunked = 33,
538 OMP_sch_static = 34,
539 OMP_sch_dynamic_chunked = 35,
540 OMP_sch_guided_chunked = 36,
541 OMP_sch_runtime = 37,
542 OMP_sch_auto = 38,
Alexey Bataev6cff6242016-05-30 13:05:14 +0000543 /// static with chunk adjustment (e.g., simd)
Samuel Antao4c8035b2016-12-12 18:00:20 +0000544 OMP_sch_static_balanced_chunked = 45,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000545 /// Lower bound for 'ordered' versions.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000546 OMP_ord_lower = 64,
547 OMP_ord_static_chunked = 65,
548 OMP_ord_static = 66,
549 OMP_ord_dynamic_chunked = 67,
550 OMP_ord_guided_chunked = 68,
551 OMP_ord_runtime = 69,
552 OMP_ord_auto = 70,
553 OMP_sch_default = OMP_sch_static,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000554 /// dist_schedule types
Carlo Bertollifc35ad22016-03-07 16:04:49 +0000555 OMP_dist_sch_static_chunked = 91,
556 OMP_dist_sch_static = 92,
Alexey Bataev9ebd7422016-05-10 09:57:36 +0000557 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers.
558 /// Set if the monotonic schedule modifier was present.
559 OMP_sch_modifier_monotonic = (1 << 29),
560 /// Set if the nonmonotonic schedule modifier was present.
561 OMP_sch_modifier_nonmonotonic = (1 << 30),
Alexey Bataev50b3c952016-02-19 10:38:26 +0000562};
563
564enum OpenMPRTLFunction {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000565 /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000566 /// kmpc_micro microtask, ...);
567 OMPRTL__kmpc_fork_call,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000568 /// Call to void *__kmpc_threadprivate_cached(ident_t *loc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000569 /// kmp_int32 global_tid, void *data, size_t size, void ***cache);
570 OMPRTL__kmpc_threadprivate_cached,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000571 /// Call to void __kmpc_threadprivate_register( ident_t *,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000572 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
573 OMPRTL__kmpc_threadprivate_register,
574 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc);
575 OMPRTL__kmpc_global_thread_num,
576 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
577 // kmp_critical_name *crit);
578 OMPRTL__kmpc_critical,
579 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32
580 // global_tid, kmp_critical_name *crit, uintptr_t hint);
581 OMPRTL__kmpc_critical_with_hint,
582 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
583 // kmp_critical_name *crit);
584 OMPRTL__kmpc_end_critical,
585 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
586 // global_tid);
587 OMPRTL__kmpc_cancel_barrier,
588 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
589 OMPRTL__kmpc_barrier,
590 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
591 OMPRTL__kmpc_for_static_fini,
592 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
593 // global_tid);
594 OMPRTL__kmpc_serialized_parallel,
595 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
596 // global_tid);
597 OMPRTL__kmpc_end_serialized_parallel,
598 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
599 // kmp_int32 num_threads);
600 OMPRTL__kmpc_push_num_threads,
601 // Call to void __kmpc_flush(ident_t *loc);
602 OMPRTL__kmpc_flush,
603 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid);
604 OMPRTL__kmpc_master,
605 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid);
606 OMPRTL__kmpc_end_master,
607 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
608 // int end_part);
609 OMPRTL__kmpc_omp_taskyield,
610 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid);
611 OMPRTL__kmpc_single,
612 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid);
613 OMPRTL__kmpc_end_single,
614 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
615 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
616 // kmp_routine_entry_t *task_entry);
617 OMPRTL__kmpc_omp_task_alloc,
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +0000618 // Call to kmp_task_t * __kmpc_omp_target_task_alloc(ident_t *,
619 // kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t,
620 // size_t sizeof_shareds, kmp_routine_entry_t *task_entry,
621 // kmp_int64 device_id);
622 OMPRTL__kmpc_omp_target_task_alloc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000623 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *
624 // new_task);
625 OMPRTL__kmpc_omp_task,
626 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
627 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
628 // kmp_int32 didit);
629 OMPRTL__kmpc_copyprivate,
630 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
631 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
632 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
633 OMPRTL__kmpc_reduce,
634 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
635 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
636 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
637 // *lck);
638 OMPRTL__kmpc_reduce_nowait,
639 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
640 // kmp_critical_name *lck);
641 OMPRTL__kmpc_end_reduce,
642 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
643 // kmp_critical_name *lck);
644 OMPRTL__kmpc_end_reduce_nowait,
645 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
646 // kmp_task_t * new_task);
647 OMPRTL__kmpc_omp_task_begin_if0,
648 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
649 // kmp_task_t * new_task);
650 OMPRTL__kmpc_omp_task_complete_if0,
651 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
652 OMPRTL__kmpc_ordered,
653 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
654 OMPRTL__kmpc_end_ordered,
655 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
656 // global_tid);
657 OMPRTL__kmpc_omp_taskwait,
658 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
659 OMPRTL__kmpc_taskgroup,
660 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
661 OMPRTL__kmpc_end_taskgroup,
662 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
663 // int proc_bind);
664 OMPRTL__kmpc_push_proc_bind,
665 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32
666 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t
667 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
668 OMPRTL__kmpc_omp_task_with_deps,
669 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32
670 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
671 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
672 OMPRTL__kmpc_omp_wait_deps,
673 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
674 // global_tid, kmp_int32 cncl_kind);
675 OMPRTL__kmpc_cancellationpoint,
676 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
677 // kmp_int32 cncl_kind);
678 OMPRTL__kmpc_cancel,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000679 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid,
680 // kmp_int32 num_teams, kmp_int32 thread_limit);
681 OMPRTL__kmpc_push_num_teams,
Alexey Bataev7292c292016-04-25 12:22:29 +0000682 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
683 // microtask, ...);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000684 OMPRTL__kmpc_fork_teams,
Alexey Bataev7292c292016-04-25 12:22:29 +0000685 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
686 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
687 // sched, kmp_uint64 grainsize, void *task_dup);
688 OMPRTL__kmpc_taskloop,
Alexey Bataev8b427062016-05-25 12:36:08 +0000689 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32
690 // num_dims, struct kmp_dim *dims);
691 OMPRTL__kmpc_doacross_init,
692 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid);
693 OMPRTL__kmpc_doacross_fini,
694 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64
695 // *vec);
696 OMPRTL__kmpc_doacross_post,
697 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64
698 // *vec);
699 OMPRTL__kmpc_doacross_wait,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000700 // Call to void *__kmpc_task_reduction_init(int gtid, int num_data, void
701 // *data);
702 OMPRTL__kmpc_task_reduction_init,
703 // Call to void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
704 // *d);
705 OMPRTL__kmpc_task_reduction_get_th_data,
Alexey Bataev6cf7b712019-04-08 19:06:42 +0000706 // Call to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al);
Alexey Bataev4f680db2019-03-19 16:41:16 +0000707 OMPRTL__kmpc_alloc,
Alexey Bataev6cf7b712019-04-08 19:06:42 +0000708 // Call to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al);
Alexey Bataev4f680db2019-03-19 16:41:16 +0000709 OMPRTL__kmpc_free,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000710
711 //
712 // Offloading related calls
713 //
Alexey Bataev7bb33532019-01-07 21:30:43 +0000714 // Call to void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64
715 // size);
716 OMPRTL__kmpc_push_target_tripcount,
George Rokos63bc9d62017-11-21 18:25:12 +0000717 // Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +0000718 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev50b3c952016-02-19 10:38:26 +0000719 // *arg_types);
720 OMPRTL__tgt_target,
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000721 // Call to int32_t __tgt_target_nowait(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
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000723 // *arg_types);
724 OMPRTL__tgt_target_nowait,
George Rokos63bc9d62017-11-21 18:25:12 +0000725 // Call to int32_t __tgt_target_teams(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +0000726 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
George Rokos63bc9d62017-11-21 18:25:12 +0000727 // *arg_types, int32_t num_teams, int32_t thread_limit);
Samuel Antaob68e2db2016-03-03 16:20:23 +0000728 OMPRTL__tgt_target_teams,
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000729 // Call to int32_t __tgt_target_teams_nowait(int64_t device_id, void
Alexey Bataeva90fc662019-06-25 16:00:43 +0000730 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000731 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
732 OMPRTL__tgt_target_teams_nowait,
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +0000733 // Call to void __tgt_register_requires(int64_t flags);
734 OMPRTL__tgt_register_requires,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000735 // Call to void __tgt_register_lib(__tgt_bin_desc *desc);
736 OMPRTL__tgt_register_lib,
737 // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc);
738 OMPRTL__tgt_unregister_lib,
George Rokos63bc9d62017-11-21 18:25:12 +0000739 // Call to void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +0000740 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
Samuel Antaodf158d52016-04-27 22:58:19 +0000741 OMPRTL__tgt_target_data_begin,
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000742 // Call to void __tgt_target_data_begin_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +0000743 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000744 // *arg_types);
745 OMPRTL__tgt_target_data_begin_nowait,
George Rokos63bc9d62017-11-21 18:25:12 +0000746 // Call to void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
747 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types);
Samuel Antaodf158d52016-04-27 22:58:19 +0000748 OMPRTL__tgt_target_data_end,
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000749 // Call to void __tgt_target_data_end_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +0000750 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000751 // *arg_types);
752 OMPRTL__tgt_target_data_end_nowait,
George Rokos63bc9d62017-11-21 18:25:12 +0000753 // Call to void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +0000754 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
Samuel Antao8d2d7302016-05-26 18:30:22 +0000755 OMPRTL__tgt_target_data_update,
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000756 // Call to void __tgt_target_data_update_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +0000757 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000758 // *arg_types);
759 OMPRTL__tgt_target_data_update_nowait,
Michael Krused47b9432019-08-05 18:43:21 +0000760 // Call to int64_t __tgt_mapper_num_components(void *rt_mapper_handle);
761 OMPRTL__tgt_mapper_num_components,
762 // Call to void __tgt_push_mapper_component(void *rt_mapper_handle, void
763 // *base, void *begin, int64_t size, int64_t type);
764 OMPRTL__tgt_push_mapper_component,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000765};
766
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000767/// A basic class for pre|post-action for advanced codegen sequence for OpenMP
768/// region.
769class CleanupTy final : public EHScopeStack::Cleanup {
770 PrePostActionTy *Action;
771
772public:
773 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
774 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
775 if (!CGF.HaveInsertPoint())
776 return;
777 Action->Exit(CGF);
778 }
779};
780
Hans Wennborg7eb54642015-09-10 17:07:54 +0000781} // anonymous namespace
Alexey Bataev18095712014-10-10 12:19:54 +0000782
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000783void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const {
784 CodeGenFunction::RunCleanupsScope Scope(CGF);
785 if (PrePostAction) {
786 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction);
787 Callback(CodeGen, CGF, *PrePostAction);
788 } else {
789 PrePostActionTy Action;
790 Callback(CodeGen, CGF, Action);
791 }
792}
793
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000794/// Check if the combiner is a call to UDR combiner and if it is so return the
795/// UDR decl used for reduction.
796static const OMPDeclareReductionDecl *
797getReductionInit(const Expr *ReductionOp) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000798 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
799 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
800 if (const auto *DRE =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000801 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000802 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000803 return DRD;
804 return nullptr;
805}
806
807static void emitInitWithReductionInitializer(CodeGenFunction &CGF,
808 const OMPDeclareReductionDecl *DRD,
809 const Expr *InitOp,
810 Address Private, Address Original,
811 QualType Ty) {
812 if (DRD->getInitializer()) {
813 std::pair<llvm::Function *, llvm::Function *> Reduction =
814 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000815 const auto *CE = cast<CallExpr>(InitOp);
816 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000817 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
818 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000819 const auto *LHSDRE =
820 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr());
821 const auto *RHSDRE =
822 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000823 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
824 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000825 [=]() { return Private; });
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000826 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000827 [=]() { return Original; });
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000828 (void)PrivateScope.Privatize();
829 RValue Func = RValue::get(Reduction.second);
830 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
831 CGF.EmitIgnoredExpr(InitOp);
832 } else {
833 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty);
Alexey Bataev18fa2322018-05-02 14:20:50 +0000834 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"});
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000835 auto *GV = new llvm::GlobalVariable(
836 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,
Alexey Bataev18fa2322018-05-02 14:20:50 +0000837 llvm::GlobalValue::PrivateLinkage, Init, Name);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000838 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty);
839 RValue InitRVal;
840 switch (CGF.getEvaluationKind(Ty)) {
841 case TEK_Scalar:
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000842 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000843 break;
844 case TEK_Complex:
845 InitRVal =
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000846 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation()));
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000847 break;
848 case TEK_Aggregate:
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800849 InitRVal = RValue::getAggregate(LV.getAddress(CGF));
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000850 break;
851 }
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000852 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000853 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal);
854 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(),
855 /*IsInitializer=*/false);
856 }
857}
858
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000859/// Emit initialization of arrays of complex types.
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000860/// \param DestAddr Address of the array.
861/// \param Type Type of array.
862/// \param Init Initial expression of array.
863/// \param SrcAddr Address of the original array.
864static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
Alexey Bataeva7b19152017-10-12 20:03:39 +0000865 QualType Type, bool EmitDeclareReductionInit,
866 const Expr *Init,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000867 const OMPDeclareReductionDecl *DRD,
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000868 Address SrcAddr = Address::invalid()) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000869 // Perform element-by-element initialization.
870 QualType ElementTy;
871
872 // Drill down to the base element type on both arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000873 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
874 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000875 DestAddr =
876 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType());
877 if (DRD)
878 SrcAddr =
879 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType());
880
881 llvm::Value *SrcBegin = nullptr;
882 if (DRD)
883 SrcBegin = SrcAddr.getPointer();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000884 llvm::Value *DestBegin = DestAddr.getPointer();
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000885 // Cast from pointer to array type to pointer to single element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000886 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000887 // The basic structure here is a while-do loop.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000888 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body");
889 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done");
890 llvm::Value *IsEmpty =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000891 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty");
892 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
893
894 // Enter the loop body, making that address the current address.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000895 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000896 CGF.EmitBlock(BodyBB);
897
898 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
899
900 llvm::PHINode *SrcElementPHI = nullptr;
901 Address SrcElementCurrent = Address::invalid();
902 if (DRD) {
903 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2,
904 "omp.arraycpy.srcElementPast");
905 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
906 SrcElementCurrent =
907 Address(SrcElementPHI,
908 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
909 }
910 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI(
911 DestBegin->getType(), 2, "omp.arraycpy.destElementPast");
912 DestElementPHI->addIncoming(DestBegin, EntryBB);
913 Address DestElementCurrent =
914 Address(DestElementPHI,
915 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize));
916
917 // Emit copy.
918 {
919 CodeGenFunction::RunCleanupsScope InitScope(CGF);
Alexey Bataeva7b19152017-10-12 20:03:39 +0000920 if (EmitDeclareReductionInit) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000921 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent,
922 SrcElementCurrent, ElementTy);
923 } else
924 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(),
925 /*IsInitializer=*/false);
926 }
927
928 if (DRD) {
929 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000930 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000931 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
932 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock());
933 }
934
935 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000936 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000937 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
938 // Check whether we've reached the end.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000939 llvm::Value *Done =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000940 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
941 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
942 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock());
943
944 // Done.
945 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
946}
947
948LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) {
Alexey Bataevf47c4b42017-09-26 13:47:31 +0000949 return CGF.EmitOMPSharedLValue(E);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000950}
951
952LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF,
953 const Expr *E) {
954 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E))
955 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false);
956 return LValue();
957}
958
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000959void ReductionCodeGen::emitAggregateInitialization(
960 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal,
961 const OMPDeclareReductionDecl *DRD) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000962 // Emit VarDecl with copy init for arrays.
963 // Get the address of the original variable captured in current
964 // captured region.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000965 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000966 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
Alexey Bataeva7b19152017-10-12 20:03:39 +0000967 bool EmitDeclareReductionInit =
968 DRD && (DRD->getInitializer() || !PrivateVD->hasInit());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000969 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(),
Alexey Bataeva7b19152017-10-12 20:03:39 +0000970 EmitDeclareReductionInit,
971 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
972 : PrivateVD->getInit(),
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800973 DRD, SharedLVal.getAddress(CGF));
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000974}
975
976ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds,
977 ArrayRef<const Expr *> Privates,
978 ArrayRef<const Expr *> ReductionOps) {
979 ClausesData.reserve(Shareds.size());
980 SharedAddresses.reserve(Shareds.size());
981 Sizes.reserve(Shareds.size());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000982 BaseDecls.reserve(Shareds.size());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000983 auto IPriv = Privates.begin();
984 auto IRed = ReductionOps.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000985 for (const Expr *Ref : Shareds) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000986 ClausesData.emplace_back(Ref, *IPriv, *IRed);
987 std::advance(IPriv, 1);
988 std::advance(IRed, 1);
989 }
990}
991
992void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) {
993 assert(SharedAddresses.size() == N &&
994 "Number of generated lvalues must be exactly N.");
Jonas Hahnfeld4525c822017-10-23 19:01:35 +0000995 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
996 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
997 SharedAddresses.emplace_back(First, Second);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000998}
999
1000void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001001 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001002 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1003 QualType PrivateType = PrivateVD->getType();
1004 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref);
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001005 if (!PrivateType->isVariablyModifiedType()) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001006 Sizes.emplace_back(
1007 CGF.getTypeSize(
1008 SharedAddresses[N].first.getType().getNonReferenceType()),
1009 nullptr);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001010 return;
1011 }
1012 llvm::Value *Size;
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001013 llvm::Value *SizeInChars;
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001014 auto *ElemType = cast<llvm::PointerType>(
1015 SharedAddresses[N].first.getPointer(CGF)->getType())
1016 ->getElementType();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001017 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001018 if (AsArraySection) {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001019 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(CGF),
1020 SharedAddresses[N].first.getPointer(CGF));
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001021 Size = CGF.Builder.CreateNUWAdd(
1022 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001023 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001024 } else {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001025 SizeInChars = CGF.getTypeSize(
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001026 SharedAddresses[N].first.getType().getNonReferenceType());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001027 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001028 }
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001029 Sizes.emplace_back(SizeInChars, Size);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001030 CodeGenFunction::OpaqueValueMapping OpaqueMap(
1031 CGF,
1032 cast<OpaqueValueExpr>(
1033 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),
1034 RValue::get(Size));
1035 CGF.EmitVariablyModifiedType(PrivateType);
1036}
1037
1038void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N,
1039 llvm::Value *Size) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001040 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001041 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1042 QualType PrivateType = PrivateVD->getType();
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001043 if (!PrivateType->isVariablyModifiedType()) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001044 assert(!Size && !Sizes[N].second &&
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001045 "Size should be nullptr for non-variably modified reduction "
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001046 "items.");
1047 return;
1048 }
1049 CodeGenFunction::OpaqueValueMapping OpaqueMap(
1050 CGF,
1051 cast<OpaqueValueExpr>(
1052 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),
1053 RValue::get(Size));
1054 CGF.EmitVariablyModifiedType(PrivateType);
1055}
1056
1057void ReductionCodeGen::emitInitialization(
1058 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal,
1059 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) {
1060 assert(SharedAddresses.size() > N && "No variable was generated");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001061 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001062 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001063 const OMPDeclareReductionDecl *DRD =
1064 getReductionInit(ClausesData[N].ReductionOp);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001065 QualType PrivateType = PrivateVD->getType();
1066 PrivateAddr = CGF.Builder.CreateElementBitCast(
1067 PrivateAddr, CGF.ConvertTypeForMem(PrivateType));
1068 QualType SharedType = SharedAddresses[N].first.getType();
1069 SharedLVal = CGF.MakeAddrLValue(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001070 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(CGF),
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001071 CGF.ConvertTypeForMem(SharedType)),
Ivan A. Kosarevf5f20462017-10-12 11:29:46 +00001072 SharedType, SharedAddresses[N].first.getBaseInfo(),
Ivan A. Kosarevb9c59f32017-10-31 11:05:34 +00001073 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType));
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001074 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001075 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001076 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) {
1077 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp,
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001078 PrivateAddr, SharedLVal.getAddress(CGF),
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001079 SharedLVal.getType());
1080 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
1081 !CGF.isTrivialInitializer(PrivateVD->getInit())) {
1082 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr,
1083 PrivateVD->getType().getQualifiers(),
1084 /*IsInitializer=*/false);
1085 }
1086}
1087
1088bool ReductionCodeGen::needCleanups(unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001089 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001090 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1091 QualType PrivateType = PrivateVD->getType();
1092 QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
1093 return DTorKind != QualType::DK_none;
1094}
1095
1096void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N,
1097 Address PrivateAddr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001098 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001099 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1100 QualType PrivateType = PrivateVD->getType();
1101 QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
1102 if (needCleanups(N)) {
1103 PrivateAddr = CGF.Builder.CreateElementBitCast(
1104 PrivateAddr, CGF.ConvertTypeForMem(PrivateType));
1105 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType);
1106 }
1107}
1108
1109static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
1110 LValue BaseLV) {
1111 BaseTy = BaseTy.getNonReferenceType();
1112 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
1113 !CGF.getContext().hasSameType(BaseTy, ElTy)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001114 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001115 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001116 } else {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001117 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy);
Ivan A. Kosarev9f9d1572017-10-30 11:49:31 +00001118 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001119 }
1120 BaseTy = BaseTy->getPointeeType();
1121 }
1122 return CGF.MakeAddrLValue(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001123 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF),
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001124 CGF.ConvertTypeForMem(ElTy)),
Ivan A. Kosarevf5f20462017-10-12 11:29:46 +00001125 BaseLV.getType(), BaseLV.getBaseInfo(),
Ivan A. Kosarevb9c59f32017-10-31 11:05:34 +00001126 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType()));
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001127}
1128
1129static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
1130 llvm::Type *BaseLVType, CharUnits BaseLVAlignment,
1131 llvm::Value *Addr) {
1132 Address Tmp = Address::invalid();
1133 Address TopTmp = Address::invalid();
1134 Address MostTopTmp = Address::invalid();
1135 BaseTy = BaseTy.getNonReferenceType();
1136 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
1137 !CGF.getContext().hasSameType(BaseTy, ElTy)) {
1138 Tmp = CGF.CreateMemTemp(BaseTy);
1139 if (TopTmp.isValid())
1140 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp);
1141 else
1142 MostTopTmp = Tmp;
1143 TopTmp = Tmp;
1144 BaseTy = BaseTy->getPointeeType();
1145 }
1146 llvm::Type *Ty = BaseLVType;
1147 if (Tmp.isValid())
1148 Ty = Tmp.getElementType();
1149 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty);
1150 if (Tmp.isValid()) {
1151 CGF.Builder.CreateStore(Addr, Tmp);
1152 return MostTopTmp;
1153 }
1154 return Address(Addr, BaseLVAlignment);
1155}
1156
Alexey Bataev1c44e152018-03-06 18:59:43 +00001157static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001158 const VarDecl *OrigVD = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001159 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) {
1160 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
1161 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001162 Base = TempOASE->getBase()->IgnoreParenImpCasts();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001163 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001164 Base = TempASE->getBase()->IgnoreParenImpCasts();
1165 DE = cast<DeclRefExpr>(Base);
1166 OrigVD = cast<VarDecl>(DE->getDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001167 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
1168 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
1169 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001170 Base = TempASE->getBase()->IgnoreParenImpCasts();
1171 DE = cast<DeclRefExpr>(Base);
1172 OrigVD = cast<VarDecl>(DE->getDecl());
1173 }
Alexey Bataev1c44e152018-03-06 18:59:43 +00001174 return OrigVD;
1175}
1176
1177Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N,
1178 Address PrivateAddr) {
1179 const DeclRefExpr *DE;
1180 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001181 BaseDecls.emplace_back(OrigVD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001182 LValue OriginalBaseLValue = CGF.EmitLValue(DE);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001183 LValue BaseLValue =
1184 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
1185 OriginalBaseLValue);
1186 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001187 BaseLValue.getPointer(CGF), SharedAddresses[N].first.getPointer(CGF));
Jonas Hahnfeld273d2612017-12-06 19:15:28 +00001188 llvm::Value *PrivatePointer =
1189 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1190 PrivateAddr.getPointer(),
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001191 SharedAddresses[N].first.getAddress(CGF).getType());
Jonas Hahnfeld273d2612017-12-06 19:15:28 +00001192 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001193 return castToBase(CGF, OrigVD->getType(),
1194 SharedAddresses[N].first.getType(),
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001195 OriginalBaseLValue.getAddress(CGF).getType(),
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001196 OriginalBaseLValue.getAlignment(), Ptr);
1197 }
1198 BaseDecls.emplace_back(
1199 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl()));
1200 return PrivateAddr;
1201}
1202
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001203bool ReductionCodeGen::usesReductionInitializer(unsigned N) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001204 const OMPDeclareReductionDecl *DRD =
1205 getReductionInit(ClausesData[N].ReductionOp);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001206 return DRD && DRD->getInitializer();
1207}
1208
Alexey Bataev18095712014-10-10 12:19:54 +00001209LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
Alexey Bataev31300ed2016-02-04 11:27:03 +00001210 return CGF.EmitLoadOfPointerLValue(
1211 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
1212 getThreadIDVariable()->getType()->castAs<PointerType>());
Alexey Bataev18095712014-10-10 12:19:54 +00001213}
1214
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001215void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001216 if (!CGF.HaveInsertPoint())
1217 return;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001218 // 1.2.2 OpenMP Language Terminology
1219 // Structured block - An executable statement with a single entry at the
1220 // top and a single exit at the bottom.
1221 // The point of exit cannot be a branch out of the structured block.
1222 // longjmp() and throw() must not violate the entry/exit criteria.
1223 CGF.EHStack.pushTerminate();
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001224 CodeGen(CGF);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001225 CGF.EHStack.popTerminate();
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001226}
1227
Alexey Bataev62b63b12015-03-10 07:28:44 +00001228LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1229 CodeGenFunction &CGF) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00001230 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()),
1231 getThreadIDVariable()->getType(),
Ivan A. Kosarev5f8c0ca2017-10-10 09:39:32 +00001232 AlignmentSource::Decl);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001233}
1234
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001235static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
1236 QualType FieldTy) {
1237 auto *Field = FieldDecl::Create(
1238 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
1239 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
1240 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
1241 Field->setAccess(AS_public);
1242 DC->addDecl(Field);
1243 return Field;
1244}
1245
Alexey Bataev18fa2322018-05-02 14:20:50 +00001246CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator,
1247 StringRef Separator)
1248 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator),
1249 OffloadEntriesInfoManager(CGM) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001250 ASTContext &C = CGM.getContext();
1251 RecordDecl *RD = C.buildImplicitRecord("ident_t");
1252 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
1253 RD->startDefinition();
1254 // reserved_1
1255 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1256 // flags
1257 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1258 // reserved_2
1259 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1260 // reserved_3
1261 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1262 // psource
1263 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
1264 RD->completeDefinition();
1265 IdentQTy = C.getRecordType(RD);
1266 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001267 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
Samuel Antaoee8fb302016-01-06 13:42:12 +00001268
1269 loadOffloadInfoMetadata();
Alexey Bataev9959db52014-05-06 10:08:46 +00001270}
1271
Alexey Bataevc2cd2d42019-10-10 17:28:10 +00001272bool CGOpenMPRuntime::tryEmitDeclareVariant(const GlobalDecl &NewGD,
1273 const GlobalDecl &OldGD,
1274 llvm::GlobalValue *OrigAddr,
1275 bool IsForDefinition) {
Alexey Bataev2df5f122019-10-01 20:18:32 +00001276 // Emit at least a definition for the aliasee if the the address of the
1277 // original function is requested.
1278 if (IsForDefinition || OrigAddr)
1279 (void)CGM.GetAddrOfGlobal(NewGD);
1280 StringRef NewMangledName = CGM.getMangledName(NewGD);
1281 llvm::GlobalValue *Addr = CGM.GetGlobalValue(NewMangledName);
1282 if (Addr && !Addr->isDeclaration()) {
1283 const auto *D = cast<FunctionDecl>(OldGD.getDecl());
Alexey Bataev5ad52582019-12-12 15:33:18 -05001284 const CGFunctionInfo &FI = CGM.getTypes().arrangeGlobalDeclaration(NewGD);
Alexey Bataev2df5f122019-10-01 20:18:32 +00001285 llvm::Type *DeclTy = CGM.getTypes().GetFunctionType(FI);
1286
1287 // Create a reference to the named value. This ensures that it is emitted
1288 // if a deferred decl.
1289 llvm::GlobalValue::LinkageTypes LT = CGM.getFunctionLinkage(OldGD);
1290
1291 // Create the new alias itself, but don't set a name yet.
1292 auto *GA =
1293 llvm::GlobalAlias::create(DeclTy, 0, LT, "", Addr, &CGM.getModule());
1294
1295 if (OrigAddr) {
1296 assert(OrigAddr->isDeclaration() && "Expected declaration");
1297
1298 GA->takeName(OrigAddr);
1299 OrigAddr->replaceAllUsesWith(
1300 llvm::ConstantExpr::getBitCast(GA, OrigAddr->getType()));
1301 OrigAddr->eraseFromParent();
1302 } else {
1303 GA->setName(CGM.getMangledName(OldGD));
1304 }
1305
1306 // Set attributes which are particular to an alias; this is a
1307 // specialization of the attributes which may be set on a global function.
1308 if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakRefAttr>() ||
1309 D->isWeakImported())
1310 GA->setLinkage(llvm::Function::WeakAnyLinkage);
1311
1312 CGM.SetCommonAttributes(OldGD, GA);
1313 return true;
1314 }
1315 return false;
1316}
1317
Alexey Bataev91797552015-03-18 04:13:55 +00001318void CGOpenMPRuntime::clear() {
1319 InternalVars.clear();
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00001320 // Clean non-target variable declarations possibly used only in debug info.
1321 for (const auto &Data : EmittedNonTargetVariables) {
1322 if (!Data.getValue().pointsToAliveValue())
1323 continue;
1324 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue());
1325 if (!GV)
1326 continue;
1327 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1328 continue;
1329 GV->eraseFromParent();
1330 }
Alexey Bataev2df5f122019-10-01 20:18:32 +00001331 // Emit aliases for the deferred aliasees.
1332 for (const auto &Pair : DeferredVariantFunction) {
1333 StringRef MangledName = CGM.getMangledName(Pair.second.second);
1334 llvm::GlobalValue *Addr = CGM.GetGlobalValue(MangledName);
1335 // If not able to emit alias, just emit original declaration.
Alexey Bataevc2cd2d42019-10-10 17:28:10 +00001336 (void)tryEmitDeclareVariant(Pair.second.first, Pair.second.second, Addr,
1337 /*IsForDefinition=*/false);
Alexey Bataev2df5f122019-10-01 20:18:32 +00001338 }
Alexey Bataev91797552015-03-18 04:13:55 +00001339}
1340
Alexey Bataev18fa2322018-05-02 14:20:50 +00001341std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const {
1342 SmallString<128> Buffer;
1343 llvm::raw_svector_ostream OS(Buffer);
1344 StringRef Sep = FirstSeparator;
1345 for (StringRef Part : Parts) {
1346 OS << Sep << Part;
1347 Sep = Separator;
1348 }
1349 return OS.str();
1350}
1351
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001352static llvm::Function *
1353emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
1354 const Expr *CombinerInitializer, const VarDecl *In,
1355 const VarDecl *Out, bool IsCombiner) {
1356 // void .omp_combiner.(Ty *in, Ty *out);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001357 ASTContext &C = CGM.getContext();
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001358 QualType PtrTy = C.getPointerType(Ty).withRestrict();
1359 FunctionArgList Args;
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001360 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(),
Alexey Bataev56223232017-06-09 13:40:18 +00001361 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001362 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(),
Alexey Bataev56223232017-06-09 13:40:18 +00001363 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001364 Args.push_back(&OmpOutParm);
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001365 Args.push_back(&OmpInParm);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001366 const CGFunctionInfo &FnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00001367 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001368 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00001369 std::string Name = CGM.getOpenMPRuntime().getName(
1370 {IsCombiner ? "omp_combiner" : "omp_initializer", ""});
1371 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1372 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00001373 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataev8c5555c2019-05-21 15:11:58 +00001374 if (CGM.getLangOpts().Optimize) {
1375 Fn->removeFnAttr(llvm::Attribute::NoInline);
1376 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1377 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1378 }
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001379 CodeGenFunction CGF(CGM);
1380 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
1381 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions.
Alexey Bataev7cae94e2018-01-04 19:45:16 +00001382 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(),
1383 Out->getLocation());
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001384 CodeGenFunction::OMPPrivateScope Scope(CGF);
1385 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001386 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() {
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001387 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>())
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001388 .getAddress(CGF);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001389 });
1390 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001391 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() {
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001392 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>())
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001393 .getAddress(CGF);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001394 });
1395 (void)Scope.Privatize();
Alexey Bataev070f43a2017-09-06 14:49:58 +00001396 if (!IsCombiner && Out->hasInit() &&
1397 !CGF.isTrivialInitializer(Out->getInit())) {
1398 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out),
1399 Out->getType().getQualifiers(),
1400 /*IsInitializer=*/true);
1401 }
1402 if (CombinerInitializer)
1403 CGF.EmitIgnoredExpr(CombinerInitializer);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001404 Scope.ForceCleanup();
1405 CGF.FinishFunction();
1406 return Fn;
1407}
1408
1409void CGOpenMPRuntime::emitUserDefinedReduction(
1410 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) {
1411 if (UDRMap.count(D) > 0)
1412 return;
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001413 llvm::Function *Combiner = emitCombinerOrInitializer(
Alexey Bataeve6aa4692018-09-13 16:54:05 +00001414 CGM, D->getType(), D->getCombiner(),
1415 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()),
1416 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()),
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001417 /*IsCombiner=*/true);
1418 llvm::Function *Initializer = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001419 if (const Expr *Init = D->getInitializer()) {
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001420 Initializer = emitCombinerOrInitializer(
Alexey Bataev070f43a2017-09-06 14:49:58 +00001421 CGM, D->getType(),
1422 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init
1423 : nullptr,
Alexey Bataeve6aa4692018-09-13 16:54:05 +00001424 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()),
1425 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()),
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001426 /*IsCombiner=*/false);
1427 }
Alexey Bataev43a919f2018-04-13 17:48:43 +00001428 UDRMap.try_emplace(D, Combiner, Initializer);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001429 if (CGF) {
1430 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn);
1431 Decls.second.push_back(D);
1432 }
1433}
1434
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001435std::pair<llvm::Function *, llvm::Function *>
1436CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) {
1437 auto I = UDRMap.find(D);
1438 if (I != UDRMap.end())
1439 return I->second;
1440 emitUserDefinedReduction(/*CGF=*/nullptr, D);
1441 return UDRMap.lookup(D);
1442}
1443
James Y Knight9871db02019-02-05 16:42:33 +00001444static llvm::Function *emitParallelOrTeamsOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001445 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS,
1446 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind,
1447 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00001448 assert(ThreadIDVar->getType()->isPointerType() &&
1449 "thread id variable must be of type kmp_int32 *");
Alexey Bataev18095712014-10-10 12:19:54 +00001450 CodeGenFunction CGF(CGM, true);
Alexey Bataev25e5b442015-09-15 12:52:43 +00001451 bool HasCancel = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001452 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001453 HasCancel = OPD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001454 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001455 HasCancel = OPSD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001456 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001457 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001458 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
Alexey Bataev2139ed62017-11-16 18:20:21 +00001459 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001460 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
Alexey Bataev10a54312017-11-27 16:54:08 +00001461 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001462 else if (const auto *OPFD =
1463 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
Alexey Bataev10a54312017-11-27 16:54:08 +00001464 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001465 else if (const auto *OPFD =
Alexey Bataev10a54312017-11-27 16:54:08 +00001466 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1467 HasCancel = OPFD->hasCancel();
Alexey Bataev25e5b442015-09-15 12:52:43 +00001468 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001469 HasCancel, OutlinedHelperName);
Alexey Bataevd157d472015-06-24 03:35:38 +00001470 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev2377fe92015-09-10 08:12:02 +00001471 return CGF.GenerateOpenMPCapturedStmtFunction(*CS);
Alexey Bataev18095712014-10-10 12:19:54 +00001472}
1473
James Y Knight9871db02019-02-05 16:42:33 +00001474llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001475 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1476 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1477 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1478 return emitParallelOrTeamsOutlinedFunction(
1479 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1480}
1481
James Y Knight9871db02019-02-05 16:42:33 +00001482llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001483 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1484 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1485 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1486 return emitParallelOrTeamsOutlinedFunction(
1487 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1488}
1489
James Y Knight9871db02019-02-05 16:42:33 +00001490llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001491 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
Alexey Bataev48591dd2016-04-20 04:01:36 +00001492 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
1493 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
1494 bool Tied, unsigned &NumberOfParts) {
1495 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF,
1496 PrePostActionTy &) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00001497 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc());
1498 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc());
Alexey Bataev48591dd2016-04-20 04:01:36 +00001499 llvm::Value *TaskArgs[] = {
1500 UpLoc, ThreadID,
1501 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1502 TaskTVar->getType()->castAs<PointerType>())
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001503 .getPointer(CGF)};
Alexey Bataev48591dd2016-04-20 04:01:36 +00001504 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs);
1505 };
1506 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1507 UntiedCodeGen);
1508 CodeGen.setAction(Action);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001509 assert(!ThreadIDVar->getType()->isPointerType() &&
1510 "thread id variable must be of type kmp_int32 for tasks");
Alexey Bataev475a7442018-01-12 19:39:11 +00001511 const OpenMPDirectiveKind Region =
1512 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop
1513 : OMPD_task;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001514 const CapturedStmt *CS = D.getCapturedStmt(Region);
1515 const auto *TD = dyn_cast<OMPTaskDirective>(&D);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001516 CodeGenFunction CGF(CGM, true);
Alexey Bataev7292c292016-04-25 12:22:29 +00001517 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
1518 InnermostKind,
1519 TD ? TD->hasCancel() : false, Action);
Alexey Bataevd157d472015-06-24 03:35:38 +00001520 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
James Y Knight9871db02019-02-05 16:42:33 +00001521 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
Alexey Bataev48591dd2016-04-20 04:01:36 +00001522 if (!Tied)
1523 NumberOfParts = Action.getNumberOfParts();
1524 return Res;
Alexey Bataev62b63b12015-03-10 07:28:44 +00001525}
1526
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001527static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM,
1528 const RecordDecl *RD, const CGRecordLayout &RL,
1529 ArrayRef<llvm::Constant *> Data) {
1530 llvm::StructType *StructTy = RL.getLLVMType();
1531 unsigned PrevIdx = 0;
1532 ConstantInitBuilder CIBuilder(CGM);
1533 auto DI = Data.begin();
1534 for (const FieldDecl *FD : RD->fields()) {
1535 unsigned Idx = RL.getLLVMFieldNo(FD);
1536 // Fill the alignment.
1537 for (unsigned I = PrevIdx; I < Idx; ++I)
1538 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I)));
1539 PrevIdx = Idx + 1;
1540 Fields.add(*DI);
1541 ++DI;
1542 }
1543}
1544
1545template <class... As>
1546static llvm::GlobalVariable *
Mike Ricee1ca7b62018-08-29 15:45:11 +00001547createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant,
1548 ArrayRef<llvm::Constant *> Data, const Twine &Name,
1549 As &&... Args) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001550 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1551 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1552 ConstantInitBuilder CIBuilder(CGM);
1553 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType());
1554 buildStructValue(Fields, CGM, RD, RL, Data);
1555 return Fields.finishAndCreateGlobal(
Mike Ricee1ca7b62018-08-29 15:45:11 +00001556 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant,
1557 std::forward<As>(Args)...);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001558}
1559
1560template <typename T>
Benjamin Kramer651d0bf2018-05-15 21:26:47 +00001561static void
1562createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty,
1563 ArrayRef<llvm::Constant *> Data,
1564 T &Parent) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001565 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1566 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1567 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType());
1568 buildStructValue(Fields, CGM, RD, RL, Data);
1569 Fields.finishAndAddTo(Parent);
1570}
1571
Alexey Bataev50b3c952016-02-19 10:38:26 +00001572Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001573 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy);
Alexey Bataevceeaa482018-11-21 21:04:34 +00001574 unsigned Reserved2Flags = getDefaultLocationReserved2Flags();
1575 FlagsTy FlagsKey(Flags, Reserved2Flags);
1576 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey);
Alexey Bataev9959db52014-05-06 10:08:46 +00001577 if (!Entry) {
1578 if (!DefaultOpenMPPSource) {
1579 // Initialize default location for psource field of ident_t structure of
1580 // all ident_t objects. Format is ";file;function;line;column;;".
1581 // Taken from
James Y Knight5d71fc52019-01-29 16:37:27 +00001582 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp
Alexey Bataev9959db52014-05-06 10:08:46 +00001583 DefaultOpenMPPSource =
John McCall7f416cc2015-09-08 08:05:57 +00001584 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001585 DefaultOpenMPPSource =
1586 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
1587 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001588
Alexey Bataevceeaa482018-11-21 21:04:34 +00001589 llvm::Constant *Data[] = {
1590 llvm::ConstantInt::getNullValue(CGM.Int32Ty),
1591 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
1592 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags),
1593 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource};
Mike Ricee1ca7b62018-08-29 15:45:11 +00001594 llvm::GlobalValue *DefaultOpenMPLocation =
Alexey Bataevceeaa482018-11-21 21:04:34 +00001595 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "",
Mike Ricee1ca7b62018-08-29 15:45:11 +00001596 llvm::GlobalValue::PrivateLinkage);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001597 DefaultOpenMPLocation->setUnnamedAddr(
1598 llvm::GlobalValue::UnnamedAddr::Global);
John McCall6c9f1fdb2016-11-19 08:17:24 +00001599
Alexey Bataevceeaa482018-11-21 21:04:34 +00001600 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation;
Alexey Bataev9959db52014-05-06 10:08:46 +00001601 }
John McCall7f416cc2015-09-08 08:05:57 +00001602 return Address(Entry, Align);
Alexey Bataev9959db52014-05-06 10:08:46 +00001603}
1604
Alexey Bataevfd006c42018-10-05 15:08:53 +00001605void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF,
1606 bool AtCurrentPoint) {
1607 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1608 assert(!Elem.second.ServiceInsertPt && "Insert point is set already.");
1609
1610 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty);
1611 if (AtCurrentPoint) {
1612 Elem.second.ServiceInsertPt = new llvm::BitCastInst(
1613 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock());
1614 } else {
1615 Elem.second.ServiceInsertPt =
1616 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt");
1617 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt);
1618 }
1619}
1620
1621void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) {
1622 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1623 if (Elem.second.ServiceInsertPt) {
1624 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt;
1625 Elem.second.ServiceInsertPt = nullptr;
1626 Ptr->eraseFromParent();
1627 }
1628}
1629
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001630llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
1631 SourceLocation Loc,
Alexey Bataev50b3c952016-02-19 10:38:26 +00001632 unsigned Flags) {
1633 Flags |= OMP_IDENT_KMPC;
Alexey Bataev9959db52014-05-06 10:08:46 +00001634 // If no debug info is generated - return global default location.
Benjamin Kramer8c305922016-02-02 11:06:51 +00001635 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo ||
Alexey Bataev9959db52014-05-06 10:08:46 +00001636 Loc.isInvalid())
John McCall7f416cc2015-09-08 08:05:57 +00001637 return getOrCreateDefaultLocation(Flags).getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001638
1639 assert(CGF.CurFn && "No function in current CodeGenFunction.");
1640
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001641 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy);
John McCall7f416cc2015-09-08 08:05:57 +00001642 Address LocValue = Address::invalid();
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001643 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
1644 if (I != OpenMPLocThreadIDMap.end())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001645 LocValue = Address(I->second.DebugLoc, Align);
John McCall7f416cc2015-09-08 08:05:57 +00001646
Alexander Musmanc6388682014-12-15 07:07:06 +00001647 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
1648 // GetOpenMPThreadID was called before this routine.
John McCall7f416cc2015-09-08 08:05:57 +00001649 if (!LocValue.isValid()) {
Alexey Bataev15007ba2014-05-07 06:18:01 +00001650 // Generate "ident_t .kmpc_loc.addr;"
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001651 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr");
Alexey Bataev18095712014-10-10 12:19:54 +00001652 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
John McCall7f416cc2015-09-08 08:05:57 +00001653 Elem.second.DebugLoc = AI.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001654 LocValue = AI;
1655
Alexey Bataevfd006c42018-10-05 15:08:53 +00001656 if (!Elem.second.ServiceInsertPt)
1657 setLocThreadIdInsertPt(CGF);
Alexey Bataev9959db52014-05-06 10:08:46 +00001658 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001659 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001660 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001661 CGF.getTypeSize(IdentQTy));
Alexey Bataev9959db52014-05-06 10:08:46 +00001662 }
1663
1664 // char **psource = &.kmpc_loc_<flags>.addr.psource;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001665 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy);
1666 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin();
1667 LValue PSource =
1668 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource));
Alexey Bataev9959db52014-05-06 10:08:46 +00001669
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001670 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
Alexey Bataevf002aca2014-05-30 05:48:40 +00001671 if (OMPDebugLoc == nullptr) {
1672 SmallString<128> Buffer2;
1673 llvm::raw_svector_ostream OS2(Buffer2);
1674 // Build debug location
1675 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
1676 OS2 << ";" << PLoc.getFilename() << ";";
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001677 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl))
Alexey Bataevf002aca2014-05-30 05:48:40 +00001678 OS2 << FD->getQualifiedNameAsString();
Alexey Bataevf002aca2014-05-30 05:48:40 +00001679 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
1680 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
1681 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
Alexey Bataev9959db52014-05-06 10:08:46 +00001682 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001683 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001684 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource);
Alexey Bataevf002aca2014-05-30 05:48:40 +00001685
John McCall7f416cc2015-09-08 08:05:57 +00001686 // Our callers always pass this to a runtime function, so for
1687 // convenience, go ahead and return a naked pointer.
1688 return LocValue.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001689}
1690
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001691llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
1692 SourceLocation Loc) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001693 assert(CGF.CurFn && "No function in current CodeGenFunction.");
1694
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001695 llvm::Value *ThreadID = nullptr;
Alexey Bataev18095712014-10-10 12:19:54 +00001696 // Check whether we've already cached a load of the thread id in this
1697 // function.
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001698 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
Alexey Bataev18095712014-10-10 12:19:54 +00001699 if (I != OpenMPLocThreadIDMap.end()) {
1700 ThreadID = I->second.ThreadID;
Alexey Bataev03b340a2014-10-21 03:16:40 +00001701 if (ThreadID != nullptr)
1702 return ThreadID;
1703 }
Alexey Bataevaee18552017-08-16 14:01:00 +00001704 // If exceptions are enabled, do not use parameter to avoid possible crash.
Alexey Bataev780f5552019-10-17 17:12:03 +00001705 if (auto *OMPRegionInfo =
1706 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
1707 if (OMPRegionInfo->getThreadIDVariable()) {
1708 // Check if this an outlined function with thread id passed as argument.
1709 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1710 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent();
1711 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions ||
1712 !CGF.getLangOpts().CXXExceptions ||
1713 CGF.Builder.GetInsertBlock() == TopBlock ||
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001714 !isa<llvm::Instruction>(LVal.getPointer(CGF)) ||
1715 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() ==
1716 TopBlock ||
1717 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() ==
Alexey Bataev780f5552019-10-17 17:12:03 +00001718 CGF.Builder.GetInsertBlock()) {
Alexey Bataev1e491372018-01-23 18:44:14 +00001719 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc);
Alexey Bataevaee18552017-08-16 14:01:00 +00001720 // If value loaded in entry block, cache it and use it everywhere in
1721 // function.
Alexey Bataev780f5552019-10-17 17:12:03 +00001722 if (CGF.Builder.GetInsertBlock() == TopBlock) {
Alexey Bataevaee18552017-08-16 14:01:00 +00001723 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1724 Elem.second.ThreadID = ThreadID;
1725 }
1726 return ThreadID;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001727 }
Alexey Bataevd6c57552014-07-25 07:55:17 +00001728 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001729 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001730
1731 // This is not an outlined function region - need to call __kmpc_int32
1732 // kmpc_global_thread_num(ident_t *loc).
1733 // Generate thread id value and cache this value for use across the
1734 // function.
Alexey Bataevfd006c42018-10-05 15:08:53 +00001735 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1736 if (!Elem.second.ServiceInsertPt)
1737 setLocThreadIdInsertPt(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001738 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001739 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001740 llvm::CallInst *Call = CGF.Builder.CreateCall(
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001741 createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
1742 emitUpdateLocation(CGF, Loc));
1743 Call->setCallingConv(CGF.getRuntimeCC());
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001744 Elem.second.ThreadID = Call;
1745 return Call;
Alexey Bataev9959db52014-05-06 10:08:46 +00001746}
1747
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001748void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001749 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataevfd006c42018-10-05 15:08:53 +00001750 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) {
1751 clearLocThreadIdInsertPt(CGF);
Alexey Bataev03b340a2014-10-21 03:16:40 +00001752 OpenMPLocThreadIDMap.erase(CGF.CurFn);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001753 }
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001754 if (FunctionUDRMap.count(CGF.CurFn) > 0) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001755 for(auto *D : FunctionUDRMap[CGF.CurFn])
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001756 UDRMap.erase(D);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001757 FunctionUDRMap.erase(CGF.CurFn);
1758 }
Michael Krused47b9432019-08-05 18:43:21 +00001759 auto I = FunctionUDMMap.find(CGF.CurFn);
1760 if (I != FunctionUDMMap.end()) {
1761 for(auto *D : I->second)
1762 UDMMap.erase(D);
1763 FunctionUDMMap.erase(I);
1764 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001765}
1766
1767llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001768 return IdentTy->getPointerTo();
Alexey Bataev9959db52014-05-06 10:08:46 +00001769}
1770
1771llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001772 if (!Kmpc_MicroTy) {
1773 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
1774 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
1775 llvm::PointerType::getUnqual(CGM.Int32Ty)};
1776 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
1777 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001778 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
1779}
1780
James Y Knight9871db02019-02-05 16:42:33 +00001781llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
1782 llvm::FunctionCallee RTLFn = nullptr;
Alexey Bataev50b3c952016-02-19 10:38:26 +00001783 switch (static_cast<OpenMPRTLFunction>(Function)) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001784 case OMPRTL__kmpc_fork_call: {
1785 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
1786 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +00001787 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1788 getKmpc_MicroPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001789 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001790 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
Alexey Bataev9959db52014-05-06 10:08:46 +00001791 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
James Y Knight9871db02019-02-05 16:42:33 +00001792 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) {
Johannes Doerfertac991bb2019-01-19 05:36:54 +00001793 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
1794 llvm::LLVMContext &Ctx = F->getContext();
1795 llvm::MDBuilder MDB(Ctx);
1796 // Annotate the callback behavior of the __kmpc_fork_call:
1797 // - The callback callee is argument number 2 (microtask).
1798 // - The first two arguments of the callback callee are unknown (-1).
1799 // - All variadic arguments to the __kmpc_fork_call are passed to the
1800 // callback callee.
1801 F->addMetadata(
1802 llvm::LLVMContext::MD_callback,
1803 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
1804 2, {-1, -1},
1805 /* VarArgsArePassed */ true)}));
1806 }
1807 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001808 break;
1809 }
1810 case OMPRTL__kmpc_global_thread_num: {
1811 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +00001812 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001813 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001814 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
Alexey Bataev9959db52014-05-06 10:08:46 +00001815 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
1816 break;
1817 }
Alexey Bataev97720002014-11-11 04:05:39 +00001818 case OMPRTL__kmpc_threadprivate_cached: {
1819 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
1820 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
1821 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1822 CGM.VoidPtrTy, CGM.SizeTy,
1823 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001824 auto *FnTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001825 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
1826 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
1827 break;
1828 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001829 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001830 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
1831 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001832 llvm::Type *TypeParams[] = {
1833 getIdentTyPointerTy(), CGM.Int32Ty,
1834 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001835 auto *FnTy =
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001836 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1837 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
1838 break;
1839 }
Alexey Bataevfc57d162015-12-15 10:55:09 +00001840 case OMPRTL__kmpc_critical_with_hint: {
1841 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid,
1842 // kmp_critical_name *crit, uintptr_t hint);
1843 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1844 llvm::PointerType::getUnqual(KmpCriticalNameTy),
1845 CGM.IntPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001846 auto *FnTy =
Alexey Bataevfc57d162015-12-15 10:55:09 +00001847 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1848 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint");
1849 break;
1850 }
Alexey Bataev97720002014-11-11 04:05:39 +00001851 case OMPRTL__kmpc_threadprivate_register: {
1852 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
1853 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
1854 // typedef void *(*kmpc_ctor)(void *);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001855 auto *KmpcCtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001856 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1857 /*isVarArg*/ false)->getPointerTo();
1858 // typedef void *(*kmpc_cctor)(void *, void *);
1859 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001860 auto *KmpcCopyCtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001861 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001862 /*isVarArg*/ false)
1863 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00001864 // typedef void (*kmpc_dtor)(void *);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001865 auto *KmpcDtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001866 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
1867 ->getPointerTo();
1868 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
1869 KmpcCopyCtorTy, KmpcDtorTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001870 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
Alexey Bataev97720002014-11-11 04:05:39 +00001871 /*isVarArg*/ false);
1872 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
1873 break;
1874 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001875 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001876 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
1877 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001878 llvm::Type *TypeParams[] = {
1879 getIdentTyPointerTy(), CGM.Int32Ty,
1880 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001881 auto *FnTy =
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001882 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1883 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
1884 break;
1885 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001886 case OMPRTL__kmpc_cancel_barrier: {
1887 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
1888 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001889 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001890 auto *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001891 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1892 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001893 break;
1894 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001895 case OMPRTL__kmpc_barrier: {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001896 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001897 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001898 auto *FnTy =
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001899 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1900 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
1901 break;
1902 }
Alexander Musmanc6388682014-12-15 07:07:06 +00001903 case OMPRTL__kmpc_for_static_fini: {
1904 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
1905 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001906 auto *FnTy =
Alexander Musmanc6388682014-12-15 07:07:06 +00001907 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1908 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
1909 break;
1910 }
Alexey Bataevb2059782014-10-13 08:23:51 +00001911 case OMPRTL__kmpc_push_num_threads: {
1912 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
1913 // kmp_int32 num_threads)
1914 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1915 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001916 auto *FnTy =
Alexey Bataevb2059782014-10-13 08:23:51 +00001917 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1918 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
1919 break;
1920 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001921 case OMPRTL__kmpc_serialized_parallel: {
1922 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
1923 // global_tid);
1924 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001925 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001926 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1927 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
1928 break;
1929 }
1930 case OMPRTL__kmpc_end_serialized_parallel: {
1931 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
1932 // global_tid);
1933 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001934 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001935 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1936 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
1937 break;
1938 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001939 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001940 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001941 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001942 auto *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001943 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001944 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
1945 break;
1946 }
Alexey Bataev8d690652014-12-04 07:23:53 +00001947 case OMPRTL__kmpc_master: {
1948 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
1949 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001950 auto *FnTy =
Alexey Bataev8d690652014-12-04 07:23:53 +00001951 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1952 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
1953 break;
1954 }
1955 case OMPRTL__kmpc_end_master: {
1956 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
1957 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001958 auto *FnTy =
Alexey Bataev8d690652014-12-04 07:23:53 +00001959 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1960 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
1961 break;
1962 }
Alexey Bataev9f797f32015-02-05 05:57:51 +00001963 case OMPRTL__kmpc_omp_taskyield: {
1964 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
1965 // int end_part);
1966 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001967 auto *FnTy =
Alexey Bataev9f797f32015-02-05 05:57:51 +00001968 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1969 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
1970 break;
1971 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001972 case OMPRTL__kmpc_single: {
1973 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
1974 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001975 auto *FnTy =
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001976 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1977 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
1978 break;
1979 }
1980 case OMPRTL__kmpc_end_single: {
1981 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
1982 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001983 auto *FnTy =
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001984 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1985 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
1986 break;
1987 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00001988 case OMPRTL__kmpc_omp_task_alloc: {
1989 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
1990 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
1991 // kmp_routine_entry_t *task_entry);
1992 assert(KmpRoutineEntryPtrTy != nullptr &&
1993 "Type kmp_routine_entry_t must be created.");
1994 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1995 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
1996 // Return void * and then cast to particular kmp_task_t type.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001997 auto *FnTy =
Alexey Bataev62b63b12015-03-10 07:28:44 +00001998 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
1999 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
2000 break;
2001 }
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00002002 case OMPRTL__kmpc_omp_target_task_alloc: {
2003 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid,
2004 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
2005 // kmp_routine_entry_t *task_entry, kmp_int64 device_id);
2006 assert(KmpRoutineEntryPtrTy != nullptr &&
2007 "Type kmp_routine_entry_t must be created.");
2008 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
2009 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy,
2010 CGM.Int64Ty};
2011 // Return void * and then cast to particular kmp_task_t type.
2012 auto *FnTy =
2013 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2014 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc");
2015 break;
2016 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002017 case OMPRTL__kmpc_omp_task: {
2018 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2019 // *new_task);
2020 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2021 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002022 auto *FnTy =
Alexey Bataev62b63b12015-03-10 07:28:44 +00002023 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2024 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
2025 break;
2026 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00002027 case OMPRTL__kmpc_copyprivate: {
2028 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
Alexey Bataev66beaa92015-04-30 03:47:32 +00002029 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
Alexey Bataeva63048e2015-03-23 06:18:07 +00002030 // kmp_int32 didit);
2031 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2032 auto *CpyFnTy =
2033 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
Alexey Bataev66beaa92015-04-30 03:47:32 +00002034 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
Alexey Bataeva63048e2015-03-23 06:18:07 +00002035 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
2036 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002037 auto *FnTy =
Alexey Bataeva63048e2015-03-23 06:18:07 +00002038 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2039 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
2040 break;
2041 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002042 case OMPRTL__kmpc_reduce: {
2043 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
2044 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
2045 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
2046 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2047 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
2048 /*isVarArg=*/false);
2049 llvm::Type *TypeParams[] = {
2050 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
2051 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
2052 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002053 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002054 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2055 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
2056 break;
2057 }
2058 case OMPRTL__kmpc_reduce_nowait: {
2059 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
2060 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
2061 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
2062 // *lck);
2063 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2064 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
2065 /*isVarArg=*/false);
2066 llvm::Type *TypeParams[] = {
2067 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
2068 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
2069 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002070 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002071 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2072 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
2073 break;
2074 }
2075 case OMPRTL__kmpc_end_reduce: {
2076 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
2077 // kmp_critical_name *lck);
2078 llvm::Type *TypeParams[] = {
2079 getIdentTyPointerTy(), CGM.Int32Ty,
2080 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002081 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002082 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2083 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
2084 break;
2085 }
2086 case OMPRTL__kmpc_end_reduce_nowait: {
2087 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
2088 // kmp_critical_name *lck);
2089 llvm::Type *TypeParams[] = {
2090 getIdentTyPointerTy(), CGM.Int32Ty,
2091 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002092 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002093 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2094 RTLFn =
2095 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
2096 break;
2097 }
Alexey Bataev1d677132015-04-22 13:57:31 +00002098 case OMPRTL__kmpc_omp_task_begin_if0: {
2099 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2100 // *new_task);
2101 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2102 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002103 auto *FnTy =
Alexey Bataev1d677132015-04-22 13:57:31 +00002104 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2105 RTLFn =
2106 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
2107 break;
2108 }
2109 case OMPRTL__kmpc_omp_task_complete_if0: {
2110 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2111 // *new_task);
2112 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2113 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002114 auto *FnTy =
Alexey Bataev1d677132015-04-22 13:57:31 +00002115 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2116 RTLFn = CGM.CreateRuntimeFunction(FnTy,
2117 /*Name=*/"__kmpc_omp_task_complete_if0");
2118 break;
2119 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002120 case OMPRTL__kmpc_ordered: {
2121 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
2122 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002123 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002124 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2125 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
2126 break;
2127 }
2128 case OMPRTL__kmpc_end_ordered: {
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002129 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002130 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002131 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002132 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2133 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
2134 break;
2135 }
Alexey Bataev8b8e2022015-04-27 05:22:09 +00002136 case OMPRTL__kmpc_omp_taskwait: {
2137 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
2138 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002139 auto *FnTy =
Alexey Bataev8b8e2022015-04-27 05:22:09 +00002140 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2141 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
2142 break;
2143 }
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002144 case OMPRTL__kmpc_taskgroup: {
2145 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
2146 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002147 auto *FnTy =
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002148 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2149 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
2150 break;
2151 }
2152 case OMPRTL__kmpc_end_taskgroup: {
2153 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
2154 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002155 auto *FnTy =
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002156 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2157 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
2158 break;
2159 }
Alexey Bataev7f210c62015-06-18 13:40:03 +00002160 case OMPRTL__kmpc_push_proc_bind: {
2161 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
2162 // int proc_bind)
2163 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002164 auto *FnTy =
Alexey Bataev7f210c62015-06-18 13:40:03 +00002165 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2166 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
2167 break;
2168 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002169 case OMPRTL__kmpc_omp_task_with_deps: {
2170 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
2171 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
2172 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
2173 llvm::Type *TypeParams[] = {
2174 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
2175 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002176 auto *FnTy =
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002177 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2178 RTLFn =
2179 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
2180 break;
2181 }
2182 case OMPRTL__kmpc_omp_wait_deps: {
2183 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
2184 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
2185 // kmp_depend_info_t *noalias_dep_list);
2186 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2187 CGM.Int32Ty, CGM.VoidPtrTy,
2188 CGM.Int32Ty, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002189 auto *FnTy =
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002190 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2191 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
2192 break;
2193 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00002194 case OMPRTL__kmpc_cancellationpoint: {
2195 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
2196 // global_tid, kmp_int32 cncl_kind)
2197 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002198 auto *FnTy =
Alexey Bataev0f34da12015-07-02 04:17:07 +00002199 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2200 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
2201 break;
2202 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002203 case OMPRTL__kmpc_cancel: {
2204 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
2205 // kmp_int32 cncl_kind)
2206 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002207 auto *FnTy =
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002208 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2209 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
2210 break;
2211 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002212 case OMPRTL__kmpc_push_num_teams: {
2213 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid,
2214 // kmp_int32 num_teams, kmp_int32 num_threads)
2215 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
2216 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002217 auto *FnTy =
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002218 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2219 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams");
2220 break;
2221 }
2222 case OMPRTL__kmpc_fork_teams: {
2223 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
2224 // microtask, ...);
2225 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2226 getKmpc_MicroPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002227 auto *FnTy =
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002228 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
2229 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams");
James Y Knight9871db02019-02-05 16:42:33 +00002230 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) {
Johannes Doerfertac991bb2019-01-19 05:36:54 +00002231 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
2232 llvm::LLVMContext &Ctx = F->getContext();
2233 llvm::MDBuilder MDB(Ctx);
2234 // Annotate the callback behavior of the __kmpc_fork_teams:
2235 // - The callback callee is argument number 2 (microtask).
2236 // - The first two arguments of the callback callee are unknown (-1).
2237 // - All variadic arguments to the __kmpc_fork_teams are passed to the
2238 // callback callee.
2239 F->addMetadata(
2240 llvm::LLVMContext::MD_callback,
2241 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
2242 2, {-1, -1},
2243 /* VarArgsArePassed */ true)}));
2244 }
2245 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002246 break;
2247 }
Alexey Bataev7292c292016-04-25 12:22:29 +00002248 case OMPRTL__kmpc_taskloop: {
2249 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
2250 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
2251 // sched, kmp_uint64 grainsize, void *task_dup);
2252 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
2253 CGM.IntTy,
2254 CGM.VoidPtrTy,
2255 CGM.IntTy,
2256 CGM.Int64Ty->getPointerTo(),
2257 CGM.Int64Ty->getPointerTo(),
2258 CGM.Int64Ty,
2259 CGM.IntTy,
2260 CGM.IntTy,
2261 CGM.Int64Ty,
2262 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002263 auto *FnTy =
Alexey Bataev7292c292016-04-25 12:22:29 +00002264 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2265 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop");
2266 break;
2267 }
Alexey Bataev8b427062016-05-25 12:36:08 +00002268 case OMPRTL__kmpc_doacross_init: {
2269 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32
2270 // num_dims, struct kmp_dim *dims);
2271 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
2272 CGM.Int32Ty,
2273 CGM.Int32Ty,
2274 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002275 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002276 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2277 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init");
2278 break;
2279 }
2280 case OMPRTL__kmpc_doacross_fini: {
2281 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid);
2282 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002283 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002284 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2285 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini");
2286 break;
2287 }
2288 case OMPRTL__kmpc_doacross_post: {
2289 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64
2290 // *vec);
2291 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2292 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002293 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002294 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2295 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post");
2296 break;
2297 }
2298 case OMPRTL__kmpc_doacross_wait: {
2299 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64
2300 // *vec);
2301 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2302 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002303 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002304 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2305 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait");
2306 break;
2307 }
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002308 case OMPRTL__kmpc_task_reduction_init: {
2309 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void
2310 // *data);
2311 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002312 auto *FnTy =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002313 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2314 RTLFn =
2315 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init");
2316 break;
2317 }
2318 case OMPRTL__kmpc_task_reduction_get_th_data: {
2319 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
2320 // *d);
2321 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002322 auto *FnTy =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002323 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2324 RTLFn = CGM.CreateRuntimeFunction(
2325 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data");
2326 break;
2327 }
Alexey Bataev4f680db2019-03-19 16:41:16 +00002328 case OMPRTL__kmpc_alloc: {
Alexey Bataev6cf7b712019-04-08 19:06:42 +00002329 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t
2330 // al); omp_allocator_handle_t type is void *.
2331 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy};
Alexey Bataev4f680db2019-03-19 16:41:16 +00002332 auto *FnTy =
2333 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2334 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc");
2335 break;
2336 }
2337 case OMPRTL__kmpc_free: {
Alexey Bataev6cf7b712019-04-08 19:06:42 +00002338 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t
2339 // al); omp_allocator_handle_t type is void *.
2340 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataev4f680db2019-03-19 16:41:16 +00002341 auto *FnTy =
2342 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2343 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free");
2344 break;
2345 }
Alexey Bataev7bb33532019-01-07 21:30:43 +00002346 case OMPRTL__kmpc_push_target_tripcount: {
2347 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64
2348 // size);
2349 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty};
2350 llvm::FunctionType *FnTy =
2351 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2352 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount");
2353 break;
2354 }
Samuel Antaobed3c462015-10-02 16:14:20 +00002355 case OMPRTL__tgt_target: {
George Rokos63bc9d62017-11-21 18:25:12 +00002356 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002357 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Samuel Antaobed3c462015-10-02 16:14:20 +00002358 // *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002359 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaobed3c462015-10-02 16:14:20 +00002360 CGM.VoidPtrTy,
2361 CGM.Int32Ty,
2362 CGM.VoidPtrPtrTy,
2363 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002364 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002365 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002366 auto *FnTy =
Samuel Antaobed3c462015-10-02 16:14:20 +00002367 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2368 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
2369 break;
2370 }
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002371 case OMPRTL__tgt_target_nowait: {
2372 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002373 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes,
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002374 // int64_t *arg_types);
2375 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2376 CGM.VoidPtrTy,
2377 CGM.Int32Ty,
2378 CGM.VoidPtrPtrTy,
2379 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002380 CGM.Int64Ty->getPointerTo(),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002381 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002382 auto *FnTy =
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002383 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2384 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait");
2385 break;
2386 }
Samuel Antaob68e2db2016-03-03 16:20:23 +00002387 case OMPRTL__tgt_target_teams: {
George Rokos63bc9d62017-11-21 18:25:12 +00002388 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002389 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes,
George Rokos63bc9d62017-11-21 18:25:12 +00002390 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
2391 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaob68e2db2016-03-03 16:20:23 +00002392 CGM.VoidPtrTy,
2393 CGM.Int32Ty,
2394 CGM.VoidPtrPtrTy,
2395 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002396 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002397 CGM.Int64Ty->getPointerTo(),
Samuel Antaob68e2db2016-03-03 16:20:23 +00002398 CGM.Int32Ty,
2399 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002400 auto *FnTy =
Samuel Antaob68e2db2016-03-03 16:20:23 +00002401 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2402 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams");
2403 break;
2404 }
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002405 case OMPRTL__tgt_target_teams_nowait: {
2406 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void
Alexey Bataeva90fc662019-06-25 16:00:43 +00002407 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002408 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
2409 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2410 CGM.VoidPtrTy,
2411 CGM.Int32Ty,
2412 CGM.VoidPtrPtrTy,
2413 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002414 CGM.Int64Ty->getPointerTo(),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002415 CGM.Int64Ty->getPointerTo(),
2416 CGM.Int32Ty,
2417 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002418 auto *FnTy =
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002419 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2420 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait");
2421 break;
2422 }
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00002423 case OMPRTL__tgt_register_requires: {
2424 // Build void __tgt_register_requires(int64_t flags);
2425 llvm::Type *TypeParams[] = {CGM.Int64Ty};
2426 auto *FnTy =
2427 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2428 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires");
2429 break;
2430 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00002431 case OMPRTL__tgt_register_lib: {
2432 // Build void __tgt_register_lib(__tgt_bin_desc *desc);
2433 QualType ParamTy =
2434 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
2435 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002436 auto *FnTy =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002437 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2438 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib");
2439 break;
2440 }
2441 case OMPRTL__tgt_unregister_lib: {
2442 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc);
2443 QualType ParamTy =
2444 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
2445 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002446 auto *FnTy =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002447 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2448 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib");
2449 break;
2450 }
Samuel Antaodf158d52016-04-27 22:58:19 +00002451 case OMPRTL__tgt_target_data_begin: {
George Rokos63bc9d62017-11-21 18:25:12 +00002452 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002453 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002454 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaodf158d52016-04-27 22:58:19 +00002455 CGM.Int32Ty,
2456 CGM.VoidPtrPtrTy,
2457 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002458 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002459 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002460 auto *FnTy =
Samuel Antaodf158d52016-04-27 22:58:19 +00002461 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2462 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin");
2463 break;
2464 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002465 case OMPRTL__tgt_target_data_begin_nowait: {
2466 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002467 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002468 // *arg_types);
2469 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2470 CGM.Int32Ty,
2471 CGM.VoidPtrPtrTy,
2472 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002473 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002474 CGM.Int64Ty->getPointerTo()};
2475 auto *FnTy =
2476 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2477 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait");
2478 break;
2479 }
Samuel Antaodf158d52016-04-27 22:58:19 +00002480 case OMPRTL__tgt_target_data_end: {
George Rokos63bc9d62017-11-21 18:25:12 +00002481 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002482 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002483 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaodf158d52016-04-27 22:58:19 +00002484 CGM.Int32Ty,
2485 CGM.VoidPtrPtrTy,
2486 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002487 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002488 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002489 auto *FnTy =
Samuel Antaodf158d52016-04-27 22:58:19 +00002490 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2491 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end");
2492 break;
2493 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002494 case OMPRTL__tgt_target_data_end_nowait: {
2495 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002496 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002497 // *arg_types);
2498 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2499 CGM.Int32Ty,
2500 CGM.VoidPtrPtrTy,
2501 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002502 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002503 CGM.Int64Ty->getPointerTo()};
2504 auto *FnTy =
2505 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2506 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait");
2507 break;
2508 }
Samuel Antao8d2d7302016-05-26 18:30:22 +00002509 case OMPRTL__tgt_target_data_update: {
George Rokos63bc9d62017-11-21 18:25:12 +00002510 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002511 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002512 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antao8d2d7302016-05-26 18:30:22 +00002513 CGM.Int32Ty,
2514 CGM.VoidPtrPtrTy,
2515 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002516 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002517 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002518 auto *FnTy =
Samuel Antao8d2d7302016-05-26 18:30:22 +00002519 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2520 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update");
2521 break;
2522 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002523 case OMPRTL__tgt_target_data_update_nowait: {
2524 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002525 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002526 // *arg_types);
2527 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2528 CGM.Int32Ty,
2529 CGM.VoidPtrPtrTy,
2530 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002531 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002532 CGM.Int64Ty->getPointerTo()};
2533 auto *FnTy =
2534 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2535 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait");
2536 break;
2537 }
Michael Krused47b9432019-08-05 18:43:21 +00002538 case OMPRTL__tgt_mapper_num_components: {
2539 // Build int64_t __tgt_mapper_num_components(void *rt_mapper_handle);
2540 llvm::Type *TypeParams[] = {CGM.VoidPtrTy};
2541 auto *FnTy =
2542 llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false);
2543 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_mapper_num_components");
2544 break;
2545 }
2546 case OMPRTL__tgt_push_mapper_component: {
2547 // Build void __tgt_push_mapper_component(void *rt_mapper_handle, void
2548 // *base, void *begin, int64_t size, int64_t type);
2549 llvm::Type *TypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.VoidPtrTy,
2550 CGM.Int64Ty, CGM.Int64Ty};
2551 auto *FnTy =
2552 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2553 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_push_mapper_component");
2554 break;
2555 }
Alexey Bataev9959db52014-05-06 10:08:46 +00002556 }
Alexey Bataev50b3c952016-02-19 10:38:26 +00002557 assert(RTLFn && "Unable to find OpenMP runtime function");
Alexey Bataev9959db52014-05-06 10:08:46 +00002558 return RTLFn;
2559}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00002560
James Y Knight9871db02019-02-05 16:42:33 +00002561llvm::FunctionCallee
2562CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman21212e42015-03-13 10:38:23 +00002563 assert((IVSize == 32 || IVSize == 64) &&
2564 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002565 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
2566 : "__kmpc_for_static_init_4u")
2567 : (IVSigned ? "__kmpc_for_static_init_8"
2568 : "__kmpc_for_static_init_8u");
2569 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
2570 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
Alexander Musman21212e42015-03-13 10:38:23 +00002571 llvm::Type *TypeParams[] = {
2572 getIdentTyPointerTy(), // loc
2573 CGM.Int32Ty, // tid
2574 CGM.Int32Ty, // schedtype
2575 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
2576 PtrTy, // p_lower
2577 PtrTy, // p_upper
2578 PtrTy, // p_stride
2579 ITy, // incr
2580 ITy // chunk
2581 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002582 auto *FnTy =
Alexander Musman21212e42015-03-13 10:38:23 +00002583 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2584 return CGM.CreateRuntimeFunction(FnTy, Name);
2585}
2586
James Y Knight9871db02019-02-05 16:42:33 +00002587llvm::FunctionCallee
2588CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002589 assert((IVSize == 32 || IVSize == 64) &&
2590 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002591 StringRef Name =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002592 IVSize == 32
2593 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
2594 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002595 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
Alexander Musman92bdaab2015-03-12 13:37:50 +00002596 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
2597 CGM.Int32Ty, // tid
2598 CGM.Int32Ty, // schedtype
2599 ITy, // lower
2600 ITy, // upper
2601 ITy, // stride
2602 ITy // chunk
2603 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002604 auto *FnTy =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002605 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2606 return CGM.CreateRuntimeFunction(FnTy, Name);
2607}
2608
James Y Knight9871db02019-02-05 16:42:33 +00002609llvm::FunctionCallee
2610CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002611 assert((IVSize == 32 || IVSize == 64) &&
2612 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002613 StringRef Name =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002614 IVSize == 32
2615 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
2616 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
2617 llvm::Type *TypeParams[] = {
2618 getIdentTyPointerTy(), // loc
2619 CGM.Int32Ty, // tid
2620 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002621 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002622 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2623 return CGM.CreateRuntimeFunction(FnTy, Name);
2624}
2625
James Y Knight9871db02019-02-05 16:42:33 +00002626llvm::FunctionCallee
2627CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002628 assert((IVSize == 32 || IVSize == 64) &&
2629 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002630 StringRef Name =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002631 IVSize == 32
2632 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
2633 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002634 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
2635 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002636 llvm::Type *TypeParams[] = {
2637 getIdentTyPointerTy(), // loc
2638 CGM.Int32Ty, // tid
2639 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
2640 PtrTy, // p_lower
2641 PtrTy, // p_upper
2642 PtrTy // p_stride
2643 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002644 auto *FnTy =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002645 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2646 return CGM.CreateRuntimeFunction(FnTy, Name);
2647}
2648
Gheorghe-Teodor Bercea625f59d2019-08-01 21:15:58 +00002649/// Obtain information that uniquely identifies a target entry. This
2650/// consists of the file and device IDs as well as line number associated with
2651/// the relevant entry source location.
2652static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
2653 unsigned &DeviceID, unsigned &FileID,
2654 unsigned &LineNum) {
2655 SourceManager &SM = C.getSourceManager();
2656
2657 // The loc should be always valid and have a file ID (the user cannot use
2658 // #pragma directives in macros)
2659
2660 assert(Loc.isValid() && "Source location is expected to be always valid.");
2661
2662 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
2663 assert(PLoc.isValid() && "Source location is expected to be always valid.");
2664
2665 llvm::sys::fs::UniqueID ID;
2666 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
2667 SM.getDiagnostics().Report(diag::err_cannot_open_file)
2668 << PLoc.getFilename() << EC.message();
2669
2670 DeviceID = ID.getDevice();
2671 FileID = ID.getFile();
2672 LineNum = PLoc.getLine();
2673}
2674
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002675Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) {
Alexey Bataev03f270c2018-03-30 18:31:07 +00002676 if (CGM.getLangOpts().OpenMPSimd)
2677 return Address::invalid();
Alexey Bataev92327c52018-03-26 16:40:55 +00002678 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00002679 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002680 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link ||
2681 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
2682 HasRequiresUnifiedSharedMemory))) {
Alexey Bataev92327c52018-03-26 16:40:55 +00002683 SmallString<64> PtrName;
2684 {
2685 llvm::raw_svector_ostream OS(PtrName);
Gheorghe-Teodor Bercea625f59d2019-08-01 21:15:58 +00002686 OS << CGM.getMangledName(GlobalDecl(VD));
2687 if (!VD->isExternallyVisible()) {
2688 unsigned DeviceID, FileID, Line;
2689 getTargetEntryUniqueInfo(CGM.getContext(),
2690 VD->getCanonicalDecl()->getBeginLoc(),
2691 DeviceID, FileID, Line);
2692 OS << llvm::format("_%x", FileID);
2693 }
2694 OS << "_decl_tgt_ref_ptr";
Alexey Bataev92327c52018-03-26 16:40:55 +00002695 }
2696 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName);
2697 if (!Ptr) {
2698 QualType PtrTy = CGM.getContext().getPointerType(VD->getType());
2699 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy),
2700 PtrName);
Gheorghe-Teodor Bercea625f59d2019-08-01 21:15:58 +00002701
2702 auto *GV = cast<llvm::GlobalVariable>(Ptr);
2703 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
2704
2705 if (!CGM.getLangOpts().OpenMPIsDevice)
Alexey Bataev03f270c2018-03-30 18:31:07 +00002706 GV->setInitializer(CGM.GetAddrOfGlobal(VD));
Alexey Bataev03f270c2018-03-30 18:31:07 +00002707 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr));
Alexey Bataev92327c52018-03-26 16:40:55 +00002708 }
2709 return Address(Ptr, CGM.getContext().getDeclAlign(VD));
2710 }
2711 return Address::invalid();
2712}
2713
Alexey Bataev97720002014-11-11 04:05:39 +00002714llvm::Constant *
2715CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002716 assert(!CGM.getLangOpts().OpenMPUseTLS ||
2717 !CGM.getContext().getTargetInfo().isTLSSupported());
Alexey Bataev97720002014-11-11 04:05:39 +00002718 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev18fa2322018-05-02 14:20:50 +00002719 std::string Suffix = getName({"cache", ""});
2720 return getOrCreateInternalVariable(
2721 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix));
Alexey Bataev97720002014-11-11 04:05:39 +00002722}
2723
John McCall7f416cc2015-09-08 08:05:57 +00002724Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
2725 const VarDecl *VD,
2726 Address VDAddr,
2727 SourceLocation Loc) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002728 if (CGM.getLangOpts().OpenMPUseTLS &&
2729 CGM.getContext().getTargetInfo().isTLSSupported())
2730 return VDAddr;
2731
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002732 llvm::Type *VarTy = VDAddr.getElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002733 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00002734 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
2735 CGM.Int8PtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00002736 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
2737 getOrCreateThreadPrivateCache(VD)};
John McCall7f416cc2015-09-08 08:05:57 +00002738 return Address(CGF.EmitRuntimeCall(
2739 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
2740 VDAddr.getAlignment());
Alexey Bataev97720002014-11-11 04:05:39 +00002741}
2742
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002743void CGOpenMPRuntime::emitThreadPrivateVarInit(
John McCall7f416cc2015-09-08 08:05:57 +00002744 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
Alexey Bataev97720002014-11-11 04:05:39 +00002745 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
2746 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
2747 // library.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002748 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002749 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +00002750 OMPLoc);
2751 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
2752 // to register constructor/destructor for variable.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002753 llvm::Value *Args[] = {
2754 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy),
2755 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +00002756 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002757 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +00002758}
2759
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002760llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
John McCall7f416cc2015-09-08 08:05:57 +00002761 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
Alexey Bataev97720002014-11-11 04:05:39 +00002762 bool PerformInit, CodeGenFunction *CGF) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002763 if (CGM.getLangOpts().OpenMPUseTLS &&
2764 CGM.getContext().getTargetInfo().isTLSSupported())
2765 return nullptr;
2766
Alexey Bataev97720002014-11-11 04:05:39 +00002767 VD = VD->getDefinition(CGM.getContext());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00002768 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) {
Alexey Bataev97720002014-11-11 04:05:39 +00002769 QualType ASTTy = VD->getType();
2770
2771 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002772 const Expr *Init = VD->getAnyInitializer();
Alexey Bataev97720002014-11-11 04:05:39 +00002773 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
2774 // Generate function that re-emits the declaration's initializer into the
2775 // threadprivate copy of the variable VD
2776 CodeGenFunction CtorCGF(CGM);
2777 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002778 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
2779 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
Alexey Bataev56223232017-06-09 13:40:18 +00002780 ImplicitParamDecl::Other);
Alexey Bataev97720002014-11-11 04:05:39 +00002781 Args.push_back(&Dst);
2782
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002783 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
John McCallc56a8b32016-03-11 04:30:31 +00002784 CGM.getContext().VoidPtrTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002785 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002786 std::string Name = getName({"__kmpc_global_ctor_", ""});
2787 llvm::Function *Fn =
2788 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002789 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002790 Args, Loc, Loc);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002791 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002792 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00002793 CGM.getContext().VoidPtrTy, Dst.getLocation());
John McCall7f416cc2015-09-08 08:05:57 +00002794 Address Arg = Address(ArgVal, VDAddr.getAlignment());
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002795 Arg = CtorCGF.Builder.CreateElementBitCast(
2796 Arg, CtorCGF.ConvertTypeForMem(ASTTy));
Alexey Bataev97720002014-11-11 04:05:39 +00002797 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
2798 /*IsInitializer=*/true);
2799 ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002800 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00002801 CGM.getContext().VoidPtrTy, Dst.getLocation());
2802 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
2803 CtorCGF.FinishFunction();
2804 Ctor = Fn;
2805 }
2806 if (VD->getType().isDestructedType() != QualType::DK_none) {
2807 // Generate function that emits destructor call for the threadprivate copy
2808 // of the variable VD
2809 CodeGenFunction DtorCGF(CGM);
2810 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002811 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
2812 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
Alexey Bataev56223232017-06-09 13:40:18 +00002813 ImplicitParamDecl::Other);
Alexey Bataev97720002014-11-11 04:05:39 +00002814 Args.push_back(&Dst);
2815
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002816 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
John McCallc56a8b32016-03-11 04:30:31 +00002817 CGM.getContext().VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002818 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002819 std::string Name = getName({"__kmpc_global_dtor_", ""});
2820 llvm::Function *Fn =
2821 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
Adrian Prantl1858c662016-04-24 22:22:29 +00002822 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
Alexey Bataev97720002014-11-11 04:05:39 +00002823 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002824 Loc, Loc);
Adrian Prantl1858c662016-04-24 22:22:29 +00002825 // Create a scope with an artificial location for the body of this function.
2826 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002827 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar(
Alexey Bataev97720002014-11-11 04:05:39 +00002828 DtorCGF.GetAddrOfLocalVar(&Dst),
John McCall7f416cc2015-09-08 08:05:57 +00002829 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
2830 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
Alexey Bataev97720002014-11-11 04:05:39 +00002831 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
2832 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
2833 DtorCGF.FinishFunction();
2834 Dtor = Fn;
2835 }
2836 // Do not emit init function if it is not required.
2837 if (!Ctor && !Dtor)
2838 return nullptr;
2839
2840 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002841 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
2842 /*isVarArg=*/false)
2843 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002844 // Copying constructor for the threadprivate variable.
2845 // Must be NULL - reserved by runtime, but currently it requires that this
2846 // parameter is always NULL. Otherwise it fires assertion.
2847 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
2848 if (Ctor == nullptr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002849 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
2850 /*isVarArg=*/false)
2851 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002852 Ctor = llvm::Constant::getNullValue(CtorTy);
2853 }
2854 if (Dtor == nullptr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002855 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
2856 /*isVarArg=*/false)
2857 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002858 Dtor = llvm::Constant::getNullValue(DtorTy);
2859 }
2860 if (!CGF) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002861 auto *InitFunctionTy =
Alexey Bataev97720002014-11-11 04:05:39 +00002862 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002863 std::string Name = getName({"__omp_threadprivate_init_", ""});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002864 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction(
Alexey Bataev18fa2322018-05-02 14:20:50 +00002865 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction());
Alexey Bataev97720002014-11-11 04:05:39 +00002866 CodeGenFunction InitCGF(CGM);
2867 FunctionArgList ArgList;
2868 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
2869 CGM.getTypes().arrangeNullaryFunction(), ArgList,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002870 Loc, Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002871 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002872 InitCGF.FinishFunction();
2873 return InitFunction;
2874 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002875 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002876 }
2877 return nullptr;
2878}
2879
Alexey Bataev34f8a702018-03-28 14:28:54 +00002880bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD,
2881 llvm::GlobalVariable *Addr,
2882 bool PerformInit) {
Alexey Bataev36724b72019-10-03 16:46:49 +00002883 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
2884 !CGM.getLangOpts().OpenMPIsDevice)
Alexey Bataev4db9dc62019-09-23 15:53:51 +00002885 return false;
Alexey Bataev34f8a702018-03-28 14:28:54 +00002886 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00002887 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002888 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
2889 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
2890 HasRequiresUnifiedSharedMemory))
Alexey Bataevd01b7492018-08-15 19:45:12 +00002891 return CGM.getLangOpts().OpenMPIsDevice;
Alexey Bataev34f8a702018-03-28 14:28:54 +00002892 VD = VD->getDefinition(CGM.getContext());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00002893 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second)
Alexey Bataev34f8a702018-03-28 14:28:54 +00002894 return CGM.getLangOpts().OpenMPIsDevice;
2895
2896 QualType ASTTy = VD->getType();
2897
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002898 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc();
Alexey Bataev34f8a702018-03-28 14:28:54 +00002899 // Produce the unique prefix to identify the new target regions. We use
2900 // the source location of the variable declaration which we know to not
2901 // conflict with any target region.
2902 unsigned DeviceID;
2903 unsigned FileID;
2904 unsigned Line;
2905 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line);
2906 SmallString<128> Buffer, Out;
2907 {
2908 llvm::raw_svector_ostream OS(Buffer);
2909 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID)
2910 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
2911 }
2912
2913 const Expr *Init = VD->getAnyInitializer();
2914 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
2915 llvm::Constant *Ctor;
2916 llvm::Constant *ID;
2917 if (CGM.getLangOpts().OpenMPIsDevice) {
2918 // Generate function that re-emits the declaration's initializer into
2919 // the threadprivate copy of the variable VD
2920 CodeGenFunction CtorCGF(CGM);
2921
2922 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2923 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2924 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
2925 FTy, Twine(Buffer, "_ctor"), FI, Loc);
2926 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF);
2927 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
2928 FunctionArgList(), Loc, Loc);
2929 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF);
2930 CtorCGF.EmitAnyExprToMem(Init,
2931 Address(Addr, CGM.getContext().getDeclAlign(VD)),
2932 Init->getType().getQualifiers(),
2933 /*IsInitializer=*/true);
2934 CtorCGF.FinishFunction();
2935 Ctor = Fn;
2936 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
Alexey Bataeve253f2f2018-05-09 14:15:18 +00002937 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor));
Alexey Bataev34f8a702018-03-28 14:28:54 +00002938 } else {
2939 Ctor = new llvm::GlobalVariable(
2940 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
2941 llvm::GlobalValue::PrivateLinkage,
2942 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor"));
2943 ID = Ctor;
2944 }
2945
2946 // Register the information for the entry associated with the constructor.
2947 Out.clear();
2948 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
2949 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor,
Alexey Bataev03f270c2018-03-30 18:31:07 +00002950 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor);
Alexey Bataev34f8a702018-03-28 14:28:54 +00002951 }
2952 if (VD->getType().isDestructedType() != QualType::DK_none) {
2953 llvm::Constant *Dtor;
2954 llvm::Constant *ID;
2955 if (CGM.getLangOpts().OpenMPIsDevice) {
2956 // Generate function that emits destructor call for the threadprivate
2957 // copy of the variable VD
2958 CodeGenFunction DtorCGF(CGM);
2959
2960 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2961 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2962 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
2963 FTy, Twine(Buffer, "_dtor"), FI, Loc);
2964 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
2965 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
2966 FunctionArgList(), Loc, Loc);
2967 // Create a scope with an artificial location for the body of this
2968 // function.
2969 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
2970 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)),
2971 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()),
2972 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
2973 DtorCGF.FinishFunction();
2974 Dtor = Fn;
2975 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
Alexey Bataeve253f2f2018-05-09 14:15:18 +00002976 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor));
Alexey Bataev34f8a702018-03-28 14:28:54 +00002977 } else {
2978 Dtor = new llvm::GlobalVariable(
2979 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
2980 llvm::GlobalValue::PrivateLinkage,
2981 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor"));
2982 ID = Dtor;
2983 }
2984 // Register the information for the entry associated with the destructor.
2985 Out.clear();
2986 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
2987 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor,
Alexey Bataev03f270c2018-03-30 18:31:07 +00002988 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor);
Alexey Bataev34f8a702018-03-28 14:28:54 +00002989 }
2990 return CGM.getLangOpts().OpenMPIsDevice;
2991}
2992
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002993Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
2994 QualType VarType,
2995 StringRef Name) {
Alexey Bataev18fa2322018-05-02 14:20:50 +00002996 std::string Suffix = getName({"artificial", ""});
2997 std::string CacheSuffix = getName({"cache", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002998 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002999 llvm::Value *GAddr =
3000 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003001 llvm::Value *Args[] = {
3002 emitUpdateLocation(CGF, SourceLocation()),
3003 getThreadID(CGF, SourceLocation()),
3004 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy),
3005 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00003006 /*isSigned=*/false),
Alexey Bataev18fa2322018-05-02 14:20:50 +00003007 getOrCreateInternalVariable(
3008 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))};
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003009 return Address(
3010 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3011 CGF.EmitRuntimeCall(
3012 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
3013 VarLVType->getPointerTo(/*AddrSpace=*/0)),
3014 CGM.getPointerAlign());
3015}
3016
Alexey Bataev1d943ae2019-11-19 12:12:23 -05003017void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond,
3018 const RegionCodeGenTy &ThenGen,
3019 const RegionCodeGenTy &ElseGen) {
Alexey Bataev1d677132015-04-22 13:57:31 +00003020 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
3021
3022 // If the condition constant folds and can be elided, try to avoid emitting
3023 // the condition and the dead arm of the if/else.
3024 bool CondConstant;
3025 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003026 if (CondConstant)
Alexey Bataev1d677132015-04-22 13:57:31 +00003027 ThenGen(CGF);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003028 else
Alexey Bataev1d677132015-04-22 13:57:31 +00003029 ElseGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00003030 return;
3031 }
3032
3033 // Otherwise, the condition did not fold, or we couldn't elide it. Just
3034 // emit the conditional branch.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003035 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then");
3036 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else");
3037 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end");
Alexey Bataev1d677132015-04-22 13:57:31 +00003038 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
3039
3040 // Emit the 'then' code.
3041 CGF.EmitBlock(ThenBlock);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003042 ThenGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00003043 CGF.EmitBranch(ContBlock);
3044 // Emit the 'else' code if present.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003045 // There is no need to emit line number for unconditional branch.
3046 (void)ApplyDebugLocation::CreateEmpty(CGF);
3047 CGF.EmitBlock(ElseBlock);
3048 ElseGen(CGF);
3049 // There is no need to emit line number for unconditional branch.
3050 (void)ApplyDebugLocation::CreateEmpty(CGF);
3051 CGF.EmitBranch(ContBlock);
Alexey Bataev1d677132015-04-22 13:57:31 +00003052 // Emit the continuation block for code after the if.
3053 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003054}
3055
Alexey Bataev1d677132015-04-22 13:57:31 +00003056void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00003057 llvm::Function *OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00003058 ArrayRef<llvm::Value *> CapturedVars,
Alexey Bataev1d677132015-04-22 13:57:31 +00003059 const Expr *IfCond) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003060 if (!CGF.HaveInsertPoint())
3061 return;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003062 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003063 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF,
3064 PrePostActionTy &) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00003065 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003066 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev2377fe92015-09-10 08:12:02 +00003067 llvm::Value *Args[] = {
3068 RTLoc,
3069 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003070 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())};
Alexey Bataev2377fe92015-09-10 08:12:02 +00003071 llvm::SmallVector<llvm::Value *, 16> RealArgs;
3072 RealArgs.append(std::begin(Args), std::end(Args));
3073 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
3074
James Y Knight9871db02019-02-05 16:42:33 +00003075 llvm::FunctionCallee RTLFn =
3076 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call);
Alexey Bataev2377fe92015-09-10 08:12:02 +00003077 CGF.EmitRuntimeCall(RTLFn, RealArgs);
3078 };
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003079 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF,
3080 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003081 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
3082 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc);
Alexey Bataev1d677132015-04-22 13:57:31 +00003083 // Build calls:
3084 // __kmpc_serialized_parallel(&Loc, GTid);
3085 llvm::Value *Args[] = {RTLoc, ThreadID};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003086 CGF.EmitRuntimeCall(
3087 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +00003088
Alexey Bataev3e0f4f82019-10-17 14:36:43 +00003089 // OutlinedFn(&GTid, &zero_bound, CapturedStruct);
3090 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc);
Alexey Bataevf89cf212019-10-16 16:59:01 +00003091 Address ZeroAddrBound =
3092 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty,
3093 /*Name=*/".bound.zero.addr");
3094 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0));
Alexey Bataev2377fe92015-09-10 08:12:02 +00003095 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
Alexey Bataev8521ff62018-07-25 20:03:01 +00003096 // ThreadId for serialized parallels is 0.
Alexey Bataev3e0f4f82019-10-17 14:36:43 +00003097 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
Alexey Bataevf89cf212019-10-16 16:59:01 +00003098 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer());
Alexey Bataev2377fe92015-09-10 08:12:02 +00003099 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
Alexey Bataev3c595a62017-08-14 15:01:03 +00003100 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +00003101
Alexey Bataev1d677132015-04-22 13:57:31 +00003102 // __kmpc_end_serialized_parallel(&Loc, GTid);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003103 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID};
Alexey Bataev1d677132015-04-22 13:57:31 +00003104 CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003105 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel),
3106 EndArgs);
Alexey Bataev1d677132015-04-22 13:57:31 +00003107 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003108 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -05003109 emitIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003110 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003111 RegionCodeGenTy ThenRCG(ThenGen);
3112 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00003113 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00003114}
3115
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00003116// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +00003117// thread-ID variable (it is passed in a first argument of the outlined function
3118// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
3119// regular serial code region, get thread ID by calling kmp_int32
3120// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
3121// return the address of that temp.
John McCall7f416cc2015-09-08 08:05:57 +00003122Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
3123 SourceLocation Loc) {
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003124 if (auto *OMPRegionInfo =
Alexey Bataevd74d0602014-10-13 06:02:40 +00003125 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003126 if (OMPRegionInfo->getThreadIDVariable())
Akira Hatanakaf139ae32019-12-03 15:17:01 -08003127 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003128
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003129 llvm::Value *ThreadID = getThreadID(CGF, Loc);
3130 QualType Int32Ty =
Alexey Bataevd74d0602014-10-13 06:02:40 +00003131 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003132 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
Alexey Bataevd74d0602014-10-13 06:02:40 +00003133 CGF.EmitStoreOfScalar(ThreadID,
John McCall7f416cc2015-09-08 08:05:57 +00003134 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
Alexey Bataevd74d0602014-10-13 06:02:40 +00003135
3136 return ThreadIDTemp;
3137}
3138
Alexey Bataev1af5bd52019-03-05 17:47:18 +00003139llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable(
3140 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003141 SmallString<256> Buffer;
3142 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00003143 Out << Name;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003144 StringRef RuntimeName = Out.str();
Alexey Bataev43a919f2018-04-13 17:48:43 +00003145 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first;
David Blaikie13156b62014-11-19 03:06:06 +00003146 if (Elem.second) {
3147 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00003148 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00003149 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00003150 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003151
David Blaikie13156b62014-11-19 03:06:06 +00003152 return Elem.second = new llvm::GlobalVariable(
3153 CGM.getModule(), Ty, /*IsConstant*/ false,
3154 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
Alexey Bataev1af5bd52019-03-05 17:47:18 +00003155 Elem.first(), /*InsertBefore=*/nullptr,
3156 llvm::GlobalValue::NotThreadLocal, AddressSpace);
Alexey Bataev97720002014-11-11 04:05:39 +00003157}
3158
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003159llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev18fa2322018-05-02 14:20:50 +00003160 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str();
3161 std::string Name = getName({Prefix, "var"});
3162 return getOrCreateInternalVariable(KmpCriticalNameTy, Name);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003163}
3164
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003165namespace {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003166/// Common pre(post)-action for different OpenMP constructs.
3167class CommonActionTy final : public PrePostActionTy {
James Y Knight9871db02019-02-05 16:42:33 +00003168 llvm::FunctionCallee EnterCallee;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003169 ArrayRef<llvm::Value *> EnterArgs;
James Y Knight9871db02019-02-05 16:42:33 +00003170 llvm::FunctionCallee ExitCallee;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003171 ArrayRef<llvm::Value *> ExitArgs;
3172 bool Conditional;
3173 llvm::BasicBlock *ContBlock = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003174
3175public:
James Y Knight9871db02019-02-05 16:42:33 +00003176 CommonActionTy(llvm::FunctionCallee EnterCallee,
3177 ArrayRef<llvm::Value *> EnterArgs,
3178 llvm::FunctionCallee ExitCallee,
3179 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003180 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
3181 ExitArgs(ExitArgs), Conditional(Conditional) {}
3182 void Enter(CodeGenFunction &CGF) override {
3183 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs);
3184 if (Conditional) {
3185 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes);
3186 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
3187 ContBlock = CGF.createBasicBlock("omp_if.end");
3188 // Generate the branch (If-stmt)
3189 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
3190 CGF.EmitBlock(ThenBlock);
3191 }
Alexey Bataeva744ff52015-05-05 09:24:37 +00003192 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003193 void Done(CodeGenFunction &CGF) {
3194 // Emit the rest of blocks/branches
3195 CGF.EmitBranch(ContBlock);
3196 CGF.EmitBlock(ContBlock, true);
3197 }
3198 void Exit(CodeGenFunction &CGF) override {
3199 CGF.EmitRuntimeCall(ExitCallee, ExitArgs);
Alexey Bataev3e6124b2015-04-10 07:48:12 +00003200 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003201};
Hans Wennborg7eb54642015-09-10 17:07:54 +00003202} // anonymous namespace
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003203
3204void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
3205 StringRef CriticalName,
3206 const RegionCodeGenTy &CriticalOpGen,
Alexey Bataevfc57d162015-12-15 10:55:09 +00003207 SourceLocation Loc, const Expr *Hint) {
3208 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
Alexey Bataev75ddfab2014-12-01 11:32:38 +00003209 // CriticalOpGen();
3210 // __kmpc_end_critical(ident_t *, gtid, Lock);
3211 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev8ef31412015-12-18 07:58:25 +00003212 if (!CGF.HaveInsertPoint())
3213 return;
Alexey Bataevfc57d162015-12-15 10:55:09 +00003214 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3215 getCriticalRegionLock(CriticalName)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003216 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args),
3217 std::end(Args));
Alexey Bataevfc57d162015-12-15 10:55:09 +00003218 if (Hint) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003219 EnterArgs.push_back(CGF.Builder.CreateIntCast(
3220 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false));
3221 }
3222 CommonActionTy Action(
3223 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint
3224 : OMPRTL__kmpc_critical),
3225 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args);
3226 CriticalOpGen.setAction(Action);
Alexey Bataevfc57d162015-12-15 10:55:09 +00003227 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003228}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003229
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003230void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003231 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003232 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003233 if (!CGF.HaveInsertPoint())
3234 return;
Alexey Bataev8d690652014-12-04 07:23:53 +00003235 // if(__kmpc_master(ident_t *, gtid)) {
3236 // MasterOpGen();
3237 // __kmpc_end_master(ident_t *, gtid);
3238 // }
3239 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00003240 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003241 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args,
3242 createRuntimeFunction(OMPRTL__kmpc_end_master), Args,
3243 /*Conditional=*/true);
3244 MasterOpGen.setAction(Action);
3245 emitInlinedDirective(CGF, OMPD_master, MasterOpGen);
3246 Action.Done(CGF);
Alexey Bataev8d690652014-12-04 07:23:53 +00003247}
3248
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003249void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
3250 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003251 if (!CGF.HaveInsertPoint())
3252 return;
Alexey Bataev9f797f32015-02-05 05:57:51 +00003253 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
3254 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003255 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00003256 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003257 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00003258 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
3259 Region->emitUntiedSwitch(CGF);
Alexey Bataev9f797f32015-02-05 05:57:51 +00003260}
3261
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003262void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
3263 const RegionCodeGenTy &TaskgroupOpGen,
3264 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003265 if (!CGF.HaveInsertPoint())
3266 return;
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003267 // __kmpc_taskgroup(ident_t *, gtid);
3268 // TaskgroupOpGen();
3269 // __kmpc_end_taskgroup(ident_t *, gtid);
3270 // Prepare arguments and build a call to __kmpc_taskgroup
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003271 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
3272 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args,
3273 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
3274 Args);
3275 TaskgroupOpGen.setAction(Action);
3276 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003277}
3278
John McCall7f416cc2015-09-08 08:05:57 +00003279/// Given an array of pointers to variables, project the address of a
3280/// given variable.
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003281static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
3282 unsigned Index, const VarDecl *Var) {
John McCall7f416cc2015-09-08 08:05:57 +00003283 // Pull out the pointer to the variable.
James Y Knight751fe282019-02-09 22:22:28 +00003284 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index);
John McCall7f416cc2015-09-08 08:05:57 +00003285 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
3286
3287 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003288 Addr = CGF.Builder.CreateElementBitCast(
3289 Addr, CGF.ConvertTypeForMem(Var->getType()));
John McCall7f416cc2015-09-08 08:05:57 +00003290 return Addr;
3291}
3292
Alexey Bataeva63048e2015-03-23 06:18:07 +00003293static llvm::Value *emitCopyprivateCopyFunction(
Alexey Bataev420d45b2015-04-14 05:11:24 +00003294 CodeGenModule &CGM, llvm::Type *ArgsType,
3295 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003296 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps,
3297 SourceLocation Loc) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003298 ASTContext &C = CGM.getContext();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003299 // void copy_func(void *LHSArg, void *RHSArg);
3300 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003301 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3302 ImplicitParamDecl::Other);
3303 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3304 ImplicitParamDecl::Other);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003305 Args.push_back(&LHSArg);
3306 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003307 const auto &CGFI =
3308 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00003309 std::string Name =
3310 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"});
3311 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
3312 llvm::GlobalValue::InternalLinkage, Name,
3313 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00003314 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00003315 Fn->setDoesNotRecurse();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003316 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003317 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev420d45b2015-04-14 05:11:24 +00003318 // Dest = (void*[n])(LHSArg);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003319 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00003320 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3321 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
3322 ArgsType), CGF.getPointerAlign());
3323 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3324 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
3325 ArgsType), CGF.getPointerAlign());
Alexey Bataeva63048e2015-03-23 06:18:07 +00003326 // *(Type0*)Dst[0] = *(Type0*)Src[0];
3327 // *(Type1*)Dst[1] = *(Type1*)Src[1];
3328 // ...
3329 // *(Typen*)Dst[n] = *(Typen*)Src[n];
Alexey Bataeva63048e2015-03-23 06:18:07 +00003330 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003331 const auto *DestVar =
3332 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +00003333 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
3334
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003335 const auto *SrcVar =
3336 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +00003337 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
3338
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003339 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003340 QualType Type = VD->getType();
John McCall7f416cc2015-09-08 08:05:57 +00003341 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003342 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00003343 CGF.FinishFunction();
3344 return Fn;
3345}
3346
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003347void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003348 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00003349 SourceLocation Loc,
3350 ArrayRef<const Expr *> CopyprivateVars,
3351 ArrayRef<const Expr *> SrcExprs,
3352 ArrayRef<const Expr *> DstExprs,
3353 ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003354 if (!CGF.HaveInsertPoint())
3355 return;
Alexey Bataeva63048e2015-03-23 06:18:07 +00003356 assert(CopyprivateVars.size() == SrcExprs.size() &&
3357 CopyprivateVars.size() == DstExprs.size() &&
3358 CopyprivateVars.size() == AssignmentOps.size());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003359 ASTContext &C = CGM.getContext();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003360 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003361 // if(__kmpc_single(ident_t *, gtid)) {
3362 // SingleOpGen();
3363 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003364 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003365 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00003366 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3367 // <copy_func>, did_it);
3368
John McCall7f416cc2015-09-08 08:05:57 +00003369 Address DidIt = Address::invalid();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003370 if (!CopyprivateVars.empty()) {
3371 // int32 did_it = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003372 QualType KmpInt32Ty =
3373 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003374 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
John McCall7f416cc2015-09-08 08:05:57 +00003375 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003376 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003377 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00003378 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003379 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args,
3380 createRuntimeFunction(OMPRTL__kmpc_end_single), Args,
3381 /*Conditional=*/true);
3382 SingleOpGen.setAction(Action);
3383 emitInlinedDirective(CGF, OMPD_single, SingleOpGen);
3384 if (DidIt.isValid()) {
3385 // did_it = 1;
3386 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
3387 }
3388 Action.Done(CGF);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003389 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3390 // <copy_func>, did_it);
John McCall7f416cc2015-09-08 08:05:57 +00003391 if (DidIt.isValid()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00003392 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
Richard Smith772e2662019-10-04 01:25:59 +00003393 QualType CopyprivateArrayTy = C.getConstantArrayType(
3394 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
3395 /*IndexTypeQuals=*/0);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003396 // Create a list of all private variables for copyprivate.
John McCall7f416cc2015-09-08 08:05:57 +00003397 Address CopyprivateList =
Alexey Bataeva63048e2015-03-23 06:18:07 +00003398 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
3399 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +00003400 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I);
John McCall7f416cc2015-09-08 08:05:57 +00003401 CGF.Builder.CreateStore(
Alexey Bataeva63048e2015-03-23 06:18:07 +00003402 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08003403 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF),
3404 CGF.VoidPtrTy),
John McCall7f416cc2015-09-08 08:05:57 +00003405 Elem);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003406 }
3407 // Build function that copies private values from single region to all other
3408 // threads in the corresponding parallel region.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003409 llvm::Value *CpyFn = emitCopyprivateCopyFunction(
Alexey Bataeva63048e2015-03-23 06:18:07 +00003410 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003411 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003412 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00003413 Address CL =
3414 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
3415 CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003416 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003417 llvm::Value *Args[] = {
3418 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
3419 getThreadID(CGF, Loc), // i32 <gtid>
Alexey Bataev66beaa92015-04-30 03:47:32 +00003420 BufSize, // size_t <buf_size>
John McCall7f416cc2015-09-08 08:05:57 +00003421 CL.getPointer(), // void *<copyprivate list>
Alexey Bataeva63048e2015-03-23 06:18:07 +00003422 CpyFn, // void (*) (void *, void *) <copy_func>
3423 DidItVal // i32 did_it
3424 };
3425 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
3426 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003427}
3428
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003429void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
3430 const RegionCodeGenTy &OrderedOpGen,
Alexey Bataev5f600d62015-09-29 03:48:57 +00003431 SourceLocation Loc, bool IsThreads) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003432 if (!CGF.HaveInsertPoint())
3433 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003434 // __kmpc_ordered(ident_t *, gtid);
3435 // OrderedOpGen();
3436 // __kmpc_end_ordered(ident_t *, gtid);
3437 // Prepare arguments and build a call to __kmpc_ordered
Alexey Bataev5f600d62015-09-29 03:48:57 +00003438 if (IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003439 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003440 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args,
3441 createRuntimeFunction(OMPRTL__kmpc_end_ordered),
3442 Args);
3443 OrderedOpGen.setAction(Action);
3444 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
3445 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003446 }
Alexey Bataev5f600d62015-09-29 03:48:57 +00003447 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003448}
3449
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003450unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) {
Alexey Bataev50b3c952016-02-19 10:38:26 +00003451 unsigned Flags;
3452 if (Kind == OMPD_for)
3453 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
3454 else if (Kind == OMPD_sections)
3455 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
3456 else if (Kind == OMPD_single)
3457 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
3458 else if (Kind == OMPD_barrier)
3459 Flags = OMP_IDENT_BARRIER_EXPL;
3460 else
3461 Flags = OMP_IDENT_BARRIER_IMPL;
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003462 return Flags;
3463}
3464
Alexey Bataevf6a53d62019-03-18 18:40:00 +00003465void CGOpenMPRuntime::getDefaultScheduleAndChunk(
3466 CodeGenFunction &CGF, const OMPLoopDirective &S,
3467 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const {
3468 // Check if the loop directive is actually a doacross loop directive. In this
3469 // case choose static, 1 schedule.
3470 if (llvm::any_of(
3471 S.getClausesOfKind<OMPOrderedClause>(),
3472 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) {
3473 ScheduleKind = OMPC_SCHEDULE_static;
3474 // Chunk size is 1 in this case.
3475 llvm::APInt ChunkSize(32, 1);
3476 ChunkExpr = IntegerLiteral::Create(
3477 CGF.getContext(), ChunkSize,
3478 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
3479 SourceLocation());
3480 }
3481}
3482
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003483void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
3484 OpenMPDirectiveKind Kind, bool EmitChecks,
3485 bool ForceSimpleCall) {
Johannes Doerfertb3c06db2019-11-04 23:00:36 -06003486 // Check if we should use the OMPBuilder
3487 auto *OMPRegionInfo =
3488 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo);
3489 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder();
3490 if (OMPBuilder) {
3491 // TODO: Move cancelation point handling into the IRBuilder.
3492 if (EmitChecks && !ForceSimpleCall && OMPRegionInfo &&
3493 OMPRegionInfo->hasCancel() && CGF.Builder.GetInsertBlock()) {
3494 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
3495 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(
3496 ".cancel.exit", CGF.Builder.GetInsertBlock()->getParent());
3497 OMPBuilder->setCancellationBlock(ExitBB);
3498 CGF.Builder.SetInsertPoint(ExitBB);
3499 CodeGenFunction::JumpDest CancelDestination =
3500 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
3501 CGF.EmitBranchThroughCleanup(CancelDestination);
3502 }
3503 auto IP = OMPBuilder->CreateBarrier(CGF.Builder, Kind, ForceSimpleCall,
3504 EmitChecks);
3505 CGF.Builder.restoreIP(IP);
3506 return;
3507 }
3508
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003509 if (!CGF.HaveInsertPoint())
3510 return;
3511 // Build call __kmpc_cancel_barrier(loc, thread_id);
3512 // Build call __kmpc_barrier(loc, thread_id);
3513 unsigned Flags = getDefaultFlagsForBarriers(Kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003514 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
3515 // thread_id);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003516 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
3517 getThreadID(CGF, Loc)};
Johannes Doerfertb3c06db2019-11-04 23:00:36 -06003518 if (OMPRegionInfo) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00003519 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003520 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003521 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev25e5b442015-09-15 12:52:43 +00003522 if (EmitChecks) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003523 // if (__kmpc_cancel_barrier()) {
3524 // exit from construct;
3525 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003526 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
3527 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
3528 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003529 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
3530 CGF.EmitBlock(ExitBB);
3531 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003532 CodeGenFunction::JumpDest CancelDestination =
Alexey Bataev25e5b442015-09-15 12:52:43 +00003533 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003534 CGF.EmitBranchThroughCleanup(CancelDestination);
3535 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
3536 }
3537 return;
3538 }
3539 }
3540 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003541}
3542
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003543/// Map the OpenMP loop schedule to the runtime enumeration.
Alexander Musmanc6388682014-12-15 07:07:06 +00003544static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003545 bool Chunked, bool Ordered) {
Alexander Musmanc6388682014-12-15 07:07:06 +00003546 switch (ScheduleKind) {
3547 case OMPC_SCHEDULE_static:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003548 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
3549 : (Ordered ? OMP_ord_static : OMP_sch_static);
Alexander Musmanc6388682014-12-15 07:07:06 +00003550 case OMPC_SCHEDULE_dynamic:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003551 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00003552 case OMPC_SCHEDULE_guided:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003553 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00003554 case OMPC_SCHEDULE_runtime:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003555 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
3556 case OMPC_SCHEDULE_auto:
3557 return Ordered ? OMP_ord_auto : OMP_sch_auto;
Alexander Musmanc6388682014-12-15 07:07:06 +00003558 case OMPC_SCHEDULE_unknown:
3559 assert(!Chunked && "chunk was specified but schedule kind not known");
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003560 return Ordered ? OMP_ord_static : OMP_sch_static;
Alexander Musmanc6388682014-12-15 07:07:06 +00003561 }
3562 llvm_unreachable("Unexpected runtime schedule");
3563}
3564
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003565/// Map the OpenMP distribute schedule to the runtime enumeration.
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003566static OpenMPSchedType
3567getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
3568 // only static is allowed for dist_schedule
3569 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
3570}
3571
Alexander Musmanc6388682014-12-15 07:07:06 +00003572bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
3573 bool Chunked) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003574 OpenMPSchedType Schedule =
3575 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
Alexander Musmanc6388682014-12-15 07:07:06 +00003576 return Schedule == OMP_sch_static;
3577}
3578
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003579bool CGOpenMPRuntime::isStaticNonchunked(
3580 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003581 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003582 return Schedule == OMP_dist_sch_static;
3583}
3584
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00003585bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind,
3586 bool Chunked) const {
3587 OpenMPSchedType Schedule =
3588 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
3589 return Schedule == OMP_sch_static_chunked;
3590}
3591
3592bool CGOpenMPRuntime::isStaticChunked(
3593 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
3594 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
3595 return Schedule == OMP_dist_sch_static_chunked;
3596}
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003597
Alexander Musmandf7a8e22015-01-22 08:49:35 +00003598bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003599 OpenMPSchedType Schedule =
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003600 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00003601 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
3602 return Schedule != OMP_sch_static;
3603}
3604
Alexey Bataev07a3b592019-08-23 19:52:05 +00003605static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003606 OpenMPScheduleClauseModifier M1,
3607 OpenMPScheduleClauseModifier M2) {
Alexey Bataev6cff6242016-05-30 13:05:14 +00003608 int Modifier = 0;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003609 switch (M1) {
3610 case OMPC_SCHEDULE_MODIFIER_monotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003611 Modifier = OMP_sch_modifier_monotonic;
3612 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003613 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003614 Modifier = OMP_sch_modifier_nonmonotonic;
3615 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003616 case OMPC_SCHEDULE_MODIFIER_simd:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003617 if (Schedule == OMP_sch_static_chunked)
3618 Schedule = OMP_sch_static_balanced_chunked;
3619 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003620 case OMPC_SCHEDULE_MODIFIER_last:
3621 case OMPC_SCHEDULE_MODIFIER_unknown:
3622 break;
3623 }
3624 switch (M2) {
3625 case OMPC_SCHEDULE_MODIFIER_monotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003626 Modifier = OMP_sch_modifier_monotonic;
3627 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003628 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003629 Modifier = OMP_sch_modifier_nonmonotonic;
3630 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003631 case OMPC_SCHEDULE_MODIFIER_simd:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003632 if (Schedule == OMP_sch_static_chunked)
3633 Schedule = OMP_sch_static_balanced_chunked;
3634 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003635 case OMPC_SCHEDULE_MODIFIER_last:
3636 case OMPC_SCHEDULE_MODIFIER_unknown:
3637 break;
3638 }
Alexey Bataev07a3b592019-08-23 19:52:05 +00003639 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription.
3640 // If the static schedule kind is specified or if the ordered clause is
3641 // specified, and if the nonmonotonic modifier is not specified, the effect is
3642 // as if the monotonic modifier is specified. Otherwise, unless the monotonic
3643 // modifier is specified, the effect is as if the nonmonotonic modifier is
3644 // specified.
3645 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) {
3646 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
3647 Schedule == OMP_sch_static_balanced_chunked ||
Alexey Bataevc3eded02019-11-18 11:13:08 -05003648 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
3649 Schedule == OMP_dist_sch_static_chunked ||
3650 Schedule == OMP_dist_sch_static))
Alexey Bataev07a3b592019-08-23 19:52:05 +00003651 Modifier = OMP_sch_modifier_nonmonotonic;
3652 }
Alexey Bataev6cff6242016-05-30 13:05:14 +00003653 return Schedule | Modifier;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003654}
3655
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003656void CGOpenMPRuntime::emitForDispatchInit(
3657 CodeGenFunction &CGF, SourceLocation Loc,
3658 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
3659 bool Ordered, const DispatchRTInput &DispatchValues) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003660 if (!CGF.HaveInsertPoint())
3661 return;
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003662 OpenMPSchedType Schedule = getRuntimeSchedule(
3663 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered);
John McCall7f416cc2015-09-08 08:05:57 +00003664 assert(Ordered ||
3665 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
Alexey Bataev6cff6242016-05-30 13:05:14 +00003666 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
3667 Schedule != OMP_sch_static_balanced_chunked));
John McCall7f416cc2015-09-08 08:05:57 +00003668 // Call __kmpc_dispatch_init(
3669 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
3670 // kmp_int[32|64] lower, kmp_int[32|64] upper,
3671 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00003672
John McCall7f416cc2015-09-08 08:05:57 +00003673 // If the Chunk was not specified in the clause - use default value 1.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003674 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk
3675 : CGF.Builder.getIntN(IVSize, 1);
John McCall7f416cc2015-09-08 08:05:57 +00003676 llvm::Value *Args[] = {
Alexey Bataev07a3b592019-08-23 19:52:05 +00003677 emitUpdateLocation(CGF, Loc),
3678 getThreadID(CGF, Loc),
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003679 CGF.Builder.getInt32(addMonoNonMonoModifier(
Alexey Bataev07a3b592019-08-23 19:52:05 +00003680 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type
3681 DispatchValues.LB, // Lower
3682 DispatchValues.UB, // Upper
3683 CGF.Builder.getIntN(IVSize, 1), // Stride
3684 Chunk // Chunk
John McCall7f416cc2015-09-08 08:05:57 +00003685 };
3686 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
3687}
3688
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003689static void emitForStaticInitCall(
3690 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
James Y Knight9871db02019-02-05 16:42:33 +00003691 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003692 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003693 const CGOpenMPRuntime::StaticRTInput &Values) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003694 if (!CGF.HaveInsertPoint())
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003695 return;
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003696
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003697 assert(!Values.Ordered);
3698 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
3699 Schedule == OMP_sch_static_balanced_chunked ||
3700 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
3701 Schedule == OMP_dist_sch_static ||
3702 Schedule == OMP_dist_sch_static_chunked);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003703
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003704 // Call __kmpc_for_static_init(
3705 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
3706 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
3707 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
3708 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
3709 llvm::Value *Chunk = Values.Chunk;
3710 if (Chunk == nullptr) {
3711 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
3712 Schedule == OMP_dist_sch_static) &&
3713 "expected static non-chunked schedule");
3714 // If the Chunk was not specified in the clause - use default value 1.
3715 Chunk = CGF.Builder.getIntN(Values.IVSize, 1);
3716 } else {
3717 assert((Schedule == OMP_sch_static_chunked ||
3718 Schedule == OMP_sch_static_balanced_chunked ||
3719 Schedule == OMP_ord_static_chunked ||
3720 Schedule == OMP_dist_sch_static_chunked) &&
3721 "expected static chunked schedule");
3722 }
3723 llvm::Value *Args[] = {
3724 UpdateLocation,
3725 ThreadId,
Alexey Bataev07a3b592019-08-23 19:52:05 +00003726 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003727 M2)), // Schedule type
3728 Values.IL.getPointer(), // &isLastIter
3729 Values.LB.getPointer(), // &LB
3730 Values.UB.getPointer(), // &UB
3731 Values.ST.getPointer(), // &Stride
3732 CGF.Builder.getIntN(Values.IVSize, 1), // Incr
3733 Chunk // Chunk
3734 };
3735 CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003736}
3737
John McCall7f416cc2015-09-08 08:05:57 +00003738void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
3739 SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003740 OpenMPDirectiveKind DKind,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003741 const OpenMPScheduleTy &ScheduleKind,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003742 const StaticRTInput &Values) {
3743 OpenMPSchedType ScheduleNum = getRuntimeSchedule(
3744 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered);
3745 assert(isOpenMPWorksharingDirective(DKind) &&
3746 "Expected loop-based or sections-based directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003747 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003748 isOpenMPLoopDirective(DKind)
3749 ? OMP_IDENT_WORK_LOOP
3750 : OMP_IDENT_WORK_SECTIONS);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003751 llvm::Value *ThreadId = getThreadID(CGF, Loc);
James Y Knight9871db02019-02-05 16:42:33 +00003752 llvm::FunctionCallee StaticInitFunction =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003753 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003754 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003755 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003756}
John McCall7f416cc2015-09-08 08:05:57 +00003757
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003758void CGOpenMPRuntime::emitDistributeStaticInit(
3759 CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003760 OpenMPDistScheduleClauseKind SchedKind,
3761 const CGOpenMPRuntime::StaticRTInput &Values) {
3762 OpenMPSchedType ScheduleNum =
3763 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003764 llvm::Value *UpdatedLocation =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003765 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003766 llvm::Value *ThreadId = getThreadID(CGF, Loc);
James Y Knight9871db02019-02-05 16:42:33 +00003767 llvm::FunctionCallee StaticInitFunction =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003768 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003769 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
3770 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003771 OMPC_SCHEDULE_MODIFIER_unknown, Values);
Alexander Musmanc6388682014-12-15 07:07:06 +00003772}
3773
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003774void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
Alexey Bataevf43f7142017-09-06 16:17:35 +00003775 SourceLocation Loc,
3776 OpenMPDirectiveKind DKind) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003777 if (!CGF.HaveInsertPoint())
3778 return;
Alexander Musmanc6388682014-12-15 07:07:06 +00003779 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataevf43f7142017-09-06 16:17:35 +00003780 llvm::Value *Args[] = {
3781 emitUpdateLocation(CGF, Loc,
3782 isOpenMPDistributeDirective(DKind)
3783 ? OMP_IDENT_WORK_DISTRIBUTE
3784 : isOpenMPLoopDirective(DKind)
3785 ? OMP_IDENT_WORK_LOOP
3786 : OMP_IDENT_WORK_SECTIONS),
3787 getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003788 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
3789 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00003790}
3791
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003792void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
3793 SourceLocation Loc,
3794 unsigned IVSize,
3795 bool IVSigned) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003796 if (!CGF.HaveInsertPoint())
3797 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003798 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00003799 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003800 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
3801}
3802
Alexander Musman92bdaab2015-03-12 13:37:50 +00003803llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
3804 SourceLocation Loc, unsigned IVSize,
John McCall7f416cc2015-09-08 08:05:57 +00003805 bool IVSigned, Address IL,
3806 Address LB, Address UB,
3807 Address ST) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00003808 // Call __kmpc_dispatch_next(
3809 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
3810 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
3811 // kmp_int[32|64] *p_stride);
3812 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00003813 emitUpdateLocation(CGF, Loc),
3814 getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00003815 IL.getPointer(), // &isLastIter
3816 LB.getPointer(), // &Lower
3817 UB.getPointer(), // &Upper
3818 ST.getPointer() // &Stride
Alexander Musman92bdaab2015-03-12 13:37:50 +00003819 };
3820 llvm::Value *Call =
3821 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
3822 return CGF.EmitScalarConversion(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003823 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00003824 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00003825}
3826
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003827void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
3828 llvm::Value *NumThreads,
3829 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003830 if (!CGF.HaveInsertPoint())
3831 return;
Alexey Bataevb2059782014-10-13 08:23:51 +00003832 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
3833 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003834 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00003835 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003836 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
3837 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00003838}
3839
Alexey Bataev7f210c62015-06-18 13:40:03 +00003840void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
3841 OpenMPProcBindClauseKind ProcBind,
3842 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003843 if (!CGF.HaveInsertPoint())
3844 return;
Alexey Bataev7f210c62015-06-18 13:40:03 +00003845 // Constants for proc bind value accepted by the runtime.
3846 enum ProcBindTy {
3847 ProcBindFalse = 0,
3848 ProcBindTrue,
3849 ProcBindMaster,
3850 ProcBindClose,
3851 ProcBindSpread,
3852 ProcBindIntel,
3853 ProcBindDefault
3854 } RuntimeProcBind;
3855 switch (ProcBind) {
3856 case OMPC_PROC_BIND_master:
3857 RuntimeProcBind = ProcBindMaster;
3858 break;
3859 case OMPC_PROC_BIND_close:
3860 RuntimeProcBind = ProcBindClose;
3861 break;
3862 case OMPC_PROC_BIND_spread:
3863 RuntimeProcBind = ProcBindSpread;
3864 break;
3865 case OMPC_PROC_BIND_unknown:
3866 llvm_unreachable("Unsupported proc_bind value.");
3867 }
3868 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
3869 llvm::Value *Args[] = {
3870 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3871 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
3872 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
3873}
3874
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003875void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
3876 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003877 if (!CGF.HaveInsertPoint())
3878 return;
Alexey Bataevd76df6d2015-02-24 12:55:09 +00003879 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003880 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
3881 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00003882}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003883
Alexey Bataev62b63b12015-03-10 07:28:44 +00003884namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003885/// Indexes of fields for type kmp_task_t.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003886enum KmpTaskTFields {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003887 /// List of shared variables.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003888 KmpTaskTShareds,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003889 /// Task routine.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003890 KmpTaskTRoutine,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003891 /// Partition id for the untied tasks.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003892 KmpTaskTPartId,
Alexey Bataevad537bb2016-05-30 09:06:50 +00003893 /// Function with call of destructors for private variables.
3894 Data1,
3895 /// Task priority.
3896 Data2,
Alexey Bataev7292c292016-04-25 12:22:29 +00003897 /// (Taskloops only) Lower bound.
3898 KmpTaskTLowerBound,
3899 /// (Taskloops only) Upper bound.
3900 KmpTaskTUpperBound,
3901 /// (Taskloops only) Stride.
3902 KmpTaskTStride,
3903 /// (Taskloops only) Is last iteration flag.
3904 KmpTaskTLastIter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003905 /// (Taskloops only) Reduction data.
3906 KmpTaskTReductions,
Alexey Bataev62b63b12015-03-10 07:28:44 +00003907};
Hans Wennborg7eb54642015-09-10 17:07:54 +00003908} // anonymous namespace
Alexey Bataev62b63b12015-03-10 07:28:44 +00003909
Samuel Antaoee8fb302016-01-06 13:42:12 +00003910bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003911 return OffloadEntriesTargetRegion.empty() &&
3912 OffloadEntriesDeviceGlobalVar.empty();
Samuel Antaoee8fb302016-01-06 13:42:12 +00003913}
3914
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003915/// Initialize target region entry.
Samuel Antaoee8fb302016-01-06 13:42:12 +00003916void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3917 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3918 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00003919 unsigned Order) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003920 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
3921 "only required for the device "
3922 "code generation.");
Samuel Antao2de62b02016-02-13 23:35:10 +00003923 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
Samuel Antaof83efdb2017-01-05 16:02:49 +00003924 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003925 OMPTargetRegionEntryTargetRegion);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003926 ++OffloadingEntriesNum;
3927}
3928
3929void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3930 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3931 StringRef ParentName, unsigned LineNum,
Samuel Antaof83efdb2017-01-05 16:02:49 +00003932 llvm::Constant *Addr, llvm::Constant *ID,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003933 OMPTargetRegionEntryKind Flags) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003934 // If we are emitting code for a target, the entry is already initialized,
3935 // only has to be registered.
3936 if (CGM.getLangOpts().OpenMPIsDevice) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00003937 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) {
3938 unsigned DiagID = CGM.getDiags().getCustomDiagID(
3939 DiagnosticsEngine::Error,
3940 "Unable to find target region on line '%0' in the device code.");
3941 CGM.getDiags().Report(DiagID) << LineNum;
3942 return;
3943 }
Samuel Antao2de62b02016-02-13 23:35:10 +00003944 auto &Entry =
3945 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
Samuel Antaoee8fb302016-01-06 13:42:12 +00003946 assert(Entry.isValid() && "Entry not initialized!");
3947 Entry.setAddress(Addr);
3948 Entry.setID(ID);
Samuel Antaof83efdb2017-01-05 16:02:49 +00003949 Entry.setFlags(Flags);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003950 } else {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003951 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags);
Samuel Antao2de62b02016-02-13 23:35:10 +00003952 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00003953 ++OffloadingEntriesNum;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003954 }
3955}
3956
3957bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00003958 unsigned DeviceID, unsigned FileID, StringRef ParentName,
3959 unsigned LineNum) const {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003960 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
3961 if (PerDevice == OffloadEntriesTargetRegion.end())
3962 return false;
3963 auto PerFile = PerDevice->second.find(FileID);
3964 if (PerFile == PerDevice->second.end())
3965 return false;
3966 auto PerParentName = PerFile->second.find(ParentName);
3967 if (PerParentName == PerFile->second.end())
3968 return false;
3969 auto PerLine = PerParentName->second.find(LineNum);
3970 if (PerLine == PerParentName->second.end())
3971 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003972 // Fail if this entry is already registered.
Samuel Antao2de62b02016-02-13 23:35:10 +00003973 if (PerLine->second.getAddress() || PerLine->second.getID())
Samuel Antaoee8fb302016-01-06 13:42:12 +00003974 return false;
3975 return true;
3976}
3977
3978void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
3979 const OffloadTargetRegionEntryInfoActTy &Action) {
3980 // Scan all target region entries and perform the provided action.
Alexey Bataev03f270c2018-03-30 18:31:07 +00003981 for (const auto &D : OffloadEntriesTargetRegion)
3982 for (const auto &F : D.second)
3983 for (const auto &P : F.second)
3984 for (const auto &L : P.second)
Samuel Antao2de62b02016-02-13 23:35:10 +00003985 Action(D.first, F.first, P.first(), L.first, L.second);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003986}
3987
Alexey Bataev03f270c2018-03-30 18:31:07 +00003988void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3989 initializeDeviceGlobalVarEntryInfo(StringRef Name,
3990 OMPTargetGlobalVarEntryKind Flags,
3991 unsigned Order) {
3992 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
3993 "only required for the device "
3994 "code generation.");
3995 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
3996 ++OffloadingEntriesNum;
3997}
Samuel Antaoee8fb302016-01-06 13:42:12 +00003998
Alexey Bataev03f270c2018-03-30 18:31:07 +00003999void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
4000 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr,
4001 CharUnits VarSize,
4002 OMPTargetGlobalVarEntryKind Flags,
4003 llvm::GlobalValue::LinkageTypes Linkage) {
4004 if (CGM.getLangOpts().OpenMPIsDevice) {
4005 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
4006 assert(Entry.isValid() && Entry.getFlags() == Flags &&
4007 "Entry not initialized!");
4008 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
4009 "Resetting with the new address.");
Alexey Bataev8259cc32019-03-12 20:05:17 +00004010 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) {
4011 if (Entry.getVarSize().isZero()) {
4012 Entry.setVarSize(VarSize);
4013 Entry.setLinkage(Linkage);
4014 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004015 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00004016 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004017 Entry.setVarSize(VarSize);
4018 Entry.setLinkage(Linkage);
Alexey Bataev8259cc32019-03-12 20:05:17 +00004019 Entry.setAddress(Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00004020 } else {
Alexey Bataev8259cc32019-03-12 20:05:17 +00004021 if (hasDeviceGlobalVarEntryInfo(VarName)) {
4022 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
4023 assert(Entry.isValid() && Entry.getFlags() == Flags &&
4024 "Entry not initialized!");
4025 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
4026 "Resetting with the new address.");
4027 if (Entry.getVarSize().isZero()) {
4028 Entry.setVarSize(VarSize);
4029 Entry.setLinkage(Linkage);
4030 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004031 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00004032 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004033 OffloadEntriesDeviceGlobalVar.try_emplace(
4034 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage);
4035 ++OffloadingEntriesNum;
4036 }
4037}
4038
4039void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
4040 actOnDeviceGlobalVarEntriesInfo(
4041 const OffloadDeviceGlobalVarEntryInfoActTy &Action) {
4042 // Scan all target region entries and perform the provided action.
4043 for (const auto &E : OffloadEntriesDeviceGlobalVar)
4044 Action(E.getKey(), E.getValue());
Samuel Antaoee8fb302016-01-06 13:42:12 +00004045}
4046
Alexey Bataev03f270c2018-03-30 18:31:07 +00004047void CGOpenMPRuntime::createOffloadEntry(
4048 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags,
4049 llvm::GlobalValue::LinkageTypes Linkage) {
Samuel Antao2de62b02016-02-13 23:35:10 +00004050 StringRef Name = Addr->getName();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004051 llvm::Module &M = CGM.getModule();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004052 llvm::LLVMContext &C = M.getContext();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004053
4054 // Create constant string with the name.
4055 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
4056
Alexey Bataev18fa2322018-05-02 14:20:50 +00004057 std::string StringName = getName({"omp_offloading", "entry_name"});
4058 auto *Str = new llvm::GlobalVariable(
4059 M, StrPtrInit->getType(), /*isConstant=*/true,
4060 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00004061 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004062
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004063 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy),
4064 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy),
4065 llvm::ConstantInt::get(CGM.SizeTy, Size),
4066 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
4067 llvm::ConstantInt::get(CGM.Int32Ty, 0)};
Alexey Bataev18fa2322018-05-02 14:20:50 +00004068 std::string EntryName = getName({"omp_offloading", "entry", ""});
Mike Ricee1ca7b62018-08-29 15:45:11 +00004069 llvm::GlobalVariable *Entry = createGlobalStruct(
4070 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data,
4071 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004072
4073 // The entry has to be created in the section the linker expects it to be.
Sergey Dmitriev4b343fd2019-09-27 20:00:51 +00004074 Entry->setSection("omp_offloading_entries");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004075}
4076
4077void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
4078 // Emit the offloading entries and metadata so that the device codegen side
Samuel Antao4c8035b2016-12-12 18:00:20 +00004079 // can easily figure out what to emit. The produced metadata looks like
4080 // this:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004081 //
4082 // !omp_offload.info = !{!1, ...}
4083 //
4084 // Right now we only generate metadata for function that contain target
4085 // regions.
4086
Sergey Dmitriev5836c352019-10-15 18:42:47 +00004087 // If we are in simd mode or there are no entries, we don't need to do
4088 // anything.
4089 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty())
Samuel Antaoee8fb302016-01-06 13:42:12 +00004090 return;
4091
4092 llvm::Module &M = CGM.getModule();
4093 llvm::LLVMContext &C = M.getContext();
Alexey Bataevba643691d2019-10-03 16:20:34 +00004094 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *,
4095 SourceLocation, StringRef>,
4096 16>
Samuel Antaoee8fb302016-01-06 13:42:12 +00004097 OrderedEntries(OffloadEntriesInfoManager.size());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004098 llvm::SmallVector<StringRef, 16> ParentFunctions(
4099 OffloadEntriesInfoManager.size());
Samuel Antaoee8fb302016-01-06 13:42:12 +00004100
Simon Pilgrim2c518802017-03-30 14:13:19 +00004101 // Auxiliary methods to create metadata values and strings.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004102 auto &&GetMDInt = [this](unsigned V) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004103 return llvm::ConstantAsMetadata::get(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004104 llvm::ConstantInt::get(CGM.Int32Ty, V));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004105 };
4106
Alexey Bataev03f270c2018-03-30 18:31:07 +00004107 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); };
4108
4109 // Create the offloading info metadata node.
4110 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004111
4112 // Create function that emits metadata for each target region entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00004113 auto &&TargetRegionMetadataEmitter =
Alexey Bataevba643691d2019-10-03 16:20:34 +00004114 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt,
4115 &GetMDString](
Alexey Bataev03f270c2018-03-30 18:31:07 +00004116 unsigned DeviceID, unsigned FileID, StringRef ParentName,
4117 unsigned Line,
4118 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
4119 // Generate metadata for target regions. Each entry of this metadata
4120 // contains:
4121 // - Entry 0 -> Kind of this type of metadata (0).
4122 // - Entry 1 -> Device ID of the file where the entry was identified.
4123 // - Entry 2 -> File ID of the file where the entry was identified.
4124 // - Entry 3 -> Mangled name of the function where the entry was
4125 // identified.
4126 // - Entry 4 -> Line in the file where the entry was identified.
4127 // - Entry 5 -> Order the entry was created.
4128 // The first element of the metadata node is the kind.
4129 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID),
4130 GetMDInt(FileID), GetMDString(ParentName),
4131 GetMDInt(Line), GetMDInt(E.getOrder())};
Samuel Antaoee8fb302016-01-06 13:42:12 +00004132
Alexey Bataevba643691d2019-10-03 16:20:34 +00004133 SourceLocation Loc;
4134 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(),
4135 E = CGM.getContext().getSourceManager().fileinfo_end();
4136 I != E; ++I) {
4137 if (I->getFirst()->getUniqueID().getDevice() == DeviceID &&
4138 I->getFirst()->getUniqueID().getFile() == FileID) {
4139 Loc = CGM.getContext().getSourceManager().translateFileLineCol(
4140 I->getFirst(), Line, 1);
4141 break;
4142 }
4143 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004144 // Save this entry in the right position of the ordered entries array.
Alexey Bataevba643691d2019-10-03 16:20:34 +00004145 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName);
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004146 ParentFunctions[E.getOrder()] = ParentName;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004147
Alexey Bataev03f270c2018-03-30 18:31:07 +00004148 // Add metadata to the named metadata node.
4149 MD->addOperand(llvm::MDNode::get(C, Ops));
4150 };
Samuel Antaoee8fb302016-01-06 13:42:12 +00004151
4152 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
4153 TargetRegionMetadataEmitter);
4154
Alexey Bataev03f270c2018-03-30 18:31:07 +00004155 // Create function that emits metadata for each device global variable entry;
4156 auto &&DeviceGlobalVarMetadataEmitter =
4157 [&C, &OrderedEntries, &GetMDInt, &GetMDString,
4158 MD](StringRef MangledName,
4159 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar
4160 &E) {
4161 // Generate metadata for global variables. Each entry of this metadata
4162 // contains:
4163 // - Entry 0 -> Kind of this type of metadata (1).
4164 // - Entry 1 -> Mangled name of the variable.
4165 // - Entry 2 -> Declare target kind.
4166 // - Entry 3 -> Order the entry was created.
4167 // The first element of the metadata node is the kind.
4168 llvm::Metadata *Ops[] = {
4169 GetMDInt(E.getKind()), GetMDString(MangledName),
4170 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
4171
4172 // Save this entry in the right position of the ordered entries array.
Alexey Bataevba643691d2019-10-03 16:20:34 +00004173 OrderedEntries[E.getOrder()] =
4174 std::make_tuple(&E, SourceLocation(), MangledName);
Alexey Bataev03f270c2018-03-30 18:31:07 +00004175
4176 // Add metadata to the named metadata node.
4177 MD->addOperand(llvm::MDNode::get(C, Ops));
4178 };
4179
4180 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo(
4181 DeviceGlobalVarMetadataEmitter);
4182
Alexey Bataevba643691d2019-10-03 16:20:34 +00004183 for (const auto &E : OrderedEntries) {
4184 assert(std::get<0>(E) && "All ordered entries must exist!");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004185 if (const auto *CE =
Samuel Antaoee8fb302016-01-06 13:42:12 +00004186 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
Alexey Bataevba643691d2019-10-03 16:20:34 +00004187 std::get<0>(E))) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004188 if (!CE->getID() || !CE->getAddress()) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004189 // Do not blame the entry if the parent funtion is not emitted.
4190 StringRef FnName = ParentFunctions[CE->getOrder()];
4191 if (!CGM.GetGlobalValue(FnName))
4192 continue;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004193 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4194 DiagnosticsEngine::Error,
Alexey Bataevba643691d2019-10-03 16:20:34 +00004195 "Offloading entry for target region in %0 is incorrect: either the "
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004196 "address or the ID is invalid.");
Alexey Bataevba643691d2019-10-03 16:20:34 +00004197 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004198 continue;
4199 }
Alexey Bataev34f8a702018-03-28 14:28:54 +00004200 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004201 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage);
Alexey Bataevba643691d2019-10-03 16:20:34 +00004202 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy::
4203 OffloadEntryInfoDeviceGlobalVar>(
4204 std::get<0>(E))) {
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004205 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags =
4206 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4207 CE->getFlags());
4208 switch (Flags) {
4209 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00004210 if (CGM.getLangOpts().OpenMPIsDevice &&
4211 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())
4212 continue;
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004213 if (!CE->getAddress()) {
4214 unsigned DiagID = CGM.getDiags().getCustomDiagID(
Alexey Bataevba643691d2019-10-03 16:20:34 +00004215 DiagnosticsEngine::Error, "Offloading entry for declare target "
4216 "variable %0 is incorrect: the "
4217 "address is invalid.");
4218 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E);
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004219 continue;
4220 }
Alexey Bataevb4dd6d22018-08-29 20:41:37 +00004221 // The vaiable has no definition - no need to add the entry.
4222 if (CE->getVarSize().isZero())
4223 continue;
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004224 break;
4225 }
4226 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink:
4227 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) ||
4228 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) &&
4229 "Declaret target link address is set.");
4230 if (CGM.getLangOpts().OpenMPIsDevice)
4231 continue;
4232 if (!CE->getAddress()) {
4233 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4234 DiagnosticsEngine::Error,
4235 "Offloading entry for declare target variable is incorrect: the "
4236 "address is invalid.");
4237 CGM.getDiags().Report(DiagID);
4238 continue;
4239 }
4240 break;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004241 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004242 createOffloadEntry(CE->getAddress(), CE->getAddress(),
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004243 CE->getVarSize().getQuantity(), Flags,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004244 CE->getLinkage());
4245 } else {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004246 llvm_unreachable("Unsupported entry kind.");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004247 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004248 }
4249}
4250
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004251/// Loads all the offload entries information from the host IR
Samuel Antaoee8fb302016-01-06 13:42:12 +00004252/// metadata.
4253void CGOpenMPRuntime::loadOffloadInfoMetadata() {
4254 // If we are in target mode, load the metadata from the host IR. This code has
4255 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
4256
4257 if (!CGM.getLangOpts().OpenMPIsDevice)
4258 return;
4259
4260 if (CGM.getLangOpts().OMPHostIRFile.empty())
4261 return;
4262
4263 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004264 if (auto EC = Buf.getError()) {
4265 CGM.getDiags().Report(diag::err_cannot_open_file)
4266 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004267 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004268 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004269
4270 llvm::LLVMContext C;
Peter Collingbourned9445c42016-11-13 07:00:17 +00004271 auto ME = expectedToErrorOrAndEmitErrors(
4272 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004273
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004274 if (auto EC = ME.getError()) {
4275 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4276 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'");
4277 CGM.getDiags().Report(DiagID)
4278 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004279 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004280 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004281
4282 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
4283 if (!MD)
4284 return;
4285
George Burgess IV00f70bd2018-03-01 05:43:23 +00004286 for (llvm::MDNode *MN : MD->operands()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004287 auto &&GetMDInt = [MN](unsigned Idx) {
4288 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004289 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
4290 };
4291
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004292 auto &&GetMDString = [MN](unsigned Idx) {
4293 auto *V = cast<llvm::MDString>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004294 return V->getString();
4295 };
4296
Alexey Bataev03f270c2018-03-30 18:31:07 +00004297 switch (GetMDInt(0)) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004298 default:
4299 llvm_unreachable("Unexpected metadata!");
4300 break;
4301 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
Alexey Bataev34f8a702018-03-28 14:28:54 +00004302 OffloadingEntryInfoTargetRegion:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004303 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
Alexey Bataev03f270c2018-03-30 18:31:07 +00004304 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2),
4305 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4),
4306 /*Order=*/GetMDInt(5));
4307 break;
4308 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
4309 OffloadingEntryInfoDeviceGlobalVar:
4310 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo(
4311 /*MangledName=*/GetMDString(1),
4312 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4313 /*Flags=*/GetMDInt(2)),
4314 /*Order=*/GetMDInt(3));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004315 break;
4316 }
4317 }
4318}
4319
Alexey Bataev62b63b12015-03-10 07:28:44 +00004320void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
4321 if (!KmpRoutineEntryPtrTy) {
4322 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004323 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004324 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
4325 FunctionProtoType::ExtProtoInfo EPI;
4326 KmpRoutineEntryPtrQTy = C.getPointerType(
4327 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
4328 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
4329 }
4330}
4331
Samuel Antaoee8fb302016-01-06 13:42:12 +00004332QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004333 // Make sure the type of the entry is already created. This is the type we
4334 // have to create:
4335 // struct __tgt_offload_entry{
4336 // void *addr; // Pointer to the offload entry info.
4337 // // (function or global)
4338 // char *name; // Name of the function or global.
4339 // size_t size; // Size of the entry info (0 if it a function).
Samuel Antaof83efdb2017-01-05 16:02:49 +00004340 // int32_t flags; // Flags associated with the entry, e.g. 'link'.
4341 // int32_t reserved; // Reserved, to use by the runtime library.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004342 // };
4343 if (TgtOffloadEntryQTy.isNull()) {
4344 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004345 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004346 RD->startDefinition();
4347 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4348 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
4349 addFieldToRecordDecl(C, RD, C.getSizeType());
Samuel Antaof83efdb2017-01-05 16:02:49 +00004350 addFieldToRecordDecl(
4351 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4352 addFieldToRecordDecl(
4353 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004354 RD->completeDefinition();
Jonas Hahnfeld5e4df282018-01-18 15:38:03 +00004355 RD->addAttr(PackedAttr::CreateImplicit(C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004356 TgtOffloadEntryQTy = C.getRecordType(RD);
4357 }
4358 return TgtOffloadEntryQTy;
4359}
4360
4361QualType CGOpenMPRuntime::getTgtDeviceImageQTy() {
4362 // These are the types we need to build:
4363 // struct __tgt_device_image{
4364 // void *ImageStart; // Pointer to the target code start.
4365 // void *ImageEnd; // Pointer to the target code end.
4366 // // We also add the host entries to the device image, as it may be useful
4367 // // for the target runtime to have access to that information.
4368 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all
4369 // // the entries.
4370 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
4371 // // entries (non inclusive).
4372 // };
4373 if (TgtDeviceImageQTy.isNull()) {
4374 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004375 RecordDecl *RD = C.buildImplicitRecord("__tgt_device_image");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004376 RD->startDefinition();
4377 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4378 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4379 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4380 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4381 RD->completeDefinition();
4382 TgtDeviceImageQTy = C.getRecordType(RD);
4383 }
4384 return TgtDeviceImageQTy;
4385}
4386
4387QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() {
4388 // struct __tgt_bin_desc{
4389 // int32_t NumDevices; // Number of devices supported.
4390 // __tgt_device_image *DeviceImages; // Arrays of device images
4391 // // (one per device).
4392 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the
4393 // // entries.
4394 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
4395 // // entries (non inclusive).
4396 // };
4397 if (TgtBinaryDescriptorQTy.isNull()) {
4398 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004399 RecordDecl *RD = C.buildImplicitRecord("__tgt_bin_desc");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004400 RD->startDefinition();
4401 addFieldToRecordDecl(
4402 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4403 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy()));
4404 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4405 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4406 RD->completeDefinition();
4407 TgtBinaryDescriptorQTy = C.getRecordType(RD);
4408 }
4409 return TgtBinaryDescriptorQTy;
4410}
4411
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004412namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00004413struct PrivateHelpersTy {
4414 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
4415 const VarDecl *PrivateElemInit)
4416 : Original(Original), PrivateCopy(PrivateCopy),
4417 PrivateElemInit(PrivateElemInit) {}
4418 const VarDecl *Original;
4419 const VarDecl *PrivateCopy;
4420 const VarDecl *PrivateElemInit;
4421};
4422typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Hans Wennborg7eb54642015-09-10 17:07:54 +00004423} // anonymous namespace
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004424
Alexey Bataev9e034042015-05-05 04:05:12 +00004425static RecordDecl *
Craig Topper8674c5c2015-09-29 04:30:07 +00004426createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004427 if (!Privates.empty()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004428 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004429 // Build struct .kmp_privates_t. {
4430 // /* private vars */
4431 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004432 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t");
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004433 RD->startDefinition();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004434 for (const auto &Pair : Privates) {
4435 const VarDecl *VD = Pair.second.Original;
4436 QualType Type = VD->getType().getNonReferenceType();
4437 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type);
Alexey Bataevc71a4092015-09-11 10:29:41 +00004438 if (VD->hasAttrs()) {
4439 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
4440 E(VD->getAttrs().end());
4441 I != E; ++I)
4442 FD->addAttr(*I);
4443 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004444 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004445 RD->completeDefinition();
4446 return RD;
4447 }
4448 return nullptr;
4449}
4450
Alexey Bataev9e034042015-05-05 04:05:12 +00004451static RecordDecl *
Alexey Bataev7292c292016-04-25 12:22:29 +00004452createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind,
4453 QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004454 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004455 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004456 // Build struct kmp_task_t {
4457 // void * shareds;
4458 // kmp_routine_entry_t routine;
4459 // kmp_int32 part_id;
Alexey Bataevad537bb2016-05-30 09:06:50 +00004460 // kmp_cmplrdata_t data1;
4461 // kmp_cmplrdata_t data2;
Alexey Bataev7292c292016-04-25 12:22:29 +00004462 // For taskloops additional fields:
4463 // kmp_uint64 lb;
4464 // kmp_uint64 ub;
4465 // kmp_int64 st;
4466 // kmp_int32 liter;
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004467 // void * reductions;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004468 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004469 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004470 UD->startDefinition();
4471 addFieldToRecordDecl(C, UD, KmpInt32Ty);
4472 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy);
4473 UD->completeDefinition();
4474 QualType KmpCmplrdataTy = C.getRecordType(UD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004475 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t");
Alexey Bataev62b63b12015-03-10 07:28:44 +00004476 RD->startDefinition();
4477 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4478 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
4479 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004480 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
4481 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004482 if (isOpenMPTaskLoopDirective(Kind)) {
4483 QualType KmpUInt64Ty =
4484 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
4485 QualType KmpInt64Ty =
4486 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
4487 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4488 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4489 addFieldToRecordDecl(C, RD, KmpInt64Ty);
4490 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004491 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004492 }
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004493 RD->completeDefinition();
4494 return RD;
4495}
4496
4497static RecordDecl *
4498createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004499 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004500 ASTContext &C = CGM.getContext();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004501 // Build struct kmp_task_t_with_privates {
4502 // kmp_task_t task_data;
4503 // .kmp_privates_t. privates;
4504 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004505 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004506 RD->startDefinition();
4507 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004508 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates))
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004509 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004510 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004511 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004512}
4513
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004514/// Emit a proxy function which accepts kmp_task_t as the second
Alexey Bataev62b63b12015-03-10 07:28:44 +00004515/// argument.
4516/// \code
4517/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00004518/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt,
Alexey Bataev7292c292016-04-25 12:22:29 +00004519/// For taskloops:
4520/// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004521/// tt->reductions, tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004522/// return 0;
4523/// }
4524/// \endcode
James Y Knight9871db02019-02-05 16:42:33 +00004525static llvm::Function *
Alexey Bataev62b63b12015-03-10 07:28:44 +00004526emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev7292c292016-04-25 12:22:29 +00004527 OpenMPDirectiveKind Kind, QualType KmpInt32Ty,
4528 QualType KmpTaskTWithPrivatesPtrQTy,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004529 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
James Y Knight9871db02019-02-05 16:42:33 +00004530 QualType SharedsPtrTy, llvm::Function *TaskFunction,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004531 llvm::Value *TaskPrivatesMap) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004532 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004533 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004534 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4535 ImplicitParamDecl::Other);
4536 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4537 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4538 ImplicitParamDecl::Other);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004539 Args.push_back(&GtidArg);
4540 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004541 const auto &TaskEntryFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004542 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004543 llvm::FunctionType *TaskEntryTy =
4544 CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004545 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""});
4546 auto *TaskEntry = llvm::Function::Create(
4547 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004548 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004549 TaskEntry->setDoesNotRecurse();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004550 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004551 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args,
4552 Loc, Loc);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004553
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004554 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
Alexey Bataev7292c292016-04-25 12:22:29 +00004555 // tt,
4556 // For taskloops:
4557 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
4558 // tt->task_data.shareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004559 llvm::Value *GtidParam = CGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00004560 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
Alexey Bataev31300ed2016-02-04 11:27:03 +00004561 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4562 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4563 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004564 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004565 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004566 LValue Base =
4567 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004568 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004569 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004570 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004571 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004572
4573 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004574 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
4575 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev1e491372018-01-23 18:44:14 +00004576 CGF.EmitLoadOfScalar(SharedsLVal, Loc),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004577 CGF.ConvertTypeForMem(SharedsPtrTy));
4578
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004579 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4580 llvm::Value *PrivatesParam;
4581 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004582 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004583 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004584 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004585 } else {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004586 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004587 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004588
Alexey Bataev7292c292016-04-25 12:22:29 +00004589 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam,
4590 TaskPrivatesMap,
4591 CGF.Builder
4592 .CreatePointerBitCastOrAddrSpaceCast(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004593 TDBase.getAddress(CGF), CGF.VoidPtrTy)
Alexey Bataev7292c292016-04-25 12:22:29 +00004594 .getPointer()};
4595 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs),
4596 std::end(CommonArgs));
4597 if (isOpenMPTaskLoopDirective(Kind)) {
4598 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004599 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI);
4600 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004601 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004602 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI);
4603 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004604 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004605 LValue StLVal = CGF.EmitLValueForField(Base, *StFI);
4606 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004607 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004608 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4609 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004610 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004611 LValue RLVal = CGF.EmitLValueForField(Base, *RFI);
4612 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004613 CallArgs.push_back(LBParam);
4614 CallArgs.push_back(UBParam);
4615 CallArgs.push_back(StParam);
4616 CallArgs.push_back(LIParam);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004617 CallArgs.push_back(RParam);
Alexey Bataev7292c292016-04-25 12:22:29 +00004618 }
4619 CallArgs.push_back(SharedsParam);
4620
Alexey Bataev3c595a62017-08-14 15:01:03 +00004621 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction,
4622 CallArgs);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004623 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)),
4624 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004625 CGF.FinishFunction();
4626 return TaskEntry;
4627}
4628
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004629static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
4630 SourceLocation Loc,
4631 QualType KmpInt32Ty,
4632 QualType KmpTaskTWithPrivatesPtrQTy,
4633 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004634 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004635 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004636 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4637 ImplicitParamDecl::Other);
4638 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4639 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4640 ImplicitParamDecl::Other);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004641 Args.push_back(&GtidArg);
4642 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004643 const auto &DestructorFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004644 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004645 llvm::FunctionType *DestructorFnTy =
4646 CGM.getTypes().GetFunctionType(DestructorFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004647 std::string Name =
4648 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""});
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004649 auto *DestructorFn =
4650 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00004651 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004652 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004653 DestructorFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004654 DestructorFn->setDoesNotRecurse();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004655 CodeGenFunction CGF(CGM);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004656 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004657 Args, Loc, Loc);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004658
Alexey Bataev31300ed2016-02-04 11:27:03 +00004659 LValue Base = CGF.EmitLoadOfPointerLValue(
4660 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4661 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004662 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004663 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
4664 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004665 Base = CGF.EmitLValueForField(Base, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004666 for (const auto *Field :
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004667 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004668 if (QualType::DestructionKind DtorKind =
4669 Field->getType().isDestructedType()) {
4670 LValue FieldLValue = CGF.EmitLValueForField(Base, Field);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004671 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004672 }
4673 }
4674 CGF.FinishFunction();
4675 return DestructorFn;
4676}
4677
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004678/// Emit a privates mapping function for correct handling of private and
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004679/// firstprivate variables.
4680/// \code
4681/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
4682/// **noalias priv1,..., <tyn> **noalias privn) {
4683/// *priv1 = &.privates.priv1;
4684/// ...;
4685/// *privn = &.privates.privn;
4686/// }
4687/// \endcode
4688static llvm::Value *
4689emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Craig Topper8674c5c2015-09-29 04:30:07 +00004690 ArrayRef<const Expr *> PrivateVars,
4691 ArrayRef<const Expr *> FirstprivateVars,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004692 ArrayRef<const Expr *> LastprivateVars,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004693 QualType PrivatesQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004694 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004695 ASTContext &C = CGM.getContext();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004696 FunctionArgList Args;
4697 ImplicitParamDecl TaskPrivatesArg(
4698 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
Alexey Bataev56223232017-06-09 13:40:18 +00004699 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
4700 ImplicitParamDecl::Other);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004701 Args.push_back(&TaskPrivatesArg);
4702 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
4703 unsigned Counter = 1;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004704 for (const Expr *E : PrivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004705 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004706 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4707 C.getPointerType(C.getPointerType(E->getType()))
4708 .withConst()
4709 .withRestrict(),
4710 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004711 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004712 PrivateVarsPos[VD] = Counter;
4713 ++Counter;
4714 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004715 for (const Expr *E : FirstprivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004716 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004717 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4718 C.getPointerType(C.getPointerType(E->getType()))
4719 .withConst()
4720 .withRestrict(),
4721 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004722 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004723 PrivateVarsPos[VD] = Counter;
4724 ++Counter;
4725 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004726 for (const Expr *E : LastprivateVars) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004727 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004728 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4729 C.getPointerType(C.getPointerType(E->getType()))
4730 .withConst()
4731 .withRestrict(),
4732 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004733 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataevf93095a2016-05-05 08:46:22 +00004734 PrivateVarsPos[VD] = Counter;
4735 ++Counter;
4736 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004737 const auto &TaskPrivatesMapFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004738 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004739 llvm::FunctionType *TaskPrivatesMapTy =
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004740 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004741 std::string Name =
4742 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""});
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004743 auto *TaskPrivatesMap = llvm::Function::Create(
Alexey Bataev18fa2322018-05-02 14:20:50 +00004744 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
4745 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004746 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004747 TaskPrivatesMapFnInfo);
Alexey Bataev8c5555c2019-05-21 15:11:58 +00004748 if (CGM.getLangOpts().Optimize) {
4749 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
4750 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
4751 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
4752 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004753 CodeGenFunction CGF(CGM);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004754 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004755 TaskPrivatesMapFnInfo, Args, Loc, Loc);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004756
4757 // *privi = &.privates.privi;
Alexey Bataev31300ed2016-02-04 11:27:03 +00004758 LValue Base = CGF.EmitLoadOfPointerLValue(
4759 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
4760 TaskPrivatesArg.getType()->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004761 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004762 Counter = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004763 for (const FieldDecl *Field : PrivatesQTyRD->fields()) {
4764 LValue FieldLVal = CGF.EmitLValueForField(Base, Field);
4765 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
4766 LValue RefLVal =
4767 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
4768 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004769 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>());
4770 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004771 ++Counter;
4772 }
4773 CGF.FinishFunction();
4774 return TaskPrivatesMap;
4775}
4776
Alexey Bataevf93095a2016-05-05 08:46:22 +00004777/// Emit initialization for private variables in task-based directives.
Alexey Bataev8a831592016-05-10 10:36:51 +00004778static void emitPrivatesInit(CodeGenFunction &CGF,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004779 const OMPExecutableDirective &D,
4780 Address KmpTaskSharedsPtr, LValue TDBase,
4781 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4782 QualType SharedsTy, QualType SharedsPtrTy,
4783 const OMPTaskDataTy &Data,
4784 ArrayRef<PrivateDataTy> Privates, bool ForDup) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004785 ASTContext &C = CGF.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004786 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
4787 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004788 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind())
4789 ? OMPD_taskloop
4790 : OMPD_task;
4791 const CapturedStmt &CS = *D.getCapturedStmt(Kind);
4792 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004793 LValue SrcBase;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004794 bool IsTargetTask =
4795 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) ||
4796 isOpenMPTargetExecutionDirective(D.getDirectiveKind());
4797 // For target-based directives skip 3 firstprivate arrays BasePointersArray,
4798 // PointersArray and SizesArray. The original variables for these arrays are
4799 // not captured and we get their addresses explicitly.
4800 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) ||
Alexey Bataev8451efa2018-01-15 19:06:12 +00004801 (IsTargetTask && KmpTaskSharedsPtr.isValid())) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004802 SrcBase = CGF.MakeAddrLValue(
4803 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4804 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
4805 SharedsTy);
4806 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004807 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004808 for (const PrivateDataTy &Pair : Privates) {
4809 const VarDecl *VD = Pair.second.PrivateCopy;
4810 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004811 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) &&
4812 !CGF.isTrivialInitializer(Init)))) {
Alexey Bataev8a831592016-05-10 10:36:51 +00004813 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004814 if (const VarDecl *Elem = Pair.second.PrivateElemInit) {
4815 const VarDecl *OriginalVD = Pair.second.Original;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004816 // Check if the variable is the target-based BasePointersArray,
4817 // PointersArray or SizesArray.
4818 LValue SharedRefLValue;
Alexey Bataevab41ea62019-03-13 20:46:28 +00004819 QualType Type = PrivateLValue.getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004820 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004821 if (IsTargetTask && !SharedField) {
4822 assert(isa<ImplicitParamDecl>(OriginalVD) &&
4823 isa<CapturedDecl>(OriginalVD->getDeclContext()) &&
4824 cast<CapturedDecl>(OriginalVD->getDeclContext())
4825 ->getNumParams() == 0 &&
4826 isa<TranslationUnitDecl>(
4827 cast<CapturedDecl>(OriginalVD->getDeclContext())
4828 ->getDeclContext()) &&
4829 "Expected artificial target data variable.");
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004830 SharedRefLValue =
4831 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type);
4832 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004833 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField);
4834 SharedRefLValue = CGF.MakeAddrLValue(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004835 Address(SharedRefLValue.getPointer(CGF),
4836 C.getDeclAlign(OriginalVD)),
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004837 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl),
4838 SharedRefLValue.getTBAAInfo());
4839 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004840 if (Type->isArrayType()) {
4841 // Initialize firstprivate array.
4842 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) {
4843 // Perform simple memcpy.
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00004844 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004845 } else {
4846 // Initialize firstprivate array using element-by-element
Simon Pilgrim2c518802017-03-30 14:13:19 +00004847 // initialization.
Alexey Bataevf93095a2016-05-05 08:46:22 +00004848 CGF.EmitOMPAggregateAssign(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004849 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF),
4850 Type,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004851 [&CGF, Elem, Init, &CapturesInfo](Address DestElement,
4852 Address SrcElement) {
4853 // Clean up any temporaries needed by the initialization.
4854 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4855 InitScope.addPrivate(
4856 Elem, [SrcElement]() -> Address { return SrcElement; });
4857 (void)InitScope.Privatize();
4858 // Emit initialization for single element.
4859 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
4860 CGF, &CapturesInfo);
4861 CGF.EmitAnyExprToMem(Init, DestElement,
4862 Init->getType().getQualifiers(),
4863 /*IsInitializer=*/false);
4864 });
4865 }
4866 } else {
4867 CodeGenFunction::OMPPrivateScope InitScope(CGF);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004868 InitScope.addPrivate(Elem, [SharedRefLValue, &CGF]() -> Address {
4869 return SharedRefLValue.getAddress(CGF);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004870 });
4871 (void)InitScope.Privatize();
4872 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
4873 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
4874 /*capturedByInit=*/false);
4875 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004876 } else {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004877 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004878 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004879 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004880 ++FI;
4881 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004882}
4883
4884/// Check if duplication function is required for taskloops.
4885static bool checkInitIsRequired(CodeGenFunction &CGF,
4886 ArrayRef<PrivateDataTy> Privates) {
4887 bool InitRequired = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004888 for (const PrivateDataTy &Pair : Privates) {
4889 const VarDecl *VD = Pair.second.PrivateCopy;
4890 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004891 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) &&
4892 !CGF.isTrivialInitializer(Init));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004893 if (InitRequired)
4894 break;
Alexey Bataevf93095a2016-05-05 08:46:22 +00004895 }
4896 return InitRequired;
4897}
4898
4899
4900/// Emit task_dup function (for initialization of
4901/// private/firstprivate/lastprivate vars and last_iter flag)
4902/// \code
4903/// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int
4904/// lastpriv) {
4905/// // setup lastprivate flag
4906/// task_dst->last = lastpriv;
4907/// // could be constructor calls here...
4908/// }
4909/// \endcode
4910static llvm::Value *
4911emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
4912 const OMPExecutableDirective &D,
4913 QualType KmpTaskTWithPrivatesPtrQTy,
4914 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4915 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy,
4916 QualType SharedsPtrTy, const OMPTaskDataTy &Data,
4917 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004918 ASTContext &C = CGM.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004919 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004920 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4921 KmpTaskTWithPrivatesPtrQTy,
4922 ImplicitParamDecl::Other);
4923 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4924 KmpTaskTWithPrivatesPtrQTy,
4925 ImplicitParamDecl::Other);
4926 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy,
4927 ImplicitParamDecl::Other);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004928 Args.push_back(&DstArg);
4929 Args.push_back(&SrcArg);
4930 Args.push_back(&LastprivArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004931 const auto &TaskDupFnInfo =
Alexey Bataevf93095a2016-05-05 08:46:22 +00004932 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004933 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004934 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""});
4935 auto *TaskDup = llvm::Function::Create(
4936 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004937 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004938 TaskDup->setDoesNotRecurse();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004939 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004940 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc,
4941 Loc);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004942
4943 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4944 CGF.GetAddrOfLocalVar(&DstArg),
4945 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4946 // task_dst->liter = lastpriv;
4947 if (WithLastIter) {
4948 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
4949 LValue Base = CGF.EmitLValueForField(
4950 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4951 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4952 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar(
4953 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc);
4954 CGF.EmitStoreOfScalar(Lastpriv, LILVal);
4955 }
4956
4957 // Emit initial values for private copies (if any).
4958 assert(!Privates.empty());
4959 Address KmpTaskSharedsPtr = Address::invalid();
4960 if (!Data.FirstprivateVars.empty()) {
4961 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4962 CGF.GetAddrOfLocalVar(&SrcArg),
4963 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4964 LValue Base = CGF.EmitLValueForField(
4965 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4966 KmpTaskSharedsPtr = Address(
4967 CGF.EmitLoadOfScalar(CGF.EmitLValueForField(
4968 Base, *std::next(KmpTaskTQTyRD->field_begin(),
4969 KmpTaskTShareds)),
4970 Loc),
4971 CGF.getNaturalTypeAlignment(SharedsTy));
4972 }
Alexey Bataev8a831592016-05-10 10:36:51 +00004973 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
4974 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004975 CGF.FinishFunction();
4976 return TaskDup;
4977}
4978
Alexey Bataev8a831592016-05-10 10:36:51 +00004979/// Checks if destructor function is required to be generated.
4980/// \return true if cleanups are required, false otherwise.
4981static bool
4982checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) {
4983 bool NeedsCleanup = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004984 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4985 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl());
4986 for (const FieldDecl *FD : PrivateRD->fields()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00004987 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType();
4988 if (NeedsCleanup)
4989 break;
4990 }
4991 return NeedsCleanup;
4992}
4993
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004994CGOpenMPRuntime::TaskResultTy
4995CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
4996 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00004997 llvm::Function *TaskFunction, QualType SharedsTy,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004998 Address Shareds, const OMPTaskDataTy &Data) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004999 ASTContext &C = CGM.getContext();
Alexey Bataev7292c292016-04-25 12:22:29 +00005000 llvm::SmallVector<PrivateDataTy, 4> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005001 // Aggregate privates and sort them by the alignment.
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005002 auto I = Data.PrivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005003 for (const Expr *E : Data.PrivateVars) {
5004 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00005005 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00005006 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00005007 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00005008 /*PrivateElemInit=*/nullptr));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005009 ++I;
5010 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005011 I = Data.FirstprivateCopies.begin();
5012 auto IElemInitRef = Data.FirstprivateInits.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005013 for (const Expr *E : Data.FirstprivateVars) {
5014 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00005015 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00005016 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00005017 PrivateHelpersTy(
5018 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00005019 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())));
Richard Trieucc3949d2016-02-18 22:34:54 +00005020 ++I;
5021 ++IElemInitRef;
Alexey Bataev9e034042015-05-05 04:05:12 +00005022 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00005023 I = Data.LastprivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005024 for (const Expr *E : Data.LastprivateVars) {
5025 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00005026 Privates.emplace_back(
Alexey Bataevf93095a2016-05-05 08:46:22 +00005027 C.getDeclAlign(VD),
5028 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00005029 /*PrivateElemInit=*/nullptr));
Alexey Bataevf93095a2016-05-05 08:46:22 +00005030 ++I;
5031 }
Fangrui Song899d1392019-04-24 14:43:05 +00005032 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) {
5033 return L.first > R.first;
5034 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005035 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005036 // Build type kmp_routine_entry_t (if not built yet).
5037 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005038 // Build type kmp_task_t (if not built yet).
Alexey Bataeve213f3e2017-10-11 15:29:40 +00005039 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) {
5040 if (SavedKmpTaskloopTQTy.isNull()) {
5041 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5042 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5043 }
5044 KmpTaskTQTy = SavedKmpTaskloopTQTy;
Alexey Bataev3a03a7f2017-10-11 15:56:38 +00005045 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00005046 assert((D.getDirectiveKind() == OMPD_task ||
5047 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) ||
5048 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) &&
5049 "Expected taskloop, task or target directive");
Alexey Bataeve213f3e2017-10-11 15:29:40 +00005050 if (SavedKmpTaskTQTy.isNull()) {
5051 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5052 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5053 }
5054 KmpTaskTQTy = SavedKmpTaskTQTy;
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005055 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005056 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005057 // Build particular struct kmp_task_t for the given task.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005058 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005059 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005060 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005061 QualType KmpTaskTWithPrivatesPtrQTy =
5062 C.getPointerType(KmpTaskTWithPrivatesQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005063 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
5064 llvm::Type *KmpTaskTWithPrivatesPtrTy =
5065 KmpTaskTWithPrivatesTy->getPointerTo();
5066 llvm::Value *KmpTaskTWithPrivatesTySize =
5067 CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005068 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
5069
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005070 // Emit initial values for private copies (if any).
5071 llvm::Value *TaskPrivatesMap = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005072 llvm::Type *TaskPrivatesMapTy =
James Y Knight9871db02019-02-05 16:42:33 +00005073 std::next(TaskFunction->arg_begin(), 3)->getType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005074 if (!Privates.empty()) {
5075 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataevf93095a2016-05-05 08:46:22 +00005076 TaskPrivatesMap = emitTaskPrivateMappingFunction(
5077 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars,
5078 FI->getType(), Privates);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005079 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5080 TaskPrivatesMap, TaskPrivatesMapTy);
5081 } else {
5082 TaskPrivatesMap = llvm::ConstantPointerNull::get(
5083 cast<llvm::PointerType>(TaskPrivatesMapTy));
5084 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005085 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
5086 // kmp_task_t *tt);
James Y Knight9871db02019-02-05 16:42:33 +00005087 llvm::Function *TaskEntry = emitProxyTaskFunction(
Alexey Bataev7292c292016-04-25 12:22:29 +00005088 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5089 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction,
5090 TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005091
5092 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
5093 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
5094 // kmp_routine_entry_t *task_entry);
5095 // Task flags. Format is taken from
James Y Knight5d71fc52019-01-29 16:37:27 +00005096 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h,
Alexey Bataev62b63b12015-03-10 07:28:44 +00005097 // description of kmp_tasking_flags struct.
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005098 enum {
5099 TiedFlag = 0x1,
5100 FinalFlag = 0x2,
5101 DestructorsFlag = 0x8,
5102 PriorityFlag = 0x20
5103 };
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005104 unsigned Flags = Data.Tied ? TiedFlag : 0;
Alexey Bataev8a831592016-05-10 10:36:51 +00005105 bool NeedsCleanup = false;
5106 if (!Privates.empty()) {
5107 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD);
5108 if (NeedsCleanup)
5109 Flags = Flags | DestructorsFlag;
5110 }
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005111 if (Data.Priority.getInt())
5112 Flags = Flags | PriorityFlag;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005113 llvm::Value *TaskFlags =
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005114 Data.Final.getPointer()
5115 ? CGF.Builder.CreateSelect(Data.Final.getPointer(),
Alexey Bataev62b63b12015-03-10 07:28:44 +00005116 CGF.Builder.getInt32(FinalFlag),
5117 CGF.Builder.getInt32(/*C=*/0))
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005118 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005119 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005120 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00005121 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc),
5122 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
5123 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5124 TaskEntry, KmpRoutineEntryPtrTy)};
5125 llvm::Value *NewTask;
5126 if (D.hasClausesOfKind<OMPNowaitClause>()) {
5127 // Check if we have any device clause associated with the directive.
5128 const Expr *Device = nullptr;
5129 if (auto *C = D.getSingleClause<OMPDeviceClause>())
5130 Device = C->getDevice();
5131 // Emit device ID if any otherwise use default value.
5132 llvm::Value *DeviceID;
5133 if (Device)
5134 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
5135 CGF.Int64Ty, /*isSigned=*/true);
5136 else
5137 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
5138 AllocArgs.push_back(DeviceID);
5139 NewTask = CGF.EmitRuntimeCall(
5140 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs);
5141 } else {
5142 NewTask = CGF.EmitRuntimeCall(
Alexey Bataev62b63b12015-03-10 07:28:44 +00005143 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00005144 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005145 llvm::Value *NewTaskNewTaskTTy =
5146 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5147 NewTask, KmpTaskTWithPrivatesPtrTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005148 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
5149 KmpTaskTWithPrivatesQTy);
5150 LValue TDBase =
5151 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005152 // Fill the data in the resulting kmp_task_t record.
5153 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00005154 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005155 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00005156 KmpTaskSharedsPtr =
5157 Address(CGF.EmitLoadOfScalar(
5158 CGF.EmitLValueForField(
5159 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
5160 KmpTaskTShareds)),
5161 Loc),
5162 CGF.getNaturalTypeAlignment(SharedsTy));
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00005163 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy);
5164 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy);
Richard Smithe78fac52018-04-05 20:52:58 +00005165 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005166 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005167 // Emit initial values for private copies (if any).
Alexey Bataevf93095a2016-05-05 08:46:22 +00005168 TaskResultTy Result;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005169 if (!Privates.empty()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00005170 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD,
5171 SharedsTy, SharedsPtrTy, Data, Privates,
5172 /*ForDup=*/false);
Alexey Bataevf93095a2016-05-05 08:46:22 +00005173 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
5174 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) {
5175 Result.TaskDupFn = emitTaskDupFunction(
5176 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
5177 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates,
5178 /*WithLastIter=*/!Data.LastprivateVars.empty());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005179 }
5180 }
Alexey Bataevad537bb2016-05-30 09:06:50 +00005181 // Fields of union "kmp_cmplrdata_t" for destructors and priority.
5182 enum { Priority = 0, Destructors = 1 };
Alexey Bataev62b63b12015-03-10 07:28:44 +00005183 // Provide pointer to function with destructors for privates.
Alexey Bataevad537bb2016-05-30 09:06:50 +00005184 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005185 const RecordDecl *KmpCmplrdataUD =
5186 (*FI)->getType()->getAsUnionType()->getDecl();
Alexey Bataevad537bb2016-05-30 09:06:50 +00005187 if (NeedsCleanup) {
5188 llvm::Value *DestructorFn = emitDestructorsFunction(
5189 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5190 KmpTaskTWithPrivatesQTy);
5191 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI);
5192 LValue DestructorsLV = CGF.EmitLValueForField(
5193 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
5194 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5195 DestructorFn, KmpRoutineEntryPtrTy),
5196 DestructorsLV);
5197 }
5198 // Set priority.
5199 if (Data.Priority.getInt()) {
5200 LValue Data2LV = CGF.EmitLValueForField(
5201 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
5202 LValue PriorityLV = CGF.EmitLValueForField(
5203 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
5204 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV);
5205 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005206 Result.NewTask = NewTask;
5207 Result.TaskEntry = TaskEntry;
5208 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
5209 Result.TDBase = TDBase;
5210 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
5211 return Result;
Alexey Bataev7292c292016-04-25 12:22:29 +00005212}
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005213
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005214void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
5215 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005216 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005217 QualType SharedsTy, Address Shareds,
5218 const Expr *IfCond,
5219 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005220 if (!CGF.HaveInsertPoint())
5221 return;
5222
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005223 TaskResultTy Result =
5224 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
5225 llvm::Value *NewTask = Result.NewTask;
James Y Knight9871db02019-02-05 16:42:33 +00005226 llvm::Function *TaskEntry = Result.TaskEntry;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005227 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy;
5228 LValue TDBase = Result.TDBase;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005229 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD;
5230 ASTContext &C = CGM.getContext();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005231 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00005232 Address DependenciesArray = Address::invalid();
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005233 unsigned NumDependencies = Data.Dependences.size();
John McCall7f416cc2015-09-08 08:05:57 +00005234 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005235 // Dependence kind for RTL.
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005236 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 };
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005237 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
5238 RecordDecl *KmpDependInfoRD;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005239 QualType FlagsTy =
5240 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005241 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
5242 if (KmpDependInfoTy.isNull()) {
5243 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
5244 KmpDependInfoRD->startDefinition();
5245 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
5246 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
5247 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
5248 KmpDependInfoRD->completeDefinition();
5249 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005250 } else {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005251 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005252 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005253 // Define type kmp_depend_info[<Dependences.size()>];
5254 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00005255 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Richard Smith772e2662019-10-04 01:25:59 +00005256 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005257 // kmp_depend_info[<Dependences.size()>] deps;
Alexey Bataev48591dd2016-04-20 04:01:36 +00005258 DependenciesArray =
5259 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005260 for (unsigned I = 0; I < NumDependencies; ++I) {
5261 const Expr *E = Data.Dependences[I].second;
5262 LValue Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005263 llvm::Value *Size;
5264 QualType Ty = E->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005265 if (const auto *ASE =
5266 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005267 LValue UpAddrLVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005268 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005269 llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32(
5270 UpAddrLVal.getPointer(CGF), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005271 llvm::Value *LowIntPtr =
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005272 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005273 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
5274 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005275 } else {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005276 Size = CGF.getTypeSize(Ty);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005277 }
5278 LValue Base = CGF.MakeAddrLValue(
James Y Knight751fe282019-02-09 22:22:28 +00005279 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005280 KmpDependInfoTy);
5281 // deps[i].base_addr = &<Dependences[i].second>;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005282 LValue BaseAddrLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005283 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00005284 CGF.EmitStoreOfScalar(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005285 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGF.IntPtrTy),
John McCall7f416cc2015-09-08 08:05:57 +00005286 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005287 // deps[i].len = sizeof(<Dependences[i].second>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005288 LValue LenLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005289 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
5290 CGF.EmitStoreOfScalar(Size, LenLVal);
5291 // deps[i].flags = <Dependences[i].first>;
5292 RTLDependenceKindTy DepKind;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005293 switch (Data.Dependences[I].first) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005294 case OMPC_DEPEND_in:
5295 DepKind = DepIn;
5296 break;
Alexey Bataev92e82f92015-11-23 13:33:42 +00005297 // Out and InOut dependencies must use the same code.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005298 case OMPC_DEPEND_out:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005299 case OMPC_DEPEND_inout:
5300 DepKind = DepInOut;
5301 break;
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005302 case OMPC_DEPEND_mutexinoutset:
5303 DepKind = DepMutexInOutSet;
5304 break;
Alexey Bataeveb482352015-12-18 05:05:56 +00005305 case OMPC_DEPEND_source:
Alexey Bataeva636c7f2015-12-23 10:27:45 +00005306 case OMPC_DEPEND_sink:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005307 case OMPC_DEPEND_unknown:
5308 llvm_unreachable("Unknown task dependence type");
5309 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005310 LValue FlagsLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005311 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
5312 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
5313 FlagsLVal);
5314 }
John McCall7f416cc2015-09-08 08:05:57 +00005315 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knightf5f1b0e2019-02-08 15:34:12 +00005316 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005317 }
5318
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005319 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev62b63b12015-03-10 07:28:44 +00005320 // libcall.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005321 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
5322 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
5323 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
5324 // list is not empty
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005325 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5326 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00005327 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
5328 llvm::Value *DepTaskArgs[7];
5329 if (NumDependencies) {
5330 DepTaskArgs[0] = UpLoc;
5331 DepTaskArgs[1] = ThreadID;
5332 DepTaskArgs[2] = NewTask;
5333 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
5334 DepTaskArgs[4] = DependenciesArray.getPointer();
5335 DepTaskArgs[5] = CGF.Builder.getInt32(0);
5336 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5337 }
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005338 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies,
5339 &TaskArgs,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005340 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005341 if (!Data.Tied) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005342 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005343 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
Alexey Bataev48591dd2016-04-20 04:01:36 +00005344 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
5345 }
John McCall7f416cc2015-09-08 08:05:57 +00005346 if (NumDependencies) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005347 CGF.EmitRuntimeCall(
Alexey Bataev48591dd2016-04-20 04:01:36 +00005348 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs);
John McCall7f416cc2015-09-08 08:05:57 +00005349 } else {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005350 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
John McCall7f416cc2015-09-08 08:05:57 +00005351 TaskArgs);
5352 }
Alexey Bataev48591dd2016-04-20 04:01:36 +00005353 // Check if parent region is untied and build return for untied task;
5354 if (auto *Region =
5355 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
5356 Region->emitUntiedSwitch(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00005357 };
John McCall7f416cc2015-09-08 08:05:57 +00005358
5359 llvm::Value *DepWaitTaskArgs[6];
5360 if (NumDependencies) {
5361 DepWaitTaskArgs[0] = UpLoc;
5362 DepWaitTaskArgs[1] = ThreadID;
5363 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
5364 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
5365 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
5366 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5367 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005368 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
Alexey Bataev3c595a62017-08-14 15:01:03 +00005369 NumDependencies, &DepWaitTaskArgs,
5370 Loc](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005371 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005372 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
5373 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
5374 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
5375 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
5376 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00005377 if (NumDependencies)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005378 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005379 DepWaitTaskArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005380 // Call proxy_task_entry(gtid, new_task);
Alexey Bataev3c595a62017-08-14 15:01:03 +00005381 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
5382 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005383 Action.Enter(CGF);
5384 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
Alexey Bataev3c595a62017-08-14 15:01:03 +00005385 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
Alexey Bataev2c7eee52017-08-04 19:10:54 +00005386 OutlinedFnArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005387 };
5388
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005389 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
5390 // kmp_task_t *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005391 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
5392 // kmp_task_t *new_task);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005393 RegionCodeGenTy RCG(CodeGen);
5394 CommonActionTy Action(
5395 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs,
5396 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs);
5397 RCG.setAction(Action);
5398 RCG(CGF);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005399 };
John McCall7f416cc2015-09-08 08:05:57 +00005400
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005401 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -05005402 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005403 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005404 RegionCodeGenTy ThenRCG(ThenCodeGen);
5405 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00005406 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005407}
5408
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005409void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
5410 const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005411 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005412 QualType SharedsTy, Address Shareds,
5413 const Expr *IfCond,
5414 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005415 if (!CGF.HaveInsertPoint())
5416 return;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005417 TaskResultTy Result =
5418 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005419 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev7292c292016-04-25 12:22:29 +00005420 // libcall.
5421 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
5422 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
5423 // sched, kmp_uint64 grainsize, void *task_dup);
5424 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5425 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
5426 llvm::Value *IfVal;
5427 if (IfCond) {
5428 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy,
5429 /*isSigned=*/true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005430 } else {
Alexey Bataev7292c292016-04-25 12:22:29 +00005431 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005432 }
Alexey Bataev7292c292016-04-25 12:22:29 +00005433
5434 LValue LBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005435 Result.TDBase,
5436 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005437 const auto *LBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005438 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005439 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF),
5440 LBLVal.getQuals(),
Alexey Bataev7292c292016-04-25 12:22:29 +00005441 /*IsInitializer=*/true);
5442 LValue UBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005443 Result.TDBase,
5444 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005445 const auto *UBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005446 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005447 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF),
5448 UBLVal.getQuals(),
Alexey Bataev7292c292016-04-25 12:22:29 +00005449 /*IsInitializer=*/true);
5450 LValue StLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005451 Result.TDBase,
5452 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005453 const auto *StVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005454 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005455 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF),
5456 StLVal.getQuals(),
Alexey Bataev7292c292016-04-25 12:22:29 +00005457 /*IsInitializer=*/true);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005458 // Store reductions address.
5459 LValue RedLVal = CGF.EmitLValueForField(
5460 Result.TDBase,
5461 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005462 if (Data.Reductions) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005463 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005464 } else {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005465 CGF.EmitNullInitialization(RedLVal.getAddress(CGF),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005466 CGF.getContext().VoidPtrTy);
5467 }
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005468 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
Alexey Bataev7292c292016-04-25 12:22:29 +00005469 llvm::Value *TaskArgs[] = {
Alexey Bataev33446032017-07-12 18:09:32 +00005470 UpLoc,
5471 ThreadID,
5472 Result.NewTask,
5473 IfVal,
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005474 LBLVal.getPointer(CGF),
5475 UBLVal.getPointer(CGF),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00005476 CGF.EmitLoadOfScalar(StLVal, Loc),
Alexey Bataevac6e4de2018-10-24 19:06:37 +00005477 llvm::ConstantInt::getSigned(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005478 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005479 llvm::ConstantInt::getSigned(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005480 CGF.IntTy, Data.Schedule.getPointer()
5481 ? Data.Schedule.getInt() ? NumTasks : Grainsize
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005482 : NoSchedule),
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005483 Data.Schedule.getPointer()
5484 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty,
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005485 /*isSigned=*/false)
5486 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0),
Alexey Bataev33446032017-07-12 18:09:32 +00005487 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5488 Result.TaskDupFn, CGF.VoidPtrTy)
5489 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)};
Alexey Bataev7292c292016-04-25 12:22:29 +00005490 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs);
5491}
5492
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005493/// Emit reduction operation for each element of array (required for
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005494/// array sections) LHS op = RHS.
5495/// \param Type Type of array.
5496/// \param LHSVar Variable on the left side of the reduction operation
5497/// (references element of array in original variable).
5498/// \param RHSVar Variable on the right side of the reduction operation
5499/// (references element of array in original variable).
5500/// \param RedOpGen Generator of reduction operation with use of LHSVar and
5501/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00005502static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005503 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
5504 const VarDecl *RHSVar,
5505 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
5506 const Expr *, const Expr *)> &RedOpGen,
5507 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
5508 const Expr *UpExpr = nullptr) {
5509 // Perform element-by-element initialization.
5510 QualType ElementTy;
5511 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
5512 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
5513
5514 // Drill down to the base element type on both arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005515 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
5516 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005517
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005518 llvm::Value *RHSBegin = RHSAddr.getPointer();
5519 llvm::Value *LHSBegin = LHSAddr.getPointer();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005520 // Cast from pointer to array type to pointer to single element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005521 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005522 // The basic structure here is a while-do loop.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005523 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
5524 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
5525 llvm::Value *IsEmpty =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005526 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
5527 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
5528
5529 // Enter the loop body, making that address the current address.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005530 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005531 CGF.EmitBlock(BodyBB);
5532
5533 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
5534
5535 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
5536 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
5537 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
5538 Address RHSElementCurrent =
5539 Address(RHSElementPHI,
5540 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5541
5542 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
5543 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
5544 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
5545 Address LHSElementCurrent =
5546 Address(LHSElementPHI,
5547 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5548
5549 // Emit copy.
5550 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005551 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; });
5552 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005553 Scope.Privatize();
5554 RedOpGen(CGF, XExpr, EExpr, UpExpr);
5555 Scope.ForceCleanup();
5556
5557 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005558 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005559 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005560 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005561 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
5562 // Check whether we've reached the end.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005563 llvm::Value *Done =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005564 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
5565 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
5566 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
5567 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
5568
5569 // Done.
5570 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
5571}
5572
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005573/// Emit reduction combiner. If the combiner is a simple expression emit it as
5574/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
5575/// UDR combiner function.
5576static void emitReductionCombiner(CodeGenFunction &CGF,
5577 const Expr *ReductionOp) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005578 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
5579 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
5580 if (const auto *DRE =
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005581 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005582 if (const auto *DRD =
5583 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005584 std::pair<llvm::Function *, llvm::Function *> Reduction =
5585 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
5586 RValue Func = RValue::get(Reduction.first);
5587 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
5588 CGF.EmitIgnoredExpr(ReductionOp);
5589 return;
5590 }
5591 CGF.EmitIgnoredExpr(ReductionOp);
5592}
5593
James Y Knight9871db02019-02-05 16:42:33 +00005594llvm::Function *CGOpenMPRuntime::emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005595 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates,
5596 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
5597 ArrayRef<const Expr *> ReductionOps) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005598 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005599
5600 // void reduction_func(void *LHSArg, void *RHSArg);
5601 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005602 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5603 ImplicitParamDecl::Other);
5604 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5605 ImplicitParamDecl::Other);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005606 Args.push_back(&LHSArg);
5607 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005608 const auto &CGFI =
5609 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00005610 std::string Name = getName({"omp", "reduction", "reduction_func"});
5611 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
5612 llvm::GlobalValue::InternalLinkage, Name,
5613 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00005614 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00005615 Fn->setDoesNotRecurse();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005616 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005617 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005618
5619 // Dst = (void*[n])(LHSArg);
5620 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00005621 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5622 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
5623 ArgsType), CGF.getPointerAlign());
5624 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5625 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
5626 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005627
5628 // ...
5629 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
5630 // ...
5631 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005632 auto IPriv = Privates.begin();
5633 unsigned Idx = 0;
5634 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005635 const auto *RHSVar =
5636 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
5637 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005638 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005639 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005640 const auto *LHSVar =
5641 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
5642 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005643 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005644 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005645 QualType PrivTy = (*IPriv)->getType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00005646 if (PrivTy->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005647 // Get array size and emit VLA type.
5648 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005649 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005650 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005651 const VariableArrayType *VLA =
5652 CGF.getContext().getAsVariableArrayType(PrivTy);
5653 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005654 CodeGenFunction::OpaqueValueMapping OpaqueMap(
Alexey Bataev1189bd02016-01-26 12:20:39 +00005655 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005656 CGF.EmitVariablyModifiedType(PrivTy);
5657 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005658 }
5659 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005660 IPriv = Privates.begin();
5661 auto ILHS = LHSExprs.begin();
5662 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005663 for (const Expr *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005664 if ((*IPriv)->getType()->isArrayType()) {
5665 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005666 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5667 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005668 EmitOMPAggregateReduction(
5669 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5670 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5671 emitReductionCombiner(CGF, E);
5672 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005673 } else {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005674 // Emit reduction for array subscript or single variable.
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005675 emitReductionCombiner(CGF, E);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005676 }
Richard Trieucc3949d2016-02-18 22:34:54 +00005677 ++IPriv;
5678 ++ILHS;
5679 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005680 }
5681 Scope.ForceCleanup();
5682 CGF.FinishFunction();
5683 return Fn;
5684}
5685
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005686void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF,
5687 const Expr *ReductionOp,
5688 const Expr *PrivateRef,
5689 const DeclRefExpr *LHS,
5690 const DeclRefExpr *RHS) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005691 if (PrivateRef->getType()->isArrayType()) {
5692 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005693 const auto *LHSVar = cast<VarDecl>(LHS->getDecl());
5694 const auto *RHSVar = cast<VarDecl>(RHS->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005695 EmitOMPAggregateReduction(
5696 CGF, PrivateRef->getType(), LHSVar, RHSVar,
5697 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5698 emitReductionCombiner(CGF, ReductionOp);
5699 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005700 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005701 // Emit reduction for array subscript or single variable.
5702 emitReductionCombiner(CGF, ReductionOp);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005703 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005704}
5705
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005706void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005707 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005708 ArrayRef<const Expr *> LHSExprs,
5709 ArrayRef<const Expr *> RHSExprs,
5710 ArrayRef<const Expr *> ReductionOps,
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005711 ReductionOptionsTy Options) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00005712 if (!CGF.HaveInsertPoint())
5713 return;
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005714
5715 bool WithNowait = Options.WithNowait;
5716 bool SimpleReduction = Options.SimpleReduction;
5717
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005718 // Next code should be emitted for reduction:
5719 //
5720 // static kmp_critical_name lock = { 0 };
5721 //
5722 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
5723 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
5724 // ...
5725 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
5726 // *(Type<n>-1*)rhs[<n>-1]);
5727 // }
5728 //
5729 // ...
5730 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
5731 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5732 // RedList, reduce_func, &<lock>)) {
5733 // case 1:
5734 // ...
5735 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5736 // ...
5737 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5738 // break;
5739 // case 2:
5740 // ...
5741 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5742 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00005743 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005744 // break;
5745 // default:;
5746 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005747 //
5748 // if SimpleReduction is true, only the next code is generated:
5749 // ...
5750 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5751 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005752
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005753 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005754
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005755 if (SimpleReduction) {
5756 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005757 auto IPriv = Privates.begin();
5758 auto ILHS = LHSExprs.begin();
5759 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005760 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005761 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5762 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005763 ++IPriv;
5764 ++ILHS;
5765 ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005766 }
5767 return;
5768 }
5769
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005770 // 1. Build a list of reduction variables.
5771 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005772 auto Size = RHSExprs.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005773 for (const Expr *E : Privates) {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005774 if (E->getType()->isVariablyModifiedType())
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005775 // Reserve place for array size.
5776 ++Size;
5777 }
5778 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005779 QualType ReductionArrayTy =
Richard Smith772e2662019-10-04 01:25:59 +00005780 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005781 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00005782 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005783 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005784 auto IPriv = Privates.begin();
5785 unsigned Idx = 0;
5786 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
James Y Knight751fe282019-02-09 22:22:28 +00005787 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
John McCall7f416cc2015-09-08 08:05:57 +00005788 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005789 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005790 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy),
John McCall7f416cc2015-09-08 08:05:57 +00005791 Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005792 if ((*IPriv)->getType()->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005793 // Store array size.
5794 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005795 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005796 llvm::Value *Size = CGF.Builder.CreateIntCast(
5797 CGF.getVLASize(
5798 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
Sander de Smalen891af03a2018-02-03 13:55:59 +00005799 .NumElts,
Alexey Bataev1189bd02016-01-26 12:20:39 +00005800 CGF.SizeTy, /*isSigned=*/false);
5801 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
5802 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005803 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005804 }
5805
5806 // 2. Emit reduce_func().
James Y Knight9871db02019-02-05 16:42:33 +00005807 llvm::Function *ReductionFn = emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005808 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
5809 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005810
5811 // 3. Create static kmp_critical_name lock = { 0 };
Alexey Bataev18fa2322018-05-02 14:20:50 +00005812 std::string Name = getName({"reduction"});
5813 llvm::Value *Lock = getCriticalRegionLock(Name);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005814
5815 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5816 // RedList, reduce_func, &<lock>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005817 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
5818 llvm::Value *ThreadId = getThreadID(CGF, Loc);
5819 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
5820 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Samuel Antao4c8035b2016-12-12 18:00:20 +00005821 ReductionList.getPointer(), CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005822 llvm::Value *Args[] = {
5823 IdentTLoc, // ident_t *<loc>
5824 ThreadId, // i32 <gtid>
5825 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
5826 ReductionArrayTySize, // size_type sizeof(RedList)
5827 RL, // void *RedList
5828 ReductionFn, // void (*) (void *, void *) <reduce_func>
5829 Lock // kmp_critical_name *&<lock>
5830 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005831 llvm::Value *Res = CGF.EmitRuntimeCall(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005832 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
5833 : OMPRTL__kmpc_reduce),
5834 Args);
5835
5836 // 5. Build switch(res)
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005837 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
5838 llvm::SwitchInst *SwInst =
5839 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005840
5841 // 6. Build case 1:
5842 // ...
5843 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5844 // ...
5845 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5846 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005847 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005848 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
5849 CGF.EmitBlock(Case1BB);
5850
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005851 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5852 llvm::Value *EndArgs[] = {
5853 IdentTLoc, // ident_t *<loc>
5854 ThreadId, // i32 <gtid>
5855 Lock // kmp_critical_name *&<lock>
5856 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005857 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5858 CodeGenFunction &CGF, PrePostActionTy &Action) {
5859 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005860 auto IPriv = Privates.begin();
5861 auto ILHS = LHSExprs.begin();
5862 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005863 for (const Expr *E : ReductionOps) {
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005864 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5865 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005866 ++IPriv;
5867 ++ILHS;
5868 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005869 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005870 };
5871 RegionCodeGenTy RCG(CodeGen);
5872 CommonActionTy Action(
5873 nullptr, llvm::None,
5874 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
5875 : OMPRTL__kmpc_end_reduce),
5876 EndArgs);
5877 RCG.setAction(Action);
5878 RCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005879
5880 CGF.EmitBranch(DefaultBB);
5881
5882 // 7. Build case 2:
5883 // ...
5884 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5885 // ...
5886 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005887 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005888 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
5889 CGF.EmitBlock(Case2BB);
5890
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005891 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
5892 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005893 auto ILHS = LHSExprs.begin();
5894 auto IRHS = RHSExprs.begin();
5895 auto IPriv = Privates.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005896 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005897 const Expr *XExpr = nullptr;
5898 const Expr *EExpr = nullptr;
5899 const Expr *UpExpr = nullptr;
5900 BinaryOperatorKind BO = BO_Comma;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005901 if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005902 if (BO->getOpcode() == BO_Assign) {
5903 XExpr = BO->getLHS();
5904 UpExpr = BO->getRHS();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005905 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005906 }
5907 // Try to emit update expression as a simple atomic.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005908 const Expr *RHSExpr = UpExpr;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005909 if (RHSExpr) {
5910 // Analyze RHS part of the whole expression.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005911 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005912 RHSExpr->IgnoreParenImpCasts())) {
5913 // If this is a conditional operator, analyze its condition for
5914 // min/max reduction operator.
5915 RHSExpr = ACO->getCond();
Alexey Bataev69a47792015-05-07 03:54:03 +00005916 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005917 if (const auto *BORHS =
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005918 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
5919 EExpr = BORHS->getRHS();
5920 BO = BORHS->getOpcode();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005921 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005922 }
5923 if (XExpr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005924 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005925 auto &&AtomicRedGen = [BO, VD,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005926 Loc](CodeGenFunction &CGF, const Expr *XExpr,
5927 const Expr *EExpr, const Expr *UpExpr) {
5928 LValue X = CGF.EmitLValue(XExpr);
5929 RValue E;
5930 if (EExpr)
5931 E = CGF.EmitAnyExpr(EExpr);
5932 CGF.EmitOMPAtomicSimpleUpdateExpr(
JF Bastien92f4ef12016-04-06 17:26:42 +00005933 X, E, BO, /*IsXLHSInRHSPart=*/true,
5934 llvm::AtomicOrdering::Monotonic, Loc,
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005935 [&CGF, UpExpr, VD, Loc](RValue XRValue) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005936 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5937 PrivateScope.addPrivate(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005938 VD, [&CGF, VD, XRValue, Loc]() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005939 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5940 CGF.emitOMPSimpleStore(
5941 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
5942 VD->getType().getNonReferenceType(), Loc);
5943 return LHSTemp;
5944 });
5945 (void)PrivateScope.Privatize();
5946 return CGF.EmitAnyExpr(UpExpr);
5947 });
5948 };
5949 if ((*IPriv)->getType()->isArrayType()) {
5950 // Emit atomic reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005951 const auto *RHSVar =
5952 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005953 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
5954 AtomicRedGen, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005955 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005956 // Emit atomic reduction for array subscript or single variable.
5957 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005958 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005959 } else {
5960 // Emit as a critical region.
5961 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
Alexey Bataev18fa2322018-05-02 14:20:50 +00005962 const Expr *, const Expr *) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005963 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev18fa2322018-05-02 14:20:50 +00005964 std::string Name = RT.getName({"atomic_reduction"});
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005965 RT.emitCriticalRegion(
Alexey Bataev18fa2322018-05-02 14:20:50 +00005966 CGF, Name,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005967 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
5968 Action.Enter(CGF);
5969 emitReductionCombiner(CGF, E);
5970 },
5971 Loc);
5972 };
5973 if ((*IPriv)->getType()->isArrayType()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005974 const auto *LHSVar =
5975 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5976 const auto *RHSVar =
5977 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005978 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5979 CritRedGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005980 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005981 CritRedGen(CGF, nullptr, nullptr, nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005982 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005983 }
Richard Trieucc3949d2016-02-18 22:34:54 +00005984 ++ILHS;
5985 ++IRHS;
5986 ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005987 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005988 };
5989 RegionCodeGenTy AtomicRCG(AtomicCodeGen);
5990 if (!WithNowait) {
5991 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
5992 llvm::Value *EndArgs[] = {
5993 IdentTLoc, // ident_t *<loc>
5994 ThreadId, // i32 <gtid>
5995 Lock // kmp_critical_name *&<lock>
5996 };
5997 CommonActionTy Action(nullptr, llvm::None,
5998 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
5999 EndArgs);
6000 AtomicRCG.setAction(Action);
6001 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006002 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006003 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006004 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00006005
6006 CGF.EmitBranch(DefaultBB);
6007 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
6008}
6009
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006010/// Generates unique name for artificial threadprivate variables.
Alexey Bataev1c44e152018-03-06 18:59:43 +00006011/// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>"
6012static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix,
6013 const Expr *Ref) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006014 SmallString<256> Buffer;
6015 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev1c44e152018-03-06 18:59:43 +00006016 const clang::DeclRefExpr *DE;
6017 const VarDecl *D = ::getBaseDecl(Ref, DE);
6018 if (!D)
6019 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl());
6020 D = D->getCanonicalDecl();
Alexey Bataev18fa2322018-05-02 14:20:50 +00006021 std::string Name = CGM.getOpenMPRuntime().getName(
6022 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)});
6023 Out << Prefix << Name << "_"
Stephen Kellyf2ceec42018-08-09 21:08:08 +00006024 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006025 return Out.str();
6026}
6027
6028/// Emits reduction initializer function:
6029/// \code
6030/// void @.red_init(void* %arg) {
6031/// %0 = bitcast void* %arg to <type>*
6032/// store <type> <init>, <type>* %0
6033/// ret void
6034/// }
6035/// \endcode
6036static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM,
6037 SourceLocation Loc,
6038 ReductionCodeGen &RCG, unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006039 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006040 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006041 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6042 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006043 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006044 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006045 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006046 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006047 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006048 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006049 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006050 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006051 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006052 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006053 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006054 Address PrivateAddr = CGF.EmitLoadOfPointer(
6055 CGF.GetAddrOfLocalVar(&Param),
6056 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6057 llvm::Value *Size = nullptr;
6058 // If the size of the reduction item is non-constant, load it from global
6059 // threadprivate variable.
6060 if (RCG.getSizes(N).second) {
6061 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6062 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006063 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006064 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6065 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006066 }
6067 RCG.emitAggregateType(CGF, N, Size);
6068 LValue SharedLVal;
6069 // If initializer uses initializer from declare reduction construct, emit a
6070 // pointer to the address of the original reduction item (reuired by reduction
6071 // initializer)
6072 if (RCG.usesReductionInitializer(N)) {
6073 Address SharedAddr =
6074 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6075 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006076 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataev21dab122018-03-09 15:20:30 +00006077 SharedAddr = CGF.EmitLoadOfPointer(
6078 SharedAddr,
6079 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006080 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy);
6081 } else {
6082 SharedLVal = CGF.MakeNaturalAlignAddrLValue(
6083 llvm::ConstantPointerNull::get(CGM.VoidPtrTy),
6084 CGM.getContext().VoidPtrTy);
6085 }
6086 // Emit the initializer:
6087 // %0 = bitcast void* %arg to <type>*
6088 // store <type> <init>, <type>* %0
6089 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal,
6090 [](CodeGenFunction &) { return false; });
6091 CGF.FinishFunction();
6092 return Fn;
6093}
6094
6095/// Emits reduction combiner function:
6096/// \code
6097/// void @.red_comb(void* %arg0, void* %arg1) {
6098/// %lhs = bitcast void* %arg0 to <type>*
6099/// %rhs = bitcast void* %arg1 to <type>*
6100/// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs)
6101/// store <type> %2, <type>* %lhs
6102/// ret void
6103/// }
6104/// \endcode
6105static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM,
6106 SourceLocation Loc,
6107 ReductionCodeGen &RCG, unsigned N,
6108 const Expr *ReductionOp,
6109 const Expr *LHS, const Expr *RHS,
6110 const Expr *PrivateRef) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006111 ASTContext &C = CGM.getContext();
6112 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl());
6113 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006114 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006115 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
6116 C.VoidPtrTy, ImplicitParamDecl::Other);
6117 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6118 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006119 Args.emplace_back(&ParamInOut);
6120 Args.emplace_back(&ParamIn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006121 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006122 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006123 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006124 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006125 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006126 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006127 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006128 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006129 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006130 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006131 llvm::Value *Size = nullptr;
6132 // If the size of the reduction item is non-constant, load it from global
6133 // threadprivate variable.
6134 if (RCG.getSizes(N).second) {
6135 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6136 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006137 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006138 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6139 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006140 }
6141 RCG.emitAggregateType(CGF, N, Size);
6142 // Remap lhs and rhs variables to the addresses of the function arguments.
6143 // %lhs = bitcast void* %arg0 to <type>*
6144 // %rhs = bitcast void* %arg1 to <type>*
6145 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006146 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006147 // Pull out the pointer to the variable.
6148 Address PtrAddr = CGF.EmitLoadOfPointer(
6149 CGF.GetAddrOfLocalVar(&ParamInOut),
6150 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6151 return CGF.Builder.CreateElementBitCast(
6152 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType()));
6153 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006154 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006155 // Pull out the pointer to the variable.
6156 Address PtrAddr = CGF.EmitLoadOfPointer(
6157 CGF.GetAddrOfLocalVar(&ParamIn),
6158 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6159 return CGF.Builder.CreateElementBitCast(
6160 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType()));
6161 });
6162 PrivateScope.Privatize();
6163 // Emit the combiner body:
6164 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs)
6165 // store <type> %2, <type>* %lhs
6166 CGM.getOpenMPRuntime().emitSingleReductionCombiner(
6167 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS),
6168 cast<DeclRefExpr>(RHS));
6169 CGF.FinishFunction();
6170 return Fn;
6171}
6172
6173/// Emits reduction finalizer function:
6174/// \code
6175/// void @.red_fini(void* %arg) {
6176/// %0 = bitcast void* %arg to <type>*
6177/// <destroy>(<type>* %0)
6178/// ret void
6179/// }
6180/// \endcode
6181static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM,
6182 SourceLocation Loc,
6183 ReductionCodeGen &RCG, unsigned N) {
6184 if (!RCG.needCleanups(N))
6185 return nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006186 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006187 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006188 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6189 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006190 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006191 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006192 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006193 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006194 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006195 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006196 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006197 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006198 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006199 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006200 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006201 Address PrivateAddr = CGF.EmitLoadOfPointer(
6202 CGF.GetAddrOfLocalVar(&Param),
6203 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6204 llvm::Value *Size = nullptr;
6205 // If the size of the reduction item is non-constant, load it from global
6206 // threadprivate variable.
6207 if (RCG.getSizes(N).second) {
6208 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6209 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006210 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006211 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6212 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006213 }
6214 RCG.emitAggregateType(CGF, N, Size);
6215 // Emit the finalizer body:
6216 // <destroy>(<type>* %0)
6217 RCG.emitCleanups(CGF, N, PrivateAddr);
Adrian Prantlce7d3592019-12-05 12:26:16 -08006218 CGF.FinishFunction(Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006219 return Fn;
6220}
6221
6222llvm::Value *CGOpenMPRuntime::emitTaskReductionInit(
6223 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
6224 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
6225 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty())
6226 return nullptr;
6227
6228 // Build typedef struct:
6229 // kmp_task_red_input {
6230 // void *reduce_shar; // shared reduction item
6231 // size_t reduce_size; // size of data item
6232 // void *reduce_init; // data initialization routine
6233 // void *reduce_fini; // data finalization routine
6234 // void *reduce_comb; // data combiner routine
6235 // kmp_task_red_flags_t flags; // flags for additional info from compiler
6236 // } kmp_task_red_input_t;
6237 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006238 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t");
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006239 RD->startDefinition();
6240 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6241 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType());
6242 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6243 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6244 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6245 const FieldDecl *FlagsFD = addFieldToRecordDecl(
6246 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false));
6247 RD->completeDefinition();
6248 QualType RDType = C.getRecordType(RD);
6249 unsigned Size = Data.ReductionVars.size();
6250 llvm::APInt ArraySize(/*numBits=*/64, Size);
6251 QualType ArrayRDType = C.getConstantArrayType(
Richard Smith772e2662019-10-04 01:25:59 +00006252 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006253 // kmp_task_red_input_t .rd_input.[Size];
6254 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input.");
6255 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies,
6256 Data.ReductionOps);
6257 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) {
6258 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt];
6259 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0),
6260 llvm::ConstantInt::get(CGM.SizeTy, Cnt)};
6261 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP(
6262 TaskRedInput.getPointer(), Idxs,
6263 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc,
6264 ".rd_input.gep.");
6265 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType);
6266 // ElemLVal.reduce_shar = &Shareds[Cnt];
6267 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD);
6268 RCG.emitSharedLValue(CGF, Cnt);
6269 llvm::Value *CastedShared =
Akira Hatanakaf139ae32019-12-03 15:17:01 -08006270 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006271 CGF.EmitStoreOfScalar(CastedShared, SharedLVal);
6272 RCG.emitAggregateType(CGF, Cnt);
6273 llvm::Value *SizeValInChars;
6274 llvm::Value *SizeVal;
6275 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt);
6276 // We use delayed creation/initialization for VLAs, array sections and
6277 // custom reduction initializations. It is required because runtime does not
6278 // provide the way to pass the sizes of VLAs/array sections to
6279 // initializer/combiner/finalizer functions and does not pass the pointer to
6280 // original reduction item to the initializer. Instead threadprivate global
6281 // variables are used to store these values and use them in the functions.
6282 bool DelayedCreation = !!SizeVal;
6283 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy,
6284 /*isSigned=*/false);
6285 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD);
6286 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal);
6287 // ElemLVal.reduce_init = init;
6288 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD);
6289 llvm::Value *InitAddr =
6290 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt));
6291 CGF.EmitStoreOfScalar(InitAddr, InitLVal);
6292 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt);
6293 // ElemLVal.reduce_fini = fini;
6294 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD);
6295 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt);
6296 llvm::Value *FiniAddr = Fini
6297 ? CGF.EmitCastToVoidPtr(Fini)
6298 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy);
6299 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal);
6300 // ElemLVal.reduce_comb = comb;
6301 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD);
6302 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction(
6303 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt],
6304 RHSExprs[Cnt], Data.ReductionCopies[Cnt]));
6305 CGF.EmitStoreOfScalar(CombAddr, CombLVal);
6306 // ElemLVal.flags = 0;
6307 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD);
6308 if (DelayedCreation) {
6309 CGF.EmitStoreOfScalar(
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006310 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006311 FlagsLVal);
6312 } else
Akira Hatanakaf139ae32019-12-03 15:17:01 -08006313 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF),
6314 FlagsLVal.getType());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006315 }
6316 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void
6317 // *data);
6318 llvm::Value *Args[] = {
6319 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6320 /*isSigned=*/true),
6321 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true),
6322 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(),
6323 CGM.VoidPtrTy)};
6324 return CGF.EmitRuntimeCall(
6325 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args);
6326}
6327
6328void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
6329 SourceLocation Loc,
6330 ReductionCodeGen &RCG,
6331 unsigned N) {
6332 auto Sizes = RCG.getSizes(N);
6333 // Emit threadprivate global variable if the type is non-constant
6334 // (Sizes.second = nullptr).
6335 if (Sizes.second) {
6336 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy,
6337 /*isSigned=*/false);
6338 Address SizeAddr = getAddrOfArtificialThreadPrivate(
6339 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006340 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006341 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false);
6342 }
6343 // Store address of the original reduction item if custom initializer is used.
6344 if (RCG.usesReductionInitializer(N)) {
6345 Address SharedAddr = getAddrOfArtificialThreadPrivate(
6346 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006347 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006348 CGF.Builder.CreateStore(
6349 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08006350 RCG.getSharedLValue(N).getPointer(CGF), CGM.VoidPtrTy),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006351 SharedAddr, /*IsVolatile=*/false);
6352 }
6353}
6354
6355Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF,
6356 SourceLocation Loc,
6357 llvm::Value *ReductionsPtr,
6358 LValue SharedLVal) {
6359 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
6360 // *d);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08006361 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc),
6362 CGM.IntTy,
6363 /*isSigned=*/true),
6364 ReductionsPtr,
6365 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6366 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)};
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006367 return Address(
6368 CGF.EmitRuntimeCall(
6369 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args),
6370 SharedLVal.getAlignment());
6371}
6372
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006373void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
6374 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006375 if (!CGF.HaveInsertPoint())
6376 return;
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006377 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
6378 // global_tid);
6379 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
6380 // Ignore return result until untied tasks are supported.
6381 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00006382 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
6383 Region->emitUntiedSwitch(CGF);
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006384}
6385
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006386void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006387 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00006388 const RegionCodeGenTy &CodeGen,
6389 bool HasCancel) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006390 if (!CGF.HaveInsertPoint())
6391 return;
Alexey Bataev25e5b442015-09-15 12:52:43 +00006392 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006393 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00006394}
6395
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006396namespace {
6397enum RTCancelKind {
6398 CancelNoreq = 0,
6399 CancelParallel = 1,
6400 CancelLoop = 2,
6401 CancelSections = 3,
6402 CancelTaskgroup = 4
6403};
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00006404} // anonymous namespace
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006405
6406static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
6407 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00006408 if (CancelRegion == OMPD_parallel)
6409 CancelKind = CancelParallel;
6410 else if (CancelRegion == OMPD_for)
6411 CancelKind = CancelLoop;
6412 else if (CancelRegion == OMPD_sections)
6413 CancelKind = CancelSections;
6414 else {
6415 assert(CancelRegion == OMPD_taskgroup);
6416 CancelKind = CancelTaskgroup;
6417 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006418 return CancelKind;
6419}
6420
6421void CGOpenMPRuntime::emitCancellationPointCall(
6422 CodeGenFunction &CGF, SourceLocation Loc,
6423 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006424 if (!CGF.HaveInsertPoint())
6425 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006426 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
6427 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006428 if (auto *OMPRegionInfo =
6429 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Jonas Hahnfeldb07931f2017-02-17 18:32:58 +00006430 // For 'cancellation point taskgroup', the task region info may not have a
6431 // cancel. This may instead happen in another adjacent task.
6432 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006433 llvm::Value *Args[] = {
6434 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
6435 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006436 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006437 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006438 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
6439 // if (__kmpc_cancellationpoint()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006440 // exit from construct;
6441 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006442 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6443 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6444 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006445 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6446 CGF.EmitBlock(ExitBB);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006447 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006448 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev25e5b442015-09-15 12:52:43 +00006449 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006450 CGF.EmitBranchThroughCleanup(CancelDest);
6451 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6452 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006453 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006454}
6455
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006456void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00006457 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006458 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006459 if (!CGF.HaveInsertPoint())
6460 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006461 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
6462 // kmp_int32 cncl_kind);
6463 if (auto *OMPRegionInfo =
6464 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006465 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF,
6466 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006467 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev87933c72015-09-18 08:07:34 +00006468 llvm::Value *Args[] = {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006469 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
Alexey Bataev87933c72015-09-18 08:07:34 +00006470 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
6471 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006472 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006473 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
Alexey Bataev87933c72015-09-18 08:07:34 +00006474 // if (__kmpc_cancel()) {
Alexey Bataev87933c72015-09-18 08:07:34 +00006475 // exit from construct;
6476 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006477 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6478 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6479 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev87933c72015-09-18 08:07:34 +00006480 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6481 CGF.EmitBlock(ExitBB);
Alexey Bataev87933c72015-09-18 08:07:34 +00006482 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006483 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev87933c72015-09-18 08:07:34 +00006484 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6485 CGF.EmitBranchThroughCleanup(CancelDest);
6486 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6487 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006488 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -05006489 emitIfClause(CGF, IfCond, ThenGen,
6490 [](CodeGenFunction &, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006491 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006492 RegionCodeGenTy ThenRCG(ThenGen);
6493 ThenRCG(CGF);
6494 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006495 }
6496}
Samuel Antaobed3c462015-10-02 16:14:20 +00006497
Samuel Antaoee8fb302016-01-06 13:42:12 +00006498void CGOpenMPRuntime::emitTargetOutlinedFunction(
6499 const OMPExecutableDirective &D, StringRef ParentName,
6500 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006501 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00006502 assert(!ParentName.empty() && "Invalid target region parent name!");
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00006503 HasEmittedTargetRegion = true;
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006504 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
6505 IsOffloadEntry, CodeGen);
6506}
6507
6508void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
6509 const OMPExecutableDirective &D, StringRef ParentName,
6510 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6511 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antao2de62b02016-02-13 23:35:10 +00006512 // Create a unique name for the entry function using the source location
6513 // information of the current target region. The name will be something like:
Samuel Antaoee8fb302016-01-06 13:42:12 +00006514 //
Samuel Antao2de62b02016-02-13 23:35:10 +00006515 // __omp_offloading_DD_FFFF_PP_lBB
Samuel Antaoee8fb302016-01-06 13:42:12 +00006516 //
6517 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
Samuel Antao2de62b02016-02-13 23:35:10 +00006518 // mangled name of the function that encloses the target region and BB is the
6519 // line number of the target region.
Samuel Antaoee8fb302016-01-06 13:42:12 +00006520
6521 unsigned DeviceID;
6522 unsigned FileID;
6523 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00006524 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00006525 Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006526 SmallString<64> EntryFnName;
6527 {
6528 llvm::raw_svector_ostream OS(EntryFnName);
Samuel Antao2de62b02016-02-13 23:35:10 +00006529 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
6530 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00006531 }
6532
Alexey Bataev475a7442018-01-12 19:39:11 +00006533 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006534
Samuel Antaobed3c462015-10-02 16:14:20 +00006535 CodeGenFunction CGF(CGM, true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006536 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
Samuel Antaobed3c462015-10-02 16:14:20 +00006537 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006538
Samuel Antao6d004262016-06-16 18:39:34 +00006539 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006540
6541 // If this target outline function is not an offload entry, we don't need to
6542 // register it.
6543 if (!IsOffloadEntry)
6544 return;
6545
6546 // The target region ID is used by the runtime library to identify the current
6547 // target region, so it only has to be unique and not necessarily point to
6548 // anything. It could be the pointer to the outlined function that implements
6549 // the target region, but we aren't using that so that the compiler doesn't
6550 // need to keep that, and could therefore inline the host function if proven
6551 // worthwhile during optimization. In the other hand, if emitting code for the
6552 // device, the ID has to be the function address so that it can retrieved from
6553 // the offloading entry and launched by the runtime library. We also mark the
6554 // outlined function to have external linkage in case we are emitting code for
6555 // the device, because these functions will be entry points to the device.
6556
6557 if (CGM.getLangOpts().OpenMPIsDevice) {
6558 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
Alexey Bataev9a700172018-05-08 14:16:57 +00006559 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Rafael Espindolacbca4872018-01-11 22:15:12 +00006560 OutlinedFn->setDSOLocal(false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006561 } else {
Alexey Bataevc15ea702018-05-09 18:02:37 +00006562 std::string Name = getName({EntryFnName, "region_id"});
Samuel Antaoee8fb302016-01-06 13:42:12 +00006563 OutlinedFnID = new llvm::GlobalVariable(
6564 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
Alexey Bataev9a700172018-05-08 14:16:57 +00006565 llvm::GlobalValue::WeakAnyLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006566 llvm::Constant::getNullValue(CGM.Int8Ty), Name);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006567 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00006568
6569 // Register the information for the entry associated with this target region.
6570 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
Samuel Antaof83efdb2017-01-05 16:02:49 +00006571 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID,
Alexey Bataev03f270c2018-03-30 18:31:07 +00006572 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion);
Samuel Antaobed3c462015-10-02 16:14:20 +00006573}
6574
Alexey Bataev5c427362019-04-10 19:11:33 +00006575/// Checks if the expression is constant or does not have non-trivial function
6576/// calls.
6577static bool isTrivial(ASTContext &Ctx, const Expr * E) {
6578 // We can skip constant expressions.
6579 // We can skip expressions with trivial calls or simple expressions.
6580 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) ||
6581 !E->hasNonTrivialCall(Ctx)) &&
6582 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true);
6583}
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006584
Alexey Bataev5c427362019-04-10 19:11:33 +00006585const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx,
6586 const Stmt *Body) {
6587 const Stmt *Child = Body->IgnoreContainers();
6588 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) {
6589 Child = nullptr;
6590 for (const Stmt *S : C->body()) {
6591 if (const auto *E = dyn_cast<Expr>(S)) {
6592 if (isTrivial(Ctx, E))
6593 continue;
6594 }
6595 // Some of the statements can be ignored.
6596 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) ||
6597 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S))
6598 continue;
6599 // Analyze declarations.
6600 if (const auto *DS = dyn_cast<DeclStmt>(S)) {
6601 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) {
6602 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6603 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6604 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6605 isa<UsingDirectiveDecl>(D) ||
6606 isa<OMPDeclareReductionDecl>(D) ||
6607 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6608 return true;
6609 const auto *VD = dyn_cast<VarDecl>(D);
6610 if (!VD)
6611 return false;
6612 return VD->isConstexpr() ||
6613 ((VD->getType().isTrivialType(Ctx) ||
6614 VD->getType()->isReferenceType()) &&
6615 (!VD->hasInit() || isTrivial(Ctx, VD->getInit())));
6616 }))
6617 continue;
6618 }
6619 // Found multiple children - cannot get the one child only.
6620 if (Child)
6621 return nullptr;
6622 Child = S;
6623 }
6624 if (Child)
6625 Child = Child->IgnoreContainers();
6626 }
6627 return Child;
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006628}
6629
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006630/// Emit the number of teams for a target directive. Inspect the num_teams
6631/// clause associated with a teams construct combined or closely nested
6632/// with the target directive.
6633///
6634/// Emit a team of size one for directives such as 'target parallel' that
6635/// have no associated teams construct.
6636///
6637/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006638static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006639emitNumTeamsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006640 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006641 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6642 "Clauses associated with the teams directive expected to be emitted "
6643 "only for the host!");
6644 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6645 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6646 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006647 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006648 switch (DirectiveKind) {
6649 case OMPD_target: {
6650 const auto *CS = D.getInnermostCapturedStmt();
6651 const auto *Body =
6652 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
6653 const Stmt *ChildStmt =
6654 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body);
6655 if (const auto *NestedDir =
6656 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6657 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) {
6658 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) {
6659 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6660 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6661 const Expr *NumTeams =
6662 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6663 llvm::Value *NumTeamsVal =
6664 CGF.EmitScalarExpr(NumTeams,
6665 /*IgnoreResultAssign*/ true);
6666 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006667 /*isSigned=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00006668 }
6669 return Bld.getInt32(0);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006670 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006671 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) ||
6672 isOpenMPSimdDirective(NestedDir->getDirectiveKind()))
6673 return Bld.getInt32(1);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006674 return Bld.getInt32(0);
6675 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006676 return nullptr;
Samuel Antaob68e2db2016-03-03 16:20:23 +00006677 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006678 case OMPD_target_teams:
6679 case OMPD_target_teams_distribute:
6680 case OMPD_target_teams_distribute_simd:
6681 case OMPD_target_teams_distribute_parallel_for:
6682 case OMPD_target_teams_distribute_parallel_for_simd: {
6683 if (D.hasClausesOfKind<OMPNumTeamsClause>()) {
6684 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF);
6685 const Expr *NumTeams =
6686 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6687 llvm::Value *NumTeamsVal =
6688 CGF.EmitScalarExpr(NumTeams,
6689 /*IgnoreResultAssign*/ true);
6690 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006691 /*isSigned=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00006692 }
6693 return Bld.getInt32(0);
6694 }
6695 case OMPD_target_parallel:
6696 case OMPD_target_parallel_for:
6697 case OMPD_target_parallel_for_simd:
6698 case OMPD_target_simd:
6699 return Bld.getInt32(1);
6700 case OMPD_parallel:
6701 case OMPD_for:
6702 case OMPD_parallel_for:
cchen47d60942019-12-05 13:43:48 -05006703 case OMPD_parallel_master:
Alexey Bataev5c427362019-04-10 19:11:33 +00006704 case OMPD_parallel_sections:
6705 case OMPD_for_simd:
6706 case OMPD_parallel_for_simd:
6707 case OMPD_cancel:
6708 case OMPD_cancellation_point:
6709 case OMPD_ordered:
6710 case OMPD_threadprivate:
6711 case OMPD_allocate:
6712 case OMPD_task:
6713 case OMPD_simd:
6714 case OMPD_sections:
6715 case OMPD_section:
6716 case OMPD_single:
6717 case OMPD_master:
6718 case OMPD_critical:
6719 case OMPD_taskyield:
6720 case OMPD_barrier:
6721 case OMPD_taskwait:
6722 case OMPD_taskgroup:
6723 case OMPD_atomic:
6724 case OMPD_flush:
6725 case OMPD_teams:
6726 case OMPD_target_data:
6727 case OMPD_target_exit_data:
6728 case OMPD_target_enter_data:
6729 case OMPD_distribute:
6730 case OMPD_distribute_simd:
6731 case OMPD_distribute_parallel_for:
6732 case OMPD_distribute_parallel_for_simd:
6733 case OMPD_teams_distribute:
6734 case OMPD_teams_distribute_simd:
6735 case OMPD_teams_distribute_parallel_for:
6736 case OMPD_teams_distribute_parallel_for_simd:
6737 case OMPD_target_update:
6738 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00006739 case OMPD_declare_variant:
Alexey Bataev5c427362019-04-10 19:11:33 +00006740 case OMPD_declare_target:
6741 case OMPD_end_declare_target:
6742 case OMPD_declare_reduction:
6743 case OMPD_declare_mapper:
6744 case OMPD_taskloop:
6745 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00006746 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00006747 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00006748 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04006749 case OMPD_parallel_master_taskloop_simd:
Alexey Bataev5c427362019-04-10 19:11:33 +00006750 case OMPD_requires:
6751 case OMPD_unknown:
6752 break;
6753 }
6754 llvm_unreachable("Unexpected directive kind.");
6755}
Samuel Antaob68e2db2016-03-03 16:20:23 +00006756
Alexey Bataev5c427362019-04-10 19:11:33 +00006757static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS,
6758 llvm::Value *DefaultThreadLimitVal) {
6759 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6760 CGF.getContext(), CS->getCapturedStmt());
6761 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6762 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) {
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006763 llvm::Value *NumThreads = nullptr;
6764 llvm::Value *CondVal = nullptr;
6765 // Handle if clause. If if clause present, the number of threads is
6766 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6767 if (Dir->hasClausesOfKind<OMPIfClause>()) {
6768 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6769 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6770 const OMPIfClause *IfClause = nullptr;
6771 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) {
6772 if (C->getNameModifier() == OMPD_unknown ||
6773 C->getNameModifier() == OMPD_parallel) {
6774 IfClause = C;
6775 break;
6776 }
6777 }
6778 if (IfClause) {
6779 const Expr *Cond = IfClause->getCondition();
6780 bool Result;
6781 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6782 if (!Result)
6783 return CGF.Builder.getInt32(1);
6784 } else {
6785 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange());
6786 if (const auto *PreInit =
6787 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) {
6788 for (const auto *I : PreInit->decls()) {
6789 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6790 CGF.EmitVarDecl(cast<VarDecl>(*I));
6791 } else {
6792 CodeGenFunction::AutoVarEmission Emission =
6793 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6794 CGF.EmitAutoVarCleanups(Emission);
6795 }
6796 }
6797 }
6798 CondVal = CGF.EvaluateExprAsBool(Cond);
6799 }
6800 }
6801 }
6802 // Check the value of num_threads clause iff if clause was not specified
6803 // or is not evaluated to false.
Alexey Bataev5c427362019-04-10 19:11:33 +00006804 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) {
6805 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6806 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6807 const auto *NumThreadsClause =
6808 Dir->getSingleClause<OMPNumThreadsClause>();
6809 CodeGenFunction::LexicalScope Scope(
6810 CGF, NumThreadsClause->getNumThreads()->getSourceRange());
6811 if (const auto *PreInit =
6812 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6813 for (const auto *I : PreInit->decls()) {
6814 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6815 CGF.EmitVarDecl(cast<VarDecl>(*I));
6816 } else {
6817 CodeGenFunction::AutoVarEmission Emission =
6818 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6819 CGF.EmitAutoVarCleanups(Emission);
6820 }
6821 }
6822 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006823 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads());
Alexey Bataev5c427362019-04-10 19:11:33 +00006824 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006825 /*isSigned=*/false);
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006826 if (DefaultThreadLimitVal)
6827 NumThreads = CGF.Builder.CreateSelect(
6828 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads),
6829 DefaultThreadLimitVal, NumThreads);
6830 } else {
6831 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal
6832 : CGF.Builder.getInt32(0);
Alexey Bataev5c427362019-04-10 19:11:33 +00006833 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006834 // Process condition of the if clause.
6835 if (CondVal) {
6836 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads,
6837 CGF.Builder.getInt32(1));
6838 }
6839 return NumThreads;
Alexey Bataev5c427362019-04-10 19:11:33 +00006840 }
6841 if (isOpenMPSimdDirective(Dir->getDirectiveKind()))
6842 return CGF.Builder.getInt32(1);
6843 return DefaultThreadLimitVal;
6844 }
6845 return DefaultThreadLimitVal ? DefaultThreadLimitVal
6846 : CGF.Builder.getInt32(0);
Samuel Antaob68e2db2016-03-03 16:20:23 +00006847}
6848
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006849/// Emit the number of threads for a target directive. Inspect the
6850/// thread_limit clause associated with a teams construct combined or closely
6851/// nested with the target directive.
6852///
6853/// Emit the num_threads clause for directives such as 'target parallel' that
6854/// have no associated teams construct.
6855///
6856/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006857static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006858emitNumThreadsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006859 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006860 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6861 "Clauses associated with the teams directive expected to be emitted "
6862 "only for the host!");
6863 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6864 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6865 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006866 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006867 llvm::Value *ThreadLimitVal = nullptr;
6868 llvm::Value *NumThreadsVal = nullptr;
6869 switch (DirectiveKind) {
6870 case OMPD_target: {
6871 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6872 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6873 return NumThreads;
6874 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6875 CGF.getContext(), CS->getCapturedStmt());
6876 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6877 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) {
6878 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6879 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6880 const auto *ThreadLimitClause =
6881 Dir->getSingleClause<OMPThreadLimitClause>();
6882 CodeGenFunction::LexicalScope Scope(
6883 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange());
6884 if (const auto *PreInit =
6885 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6886 for (const auto *I : PreInit->decls()) {
6887 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6888 CGF.EmitVarDecl(cast<VarDecl>(*I));
6889 } else {
6890 CodeGenFunction::AutoVarEmission Emission =
6891 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6892 CGF.EmitAutoVarCleanups(Emission);
6893 }
6894 }
6895 }
6896 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6897 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6898 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006899 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006900 }
6901 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) &&
6902 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) {
6903 CS = Dir->getInnermostCapturedStmt();
6904 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6905 CGF.getContext(), CS->getCapturedStmt());
6906 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6907 }
6908 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) &&
6909 !isOpenMPSimdDirective(Dir->getDirectiveKind())) {
6910 CS = Dir->getInnermostCapturedStmt();
6911 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6912 return NumThreads;
6913 }
6914 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind()))
6915 return Bld.getInt32(1);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006916 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006917 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6918 }
6919 case OMPD_target_teams: {
6920 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6921 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6922 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6923 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6924 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6925 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006926 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006927 }
6928 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6929 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6930 return NumThreads;
6931 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6932 CGF.getContext(), CS->getCapturedStmt());
6933 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6934 if (Dir->getDirectiveKind() == OMPD_distribute) {
6935 CS = Dir->getInnermostCapturedStmt();
6936 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6937 return NumThreads;
6938 }
6939 }
6940 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6941 }
6942 case OMPD_target_teams_distribute:
6943 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6944 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6945 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6946 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6947 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6948 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006949 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006950 }
6951 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal);
6952 case OMPD_target_parallel:
6953 case OMPD_target_parallel_for:
6954 case OMPD_target_parallel_for_simd:
6955 case OMPD_target_teams_distribute_parallel_for:
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006956 case OMPD_target_teams_distribute_parallel_for_simd: {
6957 llvm::Value *CondVal = nullptr;
6958 // Handle if clause. If if clause present, the number of threads is
6959 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6960 if (D.hasClausesOfKind<OMPIfClause>()) {
6961 const OMPIfClause *IfClause = nullptr;
6962 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) {
6963 if (C->getNameModifier() == OMPD_unknown ||
6964 C->getNameModifier() == OMPD_parallel) {
6965 IfClause = C;
6966 break;
6967 }
6968 }
6969 if (IfClause) {
6970 const Expr *Cond = IfClause->getCondition();
6971 bool Result;
6972 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6973 if (!Result)
6974 return Bld.getInt32(1);
6975 } else {
6976 CodeGenFunction::RunCleanupsScope Scope(CGF);
6977 CondVal = CGF.EvaluateExprAsBool(Cond);
6978 }
6979 }
6980 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006981 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6982 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6983 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6984 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6985 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6986 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006987 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006988 }
6989 if (D.hasClausesOfKind<OMPNumThreadsClause>()) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006990 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
Alexey Bataev5c427362019-04-10 19:11:33 +00006991 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>();
6992 llvm::Value *NumThreads = CGF.EmitScalarExpr(
6993 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true);
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006994 NumThreadsVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006995 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006996 ThreadLimitVal = ThreadLimitVal
Alexey Bataev5c427362019-04-10 19:11:33 +00006997 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal,
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006998 ThreadLimitVal),
6999 NumThreadsVal, ThreadLimitVal)
7000 : NumThreadsVal;
Alexey Bataev50a1c782017-12-01 21:31:08 +00007001 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00007002 if (!ThreadLimitVal)
7003 ThreadLimitVal = Bld.getInt32(0);
7004 if (CondVal)
7005 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1));
7006 return ThreadLimitVal;
7007 }
Alexey Bataev5c427362019-04-10 19:11:33 +00007008 case OMPD_target_teams_distribute_simd:
7009 case OMPD_target_simd:
7010 return Bld.getInt32(1);
7011 case OMPD_parallel:
7012 case OMPD_for:
7013 case OMPD_parallel_for:
cchen47d60942019-12-05 13:43:48 -05007014 case OMPD_parallel_master:
Alexey Bataev5c427362019-04-10 19:11:33 +00007015 case OMPD_parallel_sections:
7016 case OMPD_for_simd:
7017 case OMPD_parallel_for_simd:
7018 case OMPD_cancel:
7019 case OMPD_cancellation_point:
7020 case OMPD_ordered:
7021 case OMPD_threadprivate:
7022 case OMPD_allocate:
7023 case OMPD_task:
7024 case OMPD_simd:
7025 case OMPD_sections:
7026 case OMPD_section:
7027 case OMPD_single:
7028 case OMPD_master:
7029 case OMPD_critical:
7030 case OMPD_taskyield:
7031 case OMPD_barrier:
7032 case OMPD_taskwait:
7033 case OMPD_taskgroup:
7034 case OMPD_atomic:
7035 case OMPD_flush:
7036 case OMPD_teams:
7037 case OMPD_target_data:
7038 case OMPD_target_exit_data:
7039 case OMPD_target_enter_data:
7040 case OMPD_distribute:
7041 case OMPD_distribute_simd:
7042 case OMPD_distribute_parallel_for:
7043 case OMPD_distribute_parallel_for_simd:
7044 case OMPD_teams_distribute:
7045 case OMPD_teams_distribute_simd:
7046 case OMPD_teams_distribute_parallel_for:
7047 case OMPD_teams_distribute_parallel_for_simd:
7048 case OMPD_target_update:
7049 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00007050 case OMPD_declare_variant:
Alexey Bataev5c427362019-04-10 19:11:33 +00007051 case OMPD_declare_target:
7052 case OMPD_end_declare_target:
7053 case OMPD_declare_reduction:
7054 case OMPD_declare_mapper:
7055 case OMPD_taskloop:
7056 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00007057 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00007058 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00007059 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04007060 case OMPD_parallel_master_taskloop_simd:
Alexey Bataev5c427362019-04-10 19:11:33 +00007061 case OMPD_requires:
7062 case OMPD_unknown:
7063 break;
Samuel Antaob68e2db2016-03-03 16:20:23 +00007064 }
Alexey Bataev5c427362019-04-10 19:11:33 +00007065 llvm_unreachable("Unsupported directive kind.");
Samuel Antaob68e2db2016-03-03 16:20:23 +00007066}
7067
Samuel Antao86ace552016-04-27 22:40:57 +00007068namespace {
Alexey Bataevb3638132018-07-19 16:34:13 +00007069LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
7070
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007071// Utility to handle information from clauses associated with a given
Samuel Antao86ace552016-04-27 22:40:57 +00007072// construct that use mappable expressions (e.g. 'map' clause, 'to' clause).
7073// It provides a convenient interface to obtain the information and generate
7074// code for that information.
7075class MappableExprsHandler {
7076public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007077 /// Values for bit flags used to specify the mapping type for
Samuel Antao86ace552016-04-27 22:40:57 +00007078 /// offloading.
Alexey Bataevb3638132018-07-19 16:34:13 +00007079 enum OpenMPOffloadMappingFlags : uint64_t {
7080 /// No flags
7081 OMP_MAP_NONE = 0x0,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007082 /// Allocate memory on the device and move data from host to device.
Samuel Antao86ace552016-04-27 22:40:57 +00007083 OMP_MAP_TO = 0x01,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007084 /// Allocate memory on the device and move data from device to host.
Samuel Antao86ace552016-04-27 22:40:57 +00007085 OMP_MAP_FROM = 0x02,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007086 /// Always perform the requested mapping action on the element, even
Samuel Antao86ace552016-04-27 22:40:57 +00007087 /// if it was already mapped before.
7088 OMP_MAP_ALWAYS = 0x04,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007089 /// Delete the element from the device environment, ignoring the
Samuel Antao86ace552016-04-27 22:40:57 +00007090 /// current reference count associated with the element.
Samuel Antao6782e942016-05-26 16:48:10 +00007091 OMP_MAP_DELETE = 0x08,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007092 /// The element being mapped is a pointer-pointee pair; both the
George Rokos065755d2017-11-07 18:27:04 +00007093 /// pointer and the pointee should be mapped.
7094 OMP_MAP_PTR_AND_OBJ = 0x10,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007095 /// This flags signals that the base address of an entry should be
George Rokos065755d2017-11-07 18:27:04 +00007096 /// passed to the target kernel as an argument.
7097 OMP_MAP_TARGET_PARAM = 0x20,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007098 /// Signal that the runtime library has to return the device pointer
George Rokos065755d2017-11-07 18:27:04 +00007099 /// in the current position for the data being mapped. Used when we have the
7100 /// use_device_ptr clause.
7101 OMP_MAP_RETURN_PARAM = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007102 /// This flag signals that the reference being passed is a pointer to
Samuel Antaod486f842016-05-26 16:53:38 +00007103 /// private data.
George Rokos065755d2017-11-07 18:27:04 +00007104 OMP_MAP_PRIVATE = 0x80,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007105 /// Pass the element to the device by value.
George Rokos065755d2017-11-07 18:27:04 +00007106 OMP_MAP_LITERAL = 0x100,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007107 /// Implicit map
7108 OMP_MAP_IMPLICIT = 0x200,
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007109 /// Close is a hint to the runtime to allocate memory close to
7110 /// the target device.
7111 OMP_MAP_CLOSE = 0x400,
Alexey Bataevb3638132018-07-19 16:34:13 +00007112 /// The 16 MSBs of the flags indicate whether the entry is member of some
7113 /// struct/class.
7114 OMP_MAP_MEMBER_OF = 0xffff000000000000,
7115 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF),
Samuel Antao86ace552016-04-27 22:40:57 +00007116 };
7117
Michael Krused47b9432019-08-05 18:43:21 +00007118 /// Get the offset of the OMP_MAP_MEMBER_OF field.
7119 static unsigned getFlagMemberOffset() {
7120 unsigned Offset = 0;
7121 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1);
7122 Remain = Remain >> 1)
7123 Offset++;
7124 return Offset;
7125 }
7126
Samuel Antaocc10b852016-07-28 14:23:26 +00007127 /// Class that associates information with a base pointer to be passed to the
7128 /// runtime library.
7129 class BasePointerInfo {
7130 /// The base pointer.
7131 llvm::Value *Ptr = nullptr;
7132 /// The base declaration that refers to this device pointer, or null if
7133 /// there is none.
7134 const ValueDecl *DevPtrDecl = nullptr;
7135
7136 public:
7137 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr)
7138 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {}
7139 llvm::Value *operator*() const { return Ptr; }
7140 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; }
7141 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; }
7142 };
7143
Alexey Bataevb3638132018-07-19 16:34:13 +00007144 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>;
7145 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>;
7146 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>;
7147
7148 /// Map between a struct and the its lowest & highest elements which have been
7149 /// mapped.
7150 /// [ValueDecl *] --> {LE(FieldIndex, Pointer),
7151 /// HE(FieldIndex, Pointer)}
7152 struct StructRangeInfoTy {
7153 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = {
7154 0, Address::invalid()};
7155 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = {
7156 0, Address::invalid()};
7157 Address Base = Address::invalid();
7158 };
Samuel Antao86ace552016-04-27 22:40:57 +00007159
7160private:
Alexey Bataevb3638132018-07-19 16:34:13 +00007161 /// Kind that defines how a device pointer has to be returned.
7162 struct MapInfo {
7163 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
7164 OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
Kelvin Lief579432018-12-18 22:18:41 +00007165 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataevb3638132018-07-19 16:34:13 +00007166 bool ReturnDevicePointer = false;
7167 bool IsImplicit = false;
7168
7169 MapInfo() = default;
7170 MapInfo(
7171 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Kelvin Lief579432018-12-18 22:18:41 +00007172 OpenMPMapClauseKind MapType,
7173 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007174 bool ReturnDevicePointer, bool IsImplicit)
Kelvin Lief579432018-12-18 22:18:41 +00007175 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
Alexey Bataevb3638132018-07-19 16:34:13 +00007176 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {}
7177 };
7178
7179 /// If use_device_ptr is used on a pointer which is a struct member and there
7180 /// is no map information about it, then emission of that entry is deferred
7181 /// until the whole struct has been processed.
7182 struct DeferredDevicePtrEntryTy {
7183 const Expr *IE = nullptr;
7184 const ValueDecl *VD = nullptr;
7185
7186 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD)
7187 : IE(IE), VD(VD) {}
7188 };
7189
Michael Krused47b9432019-08-05 18:43:21 +00007190 /// The target directive from where the mappable clauses were extracted. It
7191 /// is either a executable directive or a user-defined mapper directive.
7192 llvm::PointerUnion<const OMPExecutableDirective *,
7193 const OMPDeclareMapperDecl *>
7194 CurDir;
Samuel Antao86ace552016-04-27 22:40:57 +00007195
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007196 /// Function the directive is being generated for.
Samuel Antao86ace552016-04-27 22:40:57 +00007197 CodeGenFunction &CGF;
7198
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007199 /// Set of all first private variables in the current directive.
Alexey Bataevf288cf92019-06-27 18:53:07 +00007200 /// bool data is set to true if the variable is implicitly marked as
7201 /// firstprivate, false otherwise.
7202 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls;
Samuel Antaod486f842016-05-26 16:53:38 +00007203
Samuel Antao6890b092016-07-28 14:25:09 +00007204 /// Map between device pointer declarations and their expression components.
7205 /// The key value for declarations in 'this' is null.
7206 llvm::DenseMap<
7207 const ValueDecl *,
7208 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7209 DevPointersMap;
7210
Samuel Antao86ace552016-04-27 22:40:57 +00007211 llvm::Value *getExprTypeSize(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007212 QualType ExprTy = E->getType().getCanonicalType();
Samuel Antao86ace552016-04-27 22:40:57 +00007213
7214 // Reference types are ignored for mapping purposes.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007215 if (const auto *RefTy = ExprTy->getAs<ReferenceType>())
Samuel Antao86ace552016-04-27 22:40:57 +00007216 ExprTy = RefTy->getPointeeType().getCanonicalType();
7217
7218 // Given that an array section is considered a built-in type, we need to
7219 // do the calculation based on the length of the section instead of relying
7220 // on CGF.getTypeSize(E->getType()).
7221 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) {
7222 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType(
7223 OAE->getBase()->IgnoreParenImpCasts())
7224 .getCanonicalType();
7225
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007226 // If there is no length associated with the expression and lower bound is
7227 // not specified too, that means we are using the whole length of the
7228 // base.
7229 if (!OAE->getLength() && OAE->getColonLoc().isValid() &&
7230 !OAE->getLowerBound())
Samuel Antao86ace552016-04-27 22:40:57 +00007231 return CGF.getTypeSize(BaseTy);
7232
7233 llvm::Value *ElemSize;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007234 if (const auto *PTy = BaseTy->getAs<PointerType>()) {
Samuel Antao86ace552016-04-27 22:40:57 +00007235 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007236 } else {
7237 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr());
Samuel Antao86ace552016-04-27 22:40:57 +00007238 assert(ATy && "Expecting array type if not a pointer type.");
7239 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType());
7240 }
7241
7242 // If we don't have a length at this point, that is because we have an
7243 // array section with a single element.
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007244 if (!OAE->getLength() && OAE->getColonLoc().isInvalid())
Samuel Antao86ace552016-04-27 22:40:57 +00007245 return ElemSize;
7246
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007247 if (const Expr *LenExpr = OAE->getLength()) {
Michael Liaod838cf72019-10-02 00:22:45 +00007248 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr);
7249 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(),
7250 CGF.getContext().getSizeType(),
7251 LenExpr->getExprLoc());
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007252 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize);
7253 }
7254 assert(!OAE->getLength() && OAE->getColonLoc().isValid() &&
7255 OAE->getLowerBound() && "expected array_section[lb:].");
7256 // Size = sizetype - lb * elemtype;
7257 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy);
7258 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound());
7259 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(),
7260 CGF.getContext().getSizeType(),
7261 OAE->getLowerBound()->getExprLoc());
7262 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize);
7263 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal);
7264 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal);
7265 LengthVal = CGF.Builder.CreateSelect(
7266 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0));
7267 return LengthVal;
Samuel Antao86ace552016-04-27 22:40:57 +00007268 }
7269 return CGF.getTypeSize(ExprTy);
7270 }
7271
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007272 /// Return the corresponding bits for a given map clause modifier. Add
Samuel Antao86ace552016-04-27 22:40:57 +00007273 /// a flag marking the map as a pointer if requested. Add a flag marking the
Samuel Antao6782e942016-05-26 16:48:10 +00007274 /// map as the first one of a series of maps that relate to the same map
7275 /// expression.
Kelvin Lief579432018-12-18 22:18:41 +00007276 OpenMPOffloadMappingFlags getMapTypeBits(
7277 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
7278 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const {
Alexey Bataevb3638132018-07-19 16:34:13 +00007279 OpenMPOffloadMappingFlags Bits =
7280 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE;
Samuel Antao86ace552016-04-27 22:40:57 +00007281 switch (MapType) {
7282 case OMPC_MAP_alloc:
Samuel Antao6782e942016-05-26 16:48:10 +00007283 case OMPC_MAP_release:
7284 // alloc and release is the default behavior in the runtime library, i.e.
7285 // if we don't pass any bits alloc/release that is what the runtime is
7286 // going to do. Therefore, we don't need to signal anything for these two
7287 // type modifiers.
Samuel Antao86ace552016-04-27 22:40:57 +00007288 break;
7289 case OMPC_MAP_to:
Alexey Bataevb3638132018-07-19 16:34:13 +00007290 Bits |= OMP_MAP_TO;
Samuel Antao86ace552016-04-27 22:40:57 +00007291 break;
7292 case OMPC_MAP_from:
Alexey Bataevb3638132018-07-19 16:34:13 +00007293 Bits |= OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007294 break;
7295 case OMPC_MAP_tofrom:
Alexey Bataevb3638132018-07-19 16:34:13 +00007296 Bits |= OMP_MAP_TO | OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007297 break;
7298 case OMPC_MAP_delete:
Alexey Bataevb3638132018-07-19 16:34:13 +00007299 Bits |= OMP_MAP_DELETE;
Samuel Antao86ace552016-04-27 22:40:57 +00007300 break;
Alexey Bataevb3638132018-07-19 16:34:13 +00007301 case OMPC_MAP_unknown:
Samuel Antao86ace552016-04-27 22:40:57 +00007302 llvm_unreachable("Unexpected map type!");
Samuel Antao86ace552016-04-27 22:40:57 +00007303 }
7304 if (AddPtrFlag)
George Rokos065755d2017-11-07 18:27:04 +00007305 Bits |= OMP_MAP_PTR_AND_OBJ;
7306 if (AddIsTargetParamFlag)
7307 Bits |= OMP_MAP_TARGET_PARAM;
Kelvin Lief579432018-12-18 22:18:41 +00007308 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always)
7309 != MapModifiers.end())
Samuel Antao86ace552016-04-27 22:40:57 +00007310 Bits |= OMP_MAP_ALWAYS;
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007311 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close)
7312 != MapModifiers.end())
7313 Bits |= OMP_MAP_CLOSE;
Samuel Antao86ace552016-04-27 22:40:57 +00007314 return Bits;
7315 }
7316
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007317 /// Return true if the provided expression is a final array section. A
Samuel Antao86ace552016-04-27 22:40:57 +00007318 /// final array section, is one whose length can't be proved to be one.
7319 bool isFinalArraySectionExpression(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007320 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
Samuel Antao86ace552016-04-27 22:40:57 +00007321
7322 // It is not an array section and therefore not a unity-size one.
7323 if (!OASE)
7324 return false;
7325
7326 // An array section with no colon always refer to a single element.
7327 if (OASE->getColonLoc().isInvalid())
7328 return false;
7329
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007330 const Expr *Length = OASE->getLength();
Samuel Antao86ace552016-04-27 22:40:57 +00007331
7332 // If we don't have a length we have to check if the array has size 1
7333 // for this dimension. Also, we should always expect a length if the
7334 // base type is pointer.
7335 if (!Length) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007336 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType(
7337 OASE->getBase()->IgnoreParenImpCasts())
7338 .getCanonicalType();
7339 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
Samuel Antao86ace552016-04-27 22:40:57 +00007340 return ATy->getSize().getSExtValue() != 1;
7341 // If we don't have a constant dimension length, we have to consider
7342 // the current section as having any size, so it is not necessarily
7343 // unitary. If it happen to be unity size, that's user fault.
7344 return true;
7345 }
7346
7347 // Check if the length evaluates to 1.
Fangrui Song407659a2018-11-30 23:41:18 +00007348 Expr::EvalResult Result;
7349 if (!Length->EvaluateAsInt(Result, CGF.getContext()))
Samuel Antao86ace552016-04-27 22:40:57 +00007350 return true; // Can have more that size 1.
7351
Fangrui Song407659a2018-11-30 23:41:18 +00007352 llvm::APSInt ConstLength = Result.Val.getInt();
Samuel Antao86ace552016-04-27 22:40:57 +00007353 return ConstLength.getSExtValue() != 1;
7354 }
7355
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007356 /// Generate the base pointers, section pointers, sizes and map type
Samuel Antao86ace552016-04-27 22:40:57 +00007357 /// bits for the provided map type, map modifier, and expression components.
7358 /// \a IsFirstComponent should be set to true if the provided set of
7359 /// components is the first associated with a capture.
7360 void generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00007361 OpenMPMapClauseKind MapType,
7362 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Samuel Antao86ace552016-04-27 22:40:57 +00007363 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Samuel Antaocc10b852016-07-28 14:23:26 +00007364 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007365 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
Alexey Bataevb3638132018-07-19 16:34:13 +00007366 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007367 bool IsImplicit,
7368 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7369 OverlappedElements = llvm::None) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007370 // The following summarizes what has to be generated for each map and the
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00007371 // types below. The generated information is expressed in this order:
Samuel Antao86ace552016-04-27 22:40:57 +00007372 // base pointer, section pointer, size, flags
7373 // (to add to the ones that come from the map type and modifier).
7374 //
7375 // double d;
7376 // int i[100];
7377 // float *p;
7378 //
7379 // struct S1 {
7380 // int i;
7381 // float f[50];
7382 // }
7383 // struct S2 {
7384 // int i;
7385 // float f[50];
7386 // S1 s;
7387 // double *p;
7388 // struct S2 *ps;
7389 // }
7390 // S2 s;
7391 // S2 *ps;
7392 //
7393 // map(d)
Alexey Bataevb3638132018-07-19 16:34:13 +00007394 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007395 //
7396 // map(i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007397 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007398 //
7399 // map(i[1:23])
Alexey Bataevb3638132018-07-19 16:34:13 +00007400 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007401 //
7402 // map(p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007403 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007404 //
7405 // map(p[1:24])
Alexey Bataevb3638132018-07-19 16:34:13 +00007406 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007407 //
7408 // map(s)
Alexey Bataevb3638132018-07-19 16:34:13 +00007409 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007410 //
7411 // map(s.i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007412 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007413 //
7414 // map(s.s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007415 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007416 //
7417 // map(s.p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007418 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007419 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007420 // map(to: s.p[:22])
7421 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*)
7422 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**)
7423 // &(s.p), &(s.p[0]), 22*sizeof(double),
7424 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***)
7425 // (*) alloc space for struct members, only this is a target parameter
7426 // (**) map the pointer (nothing to be mapped in this example) (the compiler
7427 // optimizes this entry out, same in the examples below)
7428 // (***) map the pointee (map: to)
Samuel Antao86ace552016-04-27 22:40:57 +00007429 //
7430 // map(s.ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007431 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007432 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007433 // map(from: s.ps->s.i)
7434 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7435 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7436 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007437 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007438 // map(to: s.ps->ps)
7439 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7440 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7441 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007442 //
7443 // map(s.ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007444 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7445 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7446 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7447 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007448 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007449 // map(to: s.ps->ps->s.f[:22])
7450 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7451 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7452 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7453 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007454 //
7455 // map(ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007456 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007457 //
7458 // map(ps->i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007459 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007460 //
7461 // map(ps->s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007462 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007463 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007464 // map(from: ps->p)
7465 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007466 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007467 // map(to: ps->p[:22])
7468 // ps, &(ps->p), sizeof(double*), TARGET_PARAM
7469 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1)
7470 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007471 //
7472 // map(ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007473 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007474 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007475 // map(from: ps->ps->s.i)
7476 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7477 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7478 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007479 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007480 // map(from: ps->ps->ps)
7481 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7482 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7483 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007484 //
7485 // map(ps->ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007486 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7487 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7488 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7489 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007490 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007491 // map(to: ps->ps->ps->s.f[:22])
7492 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7493 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7494 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7495 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
7496 //
7497 // map(to: s.f[:22]) map(from: s.p[:33])
7498 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) +
7499 // sizeof(double*) (**), TARGET_PARAM
7500 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO
7501 // &s, &(s.p), sizeof(double*), MEMBER_OF(1)
7502 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7503 // (*) allocate contiguous space needed to fit all mapped members even if
7504 // we allocate space for members not mapped (in this example,
7505 // s.f[22..49] and s.s are not mapped, yet we must allocate space for
7506 // them as well because they fall between &s.f[0] and &s.p)
7507 //
7508 // map(from: s.f[:22]) map(to: ps->p[:33])
7509 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM
7510 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7511 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*)
7512 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO
7513 // (*) the struct this entry pertains to is the 2nd element in the list of
7514 // arguments, hence MEMBER_OF(2)
7515 //
7516 // map(from: s.f[:22], s.s) map(to: ps->p[:33])
7517 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM
7518 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM
7519 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM
7520 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7521 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*)
7522 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO
7523 // (*) the struct this entry pertains to is the 4th element in the list
7524 // of arguments, hence MEMBER_OF(4)
Samuel Antao86ace552016-04-27 22:40:57 +00007525
7526 // Track if the map information being generated is the first for a capture.
7527 bool IsCaptureFirstInfo = IsFirstComponentList;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007528 // When the variable is on a declare target link or in a to clause with
7529 // unified memory, a reference is needed to hold the host/device address
7530 // of the variable.
7531 bool RequiresReference = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007532
7533 // Scan the components from the base to the complete expression.
7534 auto CI = Components.rbegin();
7535 auto CE = Components.rend();
7536 auto I = CI;
7537
7538 // Track if the map information being generated is the first for a list of
7539 // components.
7540 bool IsExpressionFirstInfo = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00007541 Address BP = Address::invalid();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007542 const Expr *AssocExpr = I->getAssociatedExpression();
7543 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7544 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
Samuel Antao86ace552016-04-27 22:40:57 +00007545
Patrick Lystere13b1e32019-01-02 19:28:48 +00007546 if (isa<MemberExpr>(AssocExpr)) {
Samuel Antao86ace552016-04-27 22:40:57 +00007547 // The base is the 'this' pointer. The content of the pointer is going
7548 // to be the base of the field being mapped.
Alexey Bataevb3638132018-07-19 16:34:13 +00007549 BP = CGF.LoadCXXThisAddress();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007550 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7551 (OASE &&
7552 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08007553 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF);
Samuel Antao86ace552016-04-27 22:40:57 +00007554 } else {
7555 // The base is the reference to the variable.
7556 // BP = &Var.
Akira Hatanakaf139ae32019-12-03 15:17:01 -08007557 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF);
Alexey Bataev92327c52018-03-26 16:40:55 +00007558 if (const auto *VD =
7559 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7560 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007561 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7562 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7563 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
7564 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) {
7565 RequiresReference = true;
7566 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataev2c1dffe2018-04-16 20:34:41 +00007567 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007568 }
Alexey Bataev92327c52018-03-26 16:40:55 +00007569 }
Samuel Antao86ace552016-04-27 22:40:57 +00007570
7571 // If the variable is a pointer and is being dereferenced (i.e. is not
Nico Webera6916892016-06-10 18:53:04 +00007572 // the last component), the base has to be the pointer itself, not its
Samuel Antao403ffd42016-07-27 22:49:49 +00007573 // reference. References are ignored for mapping purposes.
7574 QualType Ty =
7575 I->getAssociatedDeclaration()->getType().getNonReferenceType();
7576 if (Ty->isAnyPointerType() && std::next(I) != CE) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007577 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
Samuel Antao86ace552016-04-27 22:40:57 +00007578
7579 // We do not need to generate individual map information for the
7580 // pointer, it can be associated with the combined storage.
7581 ++I;
7582 }
7583 }
7584
Alexey Bataevb3638132018-07-19 16:34:13 +00007585 // Track whether a component of the list should be marked as MEMBER_OF some
7586 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry
7587 // in a component list should be marked as MEMBER_OF, all subsequent entries
7588 // do not belong to the base struct. E.g.
7589 // struct S2 s;
7590 // s.ps->ps->ps->f[:]
7591 // (1) (2) (3) (4)
7592 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a
7593 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3)
7594 // is the pointee of ps(2) which is not member of struct s, so it should not
7595 // be marked as such (it is still PTR_AND_OBJ).
7596 // The variable is initialized to false so that PTR_AND_OBJ entries which
7597 // are not struct members are not considered (e.g. array of pointers to
7598 // data).
7599 bool ShouldBeMemberOf = false;
7600
7601 // Variable keeping track of whether or not we have encountered a component
7602 // in the component list which is a member expression. Useful when we have a
7603 // pointer or a final array section, in which case it is the previous
7604 // component in the list which tells us whether we have a member expression.
7605 // E.g. X.f[:]
7606 // While processing the final array section "[:]" it is "f" which tells us
7607 // whether we are dealing with a member of a declared struct.
7608 const MemberExpr *EncounteredME = nullptr;
7609
Samuel Antao86ace552016-04-27 22:40:57 +00007610 for (; I != CE; ++I) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007611 // If the current component is member of a struct (parent struct) mark it.
7612 if (!EncounteredME) {
7613 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7614 // If we encounter a PTR_AND_OBJ entry from now on it should be marked
7615 // as MEMBER_OF the parent struct.
7616 if (EncounteredME)
7617 ShouldBeMemberOf = true;
7618 }
7619
Samuel Antao86ace552016-04-27 22:40:57 +00007620 auto Next = std::next(I);
7621
7622 // We need to generate the addresses and sizes if this is the last
7623 // component, if the component is a pointer or if it is an array section
7624 // whose length can't be proved to be one. If this is a pointer, it
7625 // becomes the base address for the following components.
7626
7627 // A final array section, is one whose length can't be proved to be one.
7628 bool IsFinalArraySection =
7629 isFinalArraySectionExpression(I->getAssociatedExpression());
7630
7631 // Get information on whether the element is a pointer. Have to do a
7632 // special treatment for array sections given that they are built-in
7633 // types.
7634 const auto *OASE =
7635 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression());
7636 bool IsPointer =
Alexey Bataevb3638132018-07-19 16:34:13 +00007637 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE)
7638 .getCanonicalType()
7639 ->isAnyPointerType()) ||
Samuel Antao86ace552016-04-27 22:40:57 +00007640 I->getAssociatedExpression()->getType()->isAnyPointerType();
7641
7642 if (Next == CE || IsPointer || IsFinalArraySection) {
Samuel Antao86ace552016-04-27 22:40:57 +00007643 // If this is not the last component, we expect the pointer to be
7644 // associated with an array expression or member expression.
7645 assert((Next == CE ||
7646 isa<MemberExpr>(Next->getAssociatedExpression()) ||
7647 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||
7648 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) &&
7649 "Unexpected expression");
7650
Akira Hatanakaf139ae32019-12-03 15:17:01 -08007651 Address LB = CGF.EmitOMPSharedLValue(I->getAssociatedExpression())
7652 .getAddress(CGF);
Samuel Antao86ace552016-04-27 22:40:57 +00007653
Alexey Bataevb3638132018-07-19 16:34:13 +00007654 // If this component is a pointer inside the base struct then we don't
7655 // need to create any entry for it - it will be combined with the object
7656 // it is pointing to into a single PTR_AND_OBJ entry.
7657 bool IsMemberPointer =
7658 IsPointer && EncounteredME &&
7659 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) ==
7660 EncounteredME);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007661 if (!OverlappedElements.empty()) {
7662 // Handle base element with the info for overlapped elements.
7663 assert(!PartialStruct.Base.isValid() && "The base element is set.");
7664 assert(Next == CE &&
7665 "Expected last element for the overlapped elements.");
7666 assert(!IsPointer &&
7667 "Unexpected base element with the pointer type.");
7668 // Mark the whole struct as the struct that requires allocation on the
7669 // device.
7670 PartialStruct.LowestElem = {0, LB};
7671 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(
7672 I->getAssociatedExpression()->getType());
7673 Address HB = CGF.Builder.CreateConstGEP(
7674 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB,
7675 CGF.VoidPtrTy),
James Y Knight751fe282019-02-09 22:22:28 +00007676 TypeSize.getQuantity() - 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007677 PartialStruct.HighestElem = {
7678 std::numeric_limits<decltype(
7679 PartialStruct.HighestElem.first)>::max(),
7680 HB};
7681 PartialStruct.Base = BP;
7682 // Emit data for non-overlapped data.
7683 OpenMPOffloadMappingFlags Flags =
7684 OMP_MAP_MEMBER_OF |
Kelvin Lief579432018-12-18 22:18:41 +00007685 getMapTypeBits(MapType, MapModifiers, IsImplicit,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007686 /*AddPtrFlag=*/false,
7687 /*AddIsTargetParamFlag=*/false);
7688 LB = BP;
7689 llvm::Value *Size = nullptr;
7690 // Do bitcopy of all non-overlapped structure elements.
7691 for (OMPClauseMappableExprCommon::MappableExprComponentListRef
7692 Component : OverlappedElements) {
7693 Address ComponentLB = Address::invalid();
7694 for (const OMPClauseMappableExprCommon::MappableComponent &MC :
7695 Component) {
7696 if (MC.getAssociatedDeclaration()) {
7697 ComponentLB =
7698 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
Akira Hatanakaf139ae32019-12-03 15:17:01 -08007699 .getAddress(CGF);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007700 Size = CGF.Builder.CreatePtrDiff(
7701 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()),
7702 CGF.EmitCastToVoidPtr(LB.getPointer()));
7703 break;
7704 }
7705 }
7706 BasePointers.push_back(BP.getPointer());
7707 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007708 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty,
7709 /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007710 Types.push_back(Flags);
James Y Knight751fe282019-02-09 22:22:28 +00007711 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007712 }
7713 BasePointers.push_back(BP.getPointer());
7714 Pointers.push_back(LB.getPointer());
7715 Size = CGF.Builder.CreatePtrDiff(
7716 CGF.EmitCastToVoidPtr(
James Y Knight751fe282019-02-09 22:22:28 +00007717 CGF.Builder.CreateConstGEP(HB, 1).getPointer()),
Alexey Bataeve82445f2018-09-20 13:54:02 +00007718 CGF.EmitCastToVoidPtr(LB.getPointer()));
Alexey Bataeva90fc662019-06-25 16:00:43 +00007719 Sizes.push_back(
7720 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007721 Types.push_back(Flags);
7722 break;
7723 }
7724 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
Alexey Bataevb3638132018-07-19 16:34:13 +00007725 if (!IsMemberPointer) {
7726 BasePointers.push_back(BP.getPointer());
7727 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007728 Sizes.push_back(
7729 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Samuel Antao03a3cec2016-07-27 22:52:16 +00007730
Alexey Bataevb3638132018-07-19 16:34:13 +00007731 // We need to add a pointer flag for each map that comes from the
7732 // same expression except for the first one. We also need to signal
7733 // this map is the first one that relates with the current capture
7734 // (there is a set of entries for each capture).
7735 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
Kelvin Lief579432018-12-18 22:18:41 +00007736 MapType, MapModifiers, IsImplicit,
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007737 !IsExpressionFirstInfo || RequiresReference,
7738 IsCaptureFirstInfo && !RequiresReference);
Alexey Bataevb3638132018-07-19 16:34:13 +00007739
7740 if (!IsExpressionFirstInfo) {
7741 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007742 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags.
Alexey Bataevb3638132018-07-19 16:34:13 +00007743 if (IsPointer)
7744 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS |
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007745 OMP_MAP_DELETE | OMP_MAP_CLOSE);
Alexey Bataevb3638132018-07-19 16:34:13 +00007746
7747 if (ShouldBeMemberOf) {
7748 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag
7749 // should be later updated with the correct value of MEMBER_OF.
7750 Flags |= OMP_MAP_MEMBER_OF;
7751 // From now on, all subsequent PTR_AND_OBJ entries should not be
7752 // marked as MEMBER_OF.
7753 ShouldBeMemberOf = false;
7754 }
7755 }
7756
7757 Types.push_back(Flags);
Samuel Antao03a3cec2016-07-27 22:52:16 +00007758 }
7759
Alexey Bataevb3638132018-07-19 16:34:13 +00007760 // If we have encountered a member expression so far, keep track of the
7761 // mapped member. If the parent is "*this", then the value declaration
7762 // is nullptr.
7763 if (EncounteredME) {
7764 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl());
7765 unsigned FieldIndex = FD->getFieldIndex();
Samuel Antao03a3cec2016-07-27 22:52:16 +00007766
Alexey Bataevb3638132018-07-19 16:34:13 +00007767 // Update info about the lowest and highest elements for this struct
7768 if (!PartialStruct.Base.isValid()) {
7769 PartialStruct.LowestElem = {FieldIndex, LB};
7770 PartialStruct.HighestElem = {FieldIndex, LB};
7771 PartialStruct.Base = BP;
7772 } else if (FieldIndex < PartialStruct.LowestElem.first) {
7773 PartialStruct.LowestElem = {FieldIndex, LB};
7774 } else if (FieldIndex > PartialStruct.HighestElem.first) {
7775 PartialStruct.HighestElem = {FieldIndex, LB};
7776 }
7777 }
Samuel Antao86ace552016-04-27 22:40:57 +00007778
7779 // If we have a final array section, we are done with this expression.
7780 if (IsFinalArraySection)
7781 break;
7782
7783 // The pointer becomes the base for the next element.
7784 if (Next != CE)
7785 BP = LB;
7786
7787 IsExpressionFirstInfo = false;
7788 IsCaptureFirstInfo = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007789 }
7790 }
7791 }
7792
Alexey Bataevb3638132018-07-19 16:34:13 +00007793 /// Return the adjusted map modifiers if the declaration a capture refers to
7794 /// appears in a first-private clause. This is expected to be used only with
7795 /// directives that start with 'target'.
7796 MappableExprsHandler::OpenMPOffloadMappingFlags
7797 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const {
7798 assert(Cap.capturesVariable() && "Expected capture by reference only!");
7799
7800 // A first private variable captured by reference will use only the
7801 // 'private ptr' and 'map to' flag. Return the right flags if the captured
7802 // declaration is known as first-private in this handler.
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007803 if (FirstPrivateDecls.count(Cap.getCapturedVar())) {
7804 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) &&
7805 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef)
7806 return MappableExprsHandler::OMP_MAP_ALWAYS |
7807 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataevc2b831f2019-04-02 16:03:40 +00007808 if (Cap.getCapturedVar()->getType()->isAnyPointerType())
7809 return MappableExprsHandler::OMP_MAP_TO |
7810 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ;
Alexey Bataevb3638132018-07-19 16:34:13 +00007811 return MappableExprsHandler::OMP_MAP_PRIVATE |
7812 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007813 }
Alexey Bataevb3638132018-07-19 16:34:13 +00007814 return MappableExprsHandler::OMP_MAP_TO |
7815 MappableExprsHandler::OMP_MAP_FROM;
7816 }
7817
7818 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) {
Michael Krused47b9432019-08-05 18:43:21 +00007819 // Rotate by getFlagMemberOffset() bits.
Alexey Bataevb3638132018-07-19 16:34:13 +00007820 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1)
Michael Krused47b9432019-08-05 18:43:21 +00007821 << getFlagMemberOffset());
Alexey Bataevb3638132018-07-19 16:34:13 +00007822 }
7823
7824 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags,
7825 OpenMPOffloadMappingFlags MemberOfFlag) {
7826 // If the entry is PTR_AND_OBJ but has not been marked with the special
7827 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be
7828 // marked as MEMBER_OF.
7829 if ((Flags & OMP_MAP_PTR_AND_OBJ) &&
7830 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF))
7831 return;
7832
7833 // Reset the placeholder value to prepare the flag for the assignment of the
7834 // proper MEMBER_OF value.
7835 Flags &= ~OMP_MAP_MEMBER_OF;
7836 Flags |= MemberOfFlag;
7837 }
7838
Alexey Bataeve82445f2018-09-20 13:54:02 +00007839 void getPlainLayout(const CXXRecordDecl *RD,
7840 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
7841 bool AsBase) const {
7842 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD);
7843
7844 llvm::StructType *St =
7845 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType();
7846
7847 unsigned NumElements = St->getNumElements();
7848 llvm::SmallVector<
7849 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
7850 RecordLayout(NumElements);
7851
7852 // Fill bases.
7853 for (const auto &I : RD->bases()) {
7854 if (I.isVirtual())
7855 continue;
7856 const auto *Base = I.getType()->getAsCXXRecordDecl();
7857 // Ignore empty bases.
7858 if (Base->isEmpty() || CGF.getContext()
7859 .getASTRecordLayout(Base)
7860 .getNonVirtualSize()
7861 .isZero())
7862 continue;
7863
7864 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
7865 RecordLayout[FieldIndex] = Base;
7866 }
7867 // Fill in virtual bases.
7868 for (const auto &I : RD->vbases()) {
7869 const auto *Base = I.getType()->getAsCXXRecordDecl();
7870 // Ignore empty bases.
7871 if (Base->isEmpty())
7872 continue;
7873 unsigned FieldIndex = RL.getVirtualBaseIndex(Base);
7874 if (RecordLayout[FieldIndex])
7875 continue;
7876 RecordLayout[FieldIndex] = Base;
7877 }
7878 // Fill in all the fields.
7879 assert(!RD->isUnion() && "Unexpected union.");
7880 for (const auto *Field : RD->fields()) {
7881 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
7882 // will fill in later.)
Richard Smith78b239e2019-06-20 20:44:45 +00007883 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) {
Alexey Bataeve82445f2018-09-20 13:54:02 +00007884 unsigned FieldIndex = RL.getLLVMFieldNo(Field);
7885 RecordLayout[FieldIndex] = Field;
7886 }
7887 }
7888 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
7889 &Data : RecordLayout) {
7890 if (Data.isNull())
7891 continue;
7892 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>())
7893 getPlainLayout(Base, Layout, /*AsBase=*/true);
7894 else
7895 Layout.push_back(Data.get<const FieldDecl *>());
7896 }
7897 }
7898
Alexey Bataevb3638132018-07-19 16:34:13 +00007899public:
7900 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
Michael Krused47b9432019-08-05 18:43:21 +00007901 : CurDir(&Dir), CGF(CGF) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007902 // Extract firstprivate clause information.
7903 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>())
7904 for (const auto *D : C->varlists())
Alexey Bataevf288cf92019-06-27 18:53:07 +00007905 FirstPrivateDecls.try_emplace(
7906 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit());
Alexey Bataevb3638132018-07-19 16:34:13 +00007907 // Extract device pointer clause information.
7908 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
7909 for (auto L : C->component_lists())
7910 DevPointersMap[L.first].push_back(L.second);
7911 }
7912
Michael Krused47b9432019-08-05 18:43:21 +00007913 /// Constructor for the declare mapper directive.
7914 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF)
7915 : CurDir(&Dir), CGF(CGF) {}
7916
Alexey Bataevb3638132018-07-19 16:34:13 +00007917 /// Generate code for the combined entry if we have a partially mapped struct
7918 /// and take care of the mapping flags of the arguments corresponding to
7919 /// individual struct members.
7920 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers,
7921 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7922 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes,
7923 const StructRangeInfoTy &PartialStruct) const {
7924 // Base is the base of the struct
7925 BasePointers.push_back(PartialStruct.Base.getPointer());
7926 // Pointer is the address of the lowest element
7927 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer();
7928 Pointers.push_back(LB);
7929 // Size is (addr of {highest+1} element) - (addr of lowest element)
7930 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer();
7931 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1);
7932 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy);
7933 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy);
7934 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00007935 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00007936 /*isSigned=*/false);
Alexey Bataevb3638132018-07-19 16:34:13 +00007937 Sizes.push_back(Size);
7938 // Map type is always TARGET_PARAM
7939 Types.push_back(OMP_MAP_TARGET_PARAM);
7940 // Remove TARGET_PARAM flag from the first element
7941 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM;
7942
7943 // All other current entries will be MEMBER_OF the combined entry
7944 // (except for PTR_AND_OBJ entries which do not have a placeholder value
7945 // 0xFFFF in the MEMBER_OF field).
7946 OpenMPOffloadMappingFlags MemberOfFlag =
7947 getMemberOfFlag(BasePointers.size() - 1);
7948 for (auto &M : CurTypes)
7949 setCorrectMemberOfFlag(M, MemberOfFlag);
7950 }
7951
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007952 /// Generate all the base pointers, section pointers, sizes and map
Samuel Antaocc10b852016-07-28 14:23:26 +00007953 /// types for the extracted mappable expressions. Also, for each item that
7954 /// relates with a device pointer, a pair of the relevant declaration and
7955 /// index where it occurs is appended to the device pointers info array.
7956 void generateAllInfo(MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007957 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7958 MapFlagsArrayTy &Types) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007959 // We have to process the component lists that relate with the same
7960 // declaration in a single chunk so that we can generate the map flags
7961 // correctly. Therefore, we organize all lists in a map.
Alexey Bataev5d1c3f62017-06-27 15:46:42 +00007962 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
Samuel Antao8d2d7302016-05-26 18:30:22 +00007963
7964 // Helper function to fill the information map for the different supported
7965 // clauses.
Samuel Antaocc10b852016-07-28 14:23:26 +00007966 auto &&InfoGen = [&Info](
7967 const ValueDecl *D,
7968 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
Kelvin Lief579432018-12-18 22:18:41 +00007969 OpenMPMapClauseKind MapType,
7970 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007971 bool ReturnDevicePointer, bool IsImplicit) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007972 const ValueDecl *VD =
7973 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
Kelvin Lief579432018-12-18 22:18:41 +00007974 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007975 IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00007976 };
Samuel Antao8d2d7302016-05-26 18:30:22 +00007977
Michael Krused47b9432019-08-05 18:43:21 +00007978 assert(CurDir.is<const OMPExecutableDirective *>() &&
7979 "Expect a executable directive");
7980 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
7981 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>())
Mark de Wever51abceb2019-11-12 20:48:11 +01007982 for (const auto L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007983 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(),
Alexey Bataevb3638132018-07-19 16:34:13 +00007984 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007985 }
Michael Krused47b9432019-08-05 18:43:21 +00007986 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>())
Mark de Wever51abceb2019-11-12 20:48:11 +01007987 for (const auto L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007988 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007989 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007990 }
Michael Krused47b9432019-08-05 18:43:21 +00007991 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>())
Mark de Wever51abceb2019-11-12 20:48:11 +01007992 for (const auto L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007993 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007994 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007995 }
Samuel Antao86ace552016-04-27 22:40:57 +00007996
Samuel Antaocc10b852016-07-28 14:23:26 +00007997 // Look at the use_device_ptr clause information and mark the existing map
7998 // entries as such. If there is no map information for an entry in the
7999 // use_device_ptr list, we create one with map type 'alloc' and zero size
Alexey Bataevb3638132018-07-19 16:34:13 +00008000 // section. It is the user fault if that was not mapped before. If there is
8001 // no map information and the pointer is a struct member, then we defer the
8002 // emission of that entry until the whole struct has been processed.
8003 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>>
8004 DeferredInfo;
8005
Alexey Bataevb3638132018-07-19 16:34:13 +00008006 for (const auto *C :
Michael Krused47b9432019-08-05 18:43:21 +00008007 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) {
Mark de Wever51abceb2019-11-12 20:48:11 +01008008 for (const auto L : C->component_lists()) {
Samuel Antaocc10b852016-07-28 14:23:26 +00008009 assert(!L.second.empty() && "Not expecting empty list of components!");
8010 const ValueDecl *VD = L.second.back().getAssociatedDeclaration();
8011 VD = cast<ValueDecl>(VD->getCanonicalDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008012 const Expr *IE = L.second.back().getAssociatedExpression();
Samuel Antaocc10b852016-07-28 14:23:26 +00008013 // If the first component is a member expression, we have to look into
8014 // 'this', which maps to null in the map of map information. Otherwise
8015 // look directly for the information.
8016 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
8017
8018 // We potentially have map information for this declaration already.
8019 // Look for the first set of components that refer to it.
8020 if (It != Info.end()) {
8021 auto CI = std::find_if(
8022 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) {
8023 return MI.Components.back().getAssociatedDeclaration() == VD;
8024 });
8025 // If we found a map entry, signal that the pointer has to be returned
8026 // and move on to the next declaration.
8027 if (CI != It->second.end()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00008028 CI->ReturnDevicePointer = true;
Samuel Antaocc10b852016-07-28 14:23:26 +00008029 continue;
8030 }
8031 }
8032
8033 // We didn't find any match in our map information - generate a zero
Alexey Bataevb3638132018-07-19 16:34:13 +00008034 // size array section - if the pointer is a struct member we defer this
8035 // action until the whole struct has been processed.
Alexey Bataevb3638132018-07-19 16:34:13 +00008036 if (isa<MemberExpr>(IE)) {
8037 // Insert the pointer into Info to be processed by
8038 // generateInfoForComponentList. Because it is a member pointer
8039 // without a pointee, no entry will be generated for it, therefore
8040 // we need to generate one after the whole struct has been processed.
8041 // Nonetheless, generateInfoForComponentList must be called to take
8042 // the pointer into account for the calculation of the range of the
8043 // partial struct.
Kelvin Lief579432018-12-18 22:18:41 +00008044 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00008045 /*ReturnDevicePointer=*/false, C->isImplicit());
8046 DeferredInfo[nullptr].emplace_back(IE, VD);
8047 } else {
Michael Krused47b9432019-08-05 18:43:21 +00008048 llvm::Value *Ptr =
8049 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc());
Alexey Bataevb3638132018-07-19 16:34:13 +00008050 BasePointers.emplace_back(Ptr, VD);
8051 Pointers.push_back(Ptr);
Michael Krused47b9432019-08-05 18:43:21 +00008052 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00008053 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM);
8054 }
Samuel Antaocc10b852016-07-28 14:23:26 +00008055 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008056 }
Samuel Antaocc10b852016-07-28 14:23:26 +00008057
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008058 for (const auto &M : Info) {
Samuel Antao86ace552016-04-27 22:40:57 +00008059 // We need to know when we generate information for the first component
8060 // associated with a capture, because the mapping flags depend on it.
8061 bool IsFirstComponentList = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00008062
8063 // Temporary versions of arrays
8064 MapBaseValuesArrayTy CurBasePointers;
8065 MapValuesArrayTy CurPointers;
8066 MapValuesArrayTy CurSizes;
8067 MapFlagsArrayTy CurTypes;
8068 StructRangeInfoTy PartialStruct;
8069
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008070 for (const MapInfo &L : M.second) {
Samuel Antao86ace552016-04-27 22:40:57 +00008071 assert(!L.Components.empty() &&
8072 "Not expecting declaration with no component lists.");
Samuel Antaocc10b852016-07-28 14:23:26 +00008073
8074 // Remember the current base pointer index.
Alexey Bataevb3638132018-07-19 16:34:13 +00008075 unsigned CurrentBasePointersIdx = CurBasePointers.size();
Michael Krused47b9432019-08-05 18:43:21 +00008076 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8077 CurBasePointers, CurPointers, CurSizes,
8078 CurTypes, PartialStruct,
8079 IsFirstComponentList, L.IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00008080
8081 // If this entry relates with a device pointer, set the relevant
8082 // declaration and add the 'return pointer' flag.
Alexey Bataevb3638132018-07-19 16:34:13 +00008083 if (L.ReturnDevicePointer) {
8084 assert(CurBasePointers.size() > CurrentBasePointersIdx &&
Samuel Antaocc10b852016-07-28 14:23:26 +00008085 "Unexpected number of mapped base pointers.");
8086
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008087 const ValueDecl *RelevantVD =
8088 L.Components.back().getAssociatedDeclaration();
Samuel Antaocc10b852016-07-28 14:23:26 +00008089 assert(RelevantVD &&
8090 "No relevant declaration related with device pointer??");
8091
Alexey Bataevb3638132018-07-19 16:34:13 +00008092 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD);
8093 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008094 }
Samuel Antao86ace552016-04-27 22:40:57 +00008095 IsFirstComponentList = false;
8096 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008097
8098 // Append any pending zero-length pointers which are struct members and
8099 // used with use_device_ptr.
8100 auto CI = DeferredInfo.find(M.first);
8101 if (CI != DeferredInfo.end()) {
8102 for (const DeferredDevicePtrEntryTy &L : CI->second) {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008103 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF);
Alexey Bataevb3638132018-07-19 16:34:13 +00008104 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar(
8105 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc());
8106 CurBasePointers.emplace_back(BasePtr, L.VD);
8107 CurPointers.push_back(Ptr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008108 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00008109 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder
8110 // value MEMBER_OF=FFFF so that the entry is later updated with the
8111 // correct value of MEMBER_OF.
8112 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM |
8113 OMP_MAP_MEMBER_OF);
8114 }
8115 }
8116
8117 // If there is an entry in PartialStruct it means we have a struct with
8118 // individual members mapped. Emit an extra combined entry.
8119 if (PartialStruct.Base.isValid())
8120 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8121 PartialStruct);
8122
8123 // We need to append the results of this capture to what we already have.
8124 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8125 Pointers.append(CurPointers.begin(), CurPointers.end());
8126 Sizes.append(CurSizes.begin(), CurSizes.end());
8127 Types.append(CurTypes.begin(), CurTypes.end());
Samuel Antao86ace552016-04-27 22:40:57 +00008128 }
8129 }
8130
Michael Krused47b9432019-08-05 18:43:21 +00008131 /// Generate all the base pointers, section pointers, sizes and map types for
8132 /// the extracted map clauses of user-defined mapper.
8133 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers,
8134 MapValuesArrayTy &Pointers,
8135 MapValuesArrayTy &Sizes,
8136 MapFlagsArrayTy &Types) const {
8137 assert(CurDir.is<const OMPDeclareMapperDecl *>() &&
8138 "Expect a declare mapper directive");
8139 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>();
8140 // We have to process the component lists that relate with the same
8141 // declaration in a single chunk so that we can generate the map flags
8142 // correctly. Therefore, we organize all lists in a map.
8143 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
8144
8145 // Helper function to fill the information map for the different supported
8146 // clauses.
8147 auto &&InfoGen = [&Info](
8148 const ValueDecl *D,
8149 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
8150 OpenMPMapClauseKind MapType,
8151 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8152 bool ReturnDevicePointer, bool IsImplicit) {
8153 const ValueDecl *VD =
8154 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
8155 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
8156 IsImplicit);
8157 };
8158
8159 for (const auto *C : CurMapperDir->clauselists()) {
8160 const auto *MC = cast<OMPMapClause>(C);
Mark de Wever51abceb2019-11-12 20:48:11 +01008161 for (const auto L : MC->component_lists()) {
Michael Krused47b9432019-08-05 18:43:21 +00008162 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(),
8163 /*ReturnDevicePointer=*/false, MC->isImplicit());
8164 }
8165 }
8166
8167 for (const auto &M : Info) {
8168 // We need to know when we generate information for the first component
8169 // associated with a capture, because the mapping flags depend on it.
8170 bool IsFirstComponentList = true;
8171
8172 // Temporary versions of arrays
8173 MapBaseValuesArrayTy CurBasePointers;
8174 MapValuesArrayTy CurPointers;
8175 MapValuesArrayTy CurSizes;
8176 MapFlagsArrayTy CurTypes;
8177 StructRangeInfoTy PartialStruct;
8178
8179 for (const MapInfo &L : M.second) {
8180 assert(!L.Components.empty() &&
8181 "Not expecting declaration with no component lists.");
8182 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8183 CurBasePointers, CurPointers, CurSizes,
8184 CurTypes, PartialStruct,
8185 IsFirstComponentList, L.IsImplicit);
8186 IsFirstComponentList = false;
8187 }
8188
8189 // If there is an entry in PartialStruct it means we have a struct with
8190 // individual members mapped. Emit an extra combined entry.
8191 if (PartialStruct.Base.isValid())
8192 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8193 PartialStruct);
8194
8195 // We need to append the results of this capture to what we already have.
8196 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8197 Pointers.append(CurPointers.begin(), CurPointers.end());
8198 Sizes.append(CurSizes.begin(), CurSizes.end());
8199 Types.append(CurTypes.begin(), CurTypes.end());
8200 }
8201 }
8202
Alexey Bataev60705422018-10-30 15:50:12 +00008203 /// Emit capture info for lambdas for variables captured by reference.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008204 void generateInfoForLambdaCaptures(
8205 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers,
8206 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
8207 MapFlagsArrayTy &Types,
8208 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008209 const auto *RD = VD->getType()
8210 .getCanonicalType()
8211 .getNonReferenceType()
8212 ->getAsCXXRecordDecl();
8213 if (!RD || !RD->isLambda())
8214 return;
8215 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD));
8216 LValue VDLVal = CGF.MakeAddrLValue(
8217 VDAddr, VD->getType().getCanonicalType().getNonReferenceType());
8218 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
8219 FieldDecl *ThisCapture = nullptr;
8220 RD->getCaptureFields(Captures, ThisCapture);
8221 if (ThisCapture) {
8222 LValue ThisLVal =
8223 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture);
Alexey Bataev969dbc02018-11-08 15:47:39 +00008224 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008225 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
8226 VDLVal.getPointer(CGF));
8227 BasePointers.push_back(ThisLVal.getPointer(CGF));
8228 Pointers.push_back(ThisLValVal.getPointer(CGF));
Alexey Bataeva90fc662019-06-25 16:00:43 +00008229 Sizes.push_back(
8230 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8231 CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008232 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008233 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8234 }
8235 for (const LambdaCapture &LC : RD->captures()) {
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008236 if (!LC.capturesVariable())
Alexey Bataev60705422018-10-30 15:50:12 +00008237 continue;
8238 const VarDecl *VD = LC.getCapturedVar();
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008239 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType())
8240 continue;
Alexey Bataev60705422018-10-30 15:50:12 +00008241 auto It = Captures.find(VD);
8242 assert(It != Captures.end() && "Found lambda capture without field.");
8243 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second);
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008244 if (LC.getCaptureKind() == LCK_ByRef) {
8245 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008246 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
8247 VDLVal.getPointer(CGF));
8248 BasePointers.push_back(VarLVal.getPointer(CGF));
8249 Pointers.push_back(VarLValVal.getPointer(CGF));
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008250 Sizes.push_back(CGF.Builder.CreateIntCast(
8251 CGF.getTypeSize(
8252 VD->getType().getCanonicalType().getNonReferenceType()),
8253 CGF.Int64Ty, /*isSigned=*/true));
8254 } else {
8255 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008256 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
8257 VDLVal.getPointer(CGF));
8258 BasePointers.push_back(VarLVal.getPointer(CGF));
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008259 Pointers.push_back(VarRVal.getScalarVal());
8260 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0));
8261 }
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008262 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008263 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8264 }
8265 }
8266
8267 /// Set correct indices for lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008268 void adjustMemberOfForLambdaCaptures(
8269 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
8270 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
8271 MapFlagsArrayTy &Types) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008272 for (unsigned I = 0, E = Types.size(); I < E; ++I) {
8273 // Set correct member_of idx for all implicit lambda captures.
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008274 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008275 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT))
8276 continue;
Alexey Bataev969dbc02018-11-08 15:47:39 +00008277 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]);
8278 assert(BasePtr && "Unable to find base lambda address.");
Alexey Bataev60705422018-10-30 15:50:12 +00008279 int TgtIdx = -1;
8280 for (unsigned J = I; J > 0; --J) {
8281 unsigned Idx = J - 1;
8282 if (Pointers[Idx] != BasePtr)
8283 continue;
8284 TgtIdx = Idx;
8285 break;
8286 }
8287 assert(TgtIdx != -1 && "Unable to find parent lambda.");
8288 // All other current entries will be MEMBER_OF the combined entry
8289 // (except for PTR_AND_OBJ entries which do not have a placeholder value
8290 // 0xFFFF in the MEMBER_OF field).
8291 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx);
8292 setCorrectMemberOfFlag(Types[I], MemberOfFlag);
8293 }
8294 }
8295
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008296 /// Generate the base pointers, section pointers, sizes and map types
Samuel Antao86ace552016-04-27 22:40:57 +00008297 /// associated to a given capture.
8298 void generateInfoForCapture(const CapturedStmt::Capture *Cap,
Samuel Antao6890b092016-07-28 14:25:09 +00008299 llvm::Value *Arg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008300 MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00008301 MapValuesArrayTy &Pointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008302 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
8303 StructRangeInfoTy &PartialStruct) const {
Samuel Antao86ace552016-04-27 22:40:57 +00008304 assert(!Cap->capturesVariableArrayType() &&
8305 "Not expecting to generate map info for a variable array type!");
8306
Samuel Antao6890b092016-07-28 14:25:09 +00008307 // We need to know when we generating information for the first component
Alexey Bataevb3638132018-07-19 16:34:13 +00008308 const ValueDecl *VD = Cap->capturesThis()
8309 ? nullptr
8310 : Cap->getCapturedVar()->getCanonicalDecl();
Samuel Antao86ace552016-04-27 22:40:57 +00008311
Samuel Antao6890b092016-07-28 14:25:09 +00008312 // If this declaration appears in a is_device_ptr clause we just have to
8313 // pass the pointer by value. If it is a reference to a declaration, we just
Alexey Bataevb3638132018-07-19 16:34:13 +00008314 // pass its value.
8315 if (DevPointersMap.count(VD)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008316 BasePointers.emplace_back(Arg, VD);
Samuel Antao6890b092016-07-28 14:25:09 +00008317 Pointers.push_back(Arg);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008318 Sizes.push_back(
8319 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8320 CGF.Int64Ty, /*isSigned=*/true));
George Rokos065755d2017-11-07 18:27:04 +00008321 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM);
Samuel Antao6890b092016-07-28 14:25:09 +00008322 return;
8323 }
8324
Alexey Bataeve82445f2018-09-20 13:54:02 +00008325 using MapData =
8326 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
Kelvin Lief579432018-12-18 22:18:41 +00008327 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008328 SmallVector<MapData, 4> DeclComponentLists;
Michael Krused47b9432019-08-05 18:43:21 +00008329 assert(CurDir.is<const OMPExecutableDirective *>() &&
8330 "Expect a executable directive");
8331 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
8332 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
Mark de Wever51abceb2019-11-12 20:48:11 +01008333 for (const auto L : C->decl_component_lists(VD)) {
Samuel Antao86ace552016-04-27 22:40:57 +00008334 assert(L.first == VD &&
8335 "We got information for the wrong declaration??");
8336 assert(!L.second.empty() &&
8337 "Not expecting declaration with no component lists.");
Alexey Bataeve82445f2018-09-20 13:54:02 +00008338 DeclComponentLists.emplace_back(L.second, C->getMapType(),
Kelvin Lief579432018-12-18 22:18:41 +00008339 C->getMapTypeModifiers(),
Alexey Bataeve82445f2018-09-20 13:54:02 +00008340 C->isImplicit());
Samuel Antao86ace552016-04-27 22:40:57 +00008341 }
Alexey Bataeve82445f2018-09-20 13:54:02 +00008342 }
8343
8344 // Find overlapping elements (including the offset from the base element).
8345 llvm::SmallDenseMap<
8346 const MapData *,
8347 llvm::SmallVector<
8348 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>,
8349 4>
8350 OverlappedData;
8351 size_t Count = 0;
8352 for (const MapData &L : DeclComponentLists) {
8353 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8354 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008355 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008356 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008357 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008358 ++Count;
8359 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) {
8360 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1;
Kelvin Lief579432018-12-18 22:18:41 +00008361 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008362 auto CI = Components.rbegin();
8363 auto CE = Components.rend();
8364 auto SI = Components1.rbegin();
8365 auto SE = Components1.rend();
8366 for (; CI != CE && SI != SE; ++CI, ++SI) {
8367 if (CI->getAssociatedExpression()->getStmtClass() !=
8368 SI->getAssociatedExpression()->getStmtClass())
8369 break;
8370 // Are we dealing with different variables/fields?
8371 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
8372 break;
8373 }
8374 // Found overlapping if, at least for one component, reached the head of
8375 // the components list.
8376 if (CI == CE || SI == SE) {
8377 assert((CI != CE || SI != SE) &&
8378 "Unexpected full match of the mapping components.");
8379 const MapData &BaseData = CI == CE ? L : L1;
8380 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData =
8381 SI == SE ? Components : Components1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008382 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData);
8383 OverlappedElements.getSecond().push_back(SubData);
8384 }
8385 }
8386 }
8387 // Sort the overlapped elements for each item.
8388 llvm::SmallVector<const FieldDecl *, 4> Layout;
8389 if (!OverlappedData.empty()) {
8390 if (const auto *CRD =
8391 VD->getType().getCanonicalType()->getAsCXXRecordDecl())
8392 getPlainLayout(CRD, Layout, /*AsBase=*/false);
8393 else {
8394 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl();
8395 Layout.append(RD->field_begin(), RD->field_end());
8396 }
8397 }
8398 for (auto &Pair : OverlappedData) {
8399 llvm::sort(
8400 Pair.getSecond(),
8401 [&Layout](
8402 OMPClauseMappableExprCommon::MappableExprComponentListRef First,
8403 OMPClauseMappableExprCommon::MappableExprComponentListRef
8404 Second) {
8405 auto CI = First.rbegin();
8406 auto CE = First.rend();
8407 auto SI = Second.rbegin();
8408 auto SE = Second.rend();
8409 for (; CI != CE && SI != SE; ++CI, ++SI) {
8410 if (CI->getAssociatedExpression()->getStmtClass() !=
8411 SI->getAssociatedExpression()->getStmtClass())
8412 break;
8413 // Are we dealing with different variables/fields?
8414 if (CI->getAssociatedDeclaration() !=
8415 SI->getAssociatedDeclaration())
8416 break;
8417 }
Richard Trieu5061e832018-09-21 21:20:33 +00008418
8419 // Lists contain the same elements.
8420 if (CI == CE && SI == SE)
8421 return false;
8422
8423 // List with less elements is less than list with more elements.
8424 if (CI == CE || SI == SE)
8425 return CI == CE;
8426
Alexey Bataeve82445f2018-09-20 13:54:02 +00008427 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
8428 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
8429 if (FD1->getParent() == FD2->getParent())
8430 return FD1->getFieldIndex() < FD2->getFieldIndex();
8431 const auto It =
8432 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) {
8433 return FD == FD1 || FD == FD2;
8434 });
8435 return *It == FD1;
8436 });
8437 }
8438
8439 // Associated with a capture, because the mapping flags depend on it.
8440 // Go through all of the elements with the overlapped elements.
8441 for (const auto &Pair : OverlappedData) {
8442 const MapData &L = *Pair.getFirst();
8443 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8444 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008445 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008446 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008447 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008448 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
8449 OverlappedComponents = Pair.getSecond();
8450 bool IsFirstComponentList = true;
Kelvin Lief579432018-12-18 22:18:41 +00008451 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008452 BasePointers, Pointers, Sizes, Types,
8453 PartialStruct, IsFirstComponentList,
8454 IsImplicit, OverlappedComponents);
8455 }
8456 // Go through other elements without overlapped elements.
8457 bool IsFirstComponentList = OverlappedData.empty();
8458 for (const MapData &L : DeclComponentLists) {
8459 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8460 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008461 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008462 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008463 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008464 auto It = OverlappedData.find(&L);
8465 if (It == OverlappedData.end())
Kelvin Lief579432018-12-18 22:18:41 +00008466 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008467 BasePointers, Pointers, Sizes, Types,
8468 PartialStruct, IsFirstComponentList,
8469 IsImplicit);
8470 IsFirstComponentList = false;
8471 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008472 }
Samuel Antao86ace552016-04-27 22:40:57 +00008473
Alexey Bataevb3638132018-07-19 16:34:13 +00008474 /// Generate the base pointers, section pointers, sizes and map types
8475 /// associated with the declare target link variables.
8476 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers,
8477 MapValuesArrayTy &Pointers,
8478 MapValuesArrayTy &Sizes,
8479 MapFlagsArrayTy &Types) const {
Michael Krused47b9432019-08-05 18:43:21 +00008480 assert(CurDir.is<const OMPExecutableDirective *>() &&
8481 "Expect a executable directive");
8482 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
Alexey Bataevb3638132018-07-19 16:34:13 +00008483 // Map other list items in the map clause which are not captured variables
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00008484 // but "declare target link" global variables.
Michael Krused47b9432019-08-05 18:43:21 +00008485 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
Mark de Wever51abceb2019-11-12 20:48:11 +01008486 for (const auto L : C->component_lists()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00008487 if (!L.first)
8488 continue;
8489 const auto *VD = dyn_cast<VarDecl>(L.first);
8490 if (!VD)
8491 continue;
8492 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00008493 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00008494 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
8495 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)
Alexey Bataevb3638132018-07-19 16:34:13 +00008496 continue;
8497 StructRangeInfoTy PartialStruct;
8498 generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00008499 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008500 Pointers, Sizes, Types, PartialStruct,
8501 /*IsFirstComponentList=*/true, C->isImplicit());
8502 assert(!PartialStruct.Base.isValid() &&
8503 "No partial structs for declare target link expected.");
8504 }
8505 }
Samuel Antao86ace552016-04-27 22:40:57 +00008506 }
Samuel Antaod486f842016-05-26 16:53:38 +00008507
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008508 /// Generate the default map information for a given capture \a CI,
Samuel Antaod486f842016-05-26 16:53:38 +00008509 /// record field declaration \a RI and captured value \a CV.
Samuel Antaocc10b852016-07-28 14:23:26 +00008510 void generateDefaultMapInfo(const CapturedStmt::Capture &CI,
8511 const FieldDecl &RI, llvm::Value *CV,
8512 MapBaseValuesArrayTy &CurBasePointers,
8513 MapValuesArrayTy &CurPointers,
8514 MapValuesArrayTy &CurSizes,
Alexey Bataevb3638132018-07-19 16:34:13 +00008515 MapFlagsArrayTy &CurMapTypes) const {
Alexey Bataevf288cf92019-06-27 18:53:07 +00008516 bool IsImplicit = true;
Samuel Antaod486f842016-05-26 16:53:38 +00008517 // Do the default mapping.
8518 if (CI.capturesThis()) {
8519 CurBasePointers.push_back(CV);
8520 CurPointers.push_back(CV);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008521 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr());
Alexey Bataeva90fc662019-06-25 16:00:43 +00008522 CurSizes.push_back(
8523 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()),
8524 CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008525 // Default map type.
Samuel Antaocc10b852016-07-28 14:23:26 +00008526 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM);
Samuel Antaod486f842016-05-26 16:53:38 +00008527 } else if (CI.capturesVariableByCopy()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008528 CurBasePointers.push_back(CV);
8529 CurPointers.push_back(CV);
Samuel Antaod486f842016-05-26 16:53:38 +00008530 if (!RI.getType()->isAnyPointerType()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008531 // We have to signal to the runtime captures passed by value that are
8532 // not pointers.
George Rokos065755d2017-11-07 18:27:04 +00008533 CurMapTypes.push_back(OMP_MAP_LITERAL);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008534 CurSizes.push_back(CGF.Builder.CreateIntCast(
8535 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008536 } else {
8537 // Pointers are implicitly mapped with a zero size and no flags
8538 // (other than first map that is added for all implicit maps).
Alexey Bataevb3638132018-07-19 16:34:13 +00008539 CurMapTypes.push_back(OMP_MAP_NONE);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008540 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
Samuel Antaod486f842016-05-26 16:53:38 +00008541 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008542 const VarDecl *VD = CI.getCapturedVar();
8543 auto I = FirstPrivateDecls.find(VD);
8544 if (I != FirstPrivateDecls.end())
8545 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008546 } else {
8547 assert(CI.capturesVariable() && "Expected captured reference.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008548 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr());
Samuel Antaod486f842016-05-26 16:53:38 +00008549 QualType ElementType = PtrTy->getPointeeType();
Alexey Bataeva90fc662019-06-25 16:00:43 +00008550 CurSizes.push_back(CGF.Builder.CreateIntCast(
8551 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008552 // The default map type for a scalar/complex type is 'to' because by
8553 // default the value doesn't have to be retrieved. For an aggregate
8554 // type, the default is 'tofrom'.
Alexey Bataevb3638132018-07-19 16:34:13 +00008555 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI));
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008556 const VarDecl *VD = CI.getCapturedVar();
Alexey Bataevf288cf92019-06-27 18:53:07 +00008557 auto I = FirstPrivateDecls.find(VD);
8558 if (I != FirstPrivateDecls.end() &&
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008559 VD->getType().isConstant(CGF.getContext())) {
8560 llvm::Constant *Addr =
8561 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD);
8562 // Copy the value of the original variable to the new global copy.
8563 CGF.Builder.CreateMemCpy(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008564 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(CGF),
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008565 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)),
Rui Ueyama49a3ad22019-07-16 04:46:31 +00008566 CurSizes.back(), /*IsVolatile=*/false);
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008567 // Use new global variable as the base pointers.
8568 CurBasePointers.push_back(Addr);
8569 CurPointers.push_back(Addr);
8570 } else {
8571 CurBasePointers.push_back(CV);
Alexey Bataevf288cf92019-06-27 18:53:07 +00008572 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) {
Alexey Bataevc2b831f2019-04-02 16:03:40 +00008573 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue(
8574 CV, ElementType, CGF.getContext().getDeclAlign(VD),
8575 AlignmentSource::Decl));
8576 CurPointers.push_back(PtrAddr.getPointer());
8577 } else {
8578 CurPointers.push_back(CV);
8579 }
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008580 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008581 if (I != FirstPrivateDecls.end())
8582 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008583 }
George Rokos065755d2017-11-07 18:27:04 +00008584 // Every default map produces a single argument which is a target parameter.
8585 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM;
Alexey Bataevb3638132018-07-19 16:34:13 +00008586
8587 // Add flag stating this is an implicit map.
Alexey Bataevf288cf92019-06-27 18:53:07 +00008588 if (IsImplicit)
8589 CurMapTypes.back() |= OMP_MAP_IMPLICIT;
Samuel Antaod486f842016-05-26 16:53:38 +00008590 }
Samuel Antao86ace552016-04-27 22:40:57 +00008591};
Samuel Antaodf158d52016-04-27 22:58:19 +00008592} // anonymous namespace
8593
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008594/// Emit the arrays used to pass the captures and map information to the
Samuel Antaodf158d52016-04-27 22:58:19 +00008595/// offloading runtime library. If there is no map or capture information,
8596/// return nullptr by reference.
8597static void
Samuel Antaocc10b852016-07-28 14:23:26 +00008598emitOffloadingArrays(CodeGenFunction &CGF,
8599 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers,
Samuel Antaodf158d52016-04-27 22:58:19 +00008600 MappableExprsHandler::MapValuesArrayTy &Pointers,
8601 MappableExprsHandler::MapValuesArrayTy &Sizes,
Samuel Antaocc10b852016-07-28 14:23:26 +00008602 MappableExprsHandler::MapFlagsArrayTy &MapTypes,
8603 CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008604 CodeGenModule &CGM = CGF.CGM;
8605 ASTContext &Ctx = CGF.getContext();
Samuel Antaodf158d52016-04-27 22:58:19 +00008606
Samuel Antaocc10b852016-07-28 14:23:26 +00008607 // Reset the array information.
8608 Info.clearArrayInfo();
8609 Info.NumberOfPtrs = BasePointers.size();
Samuel Antaodf158d52016-04-27 22:58:19 +00008610
Samuel Antaocc10b852016-07-28 14:23:26 +00008611 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008612 // Detect if we have any capture size requiring runtime evaluation of the
8613 // size so that a constant array could be eventually used.
8614 bool hasRuntimeEvaluationCaptureSize = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008615 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008616 if (!isa<llvm::Constant>(S)) {
8617 hasRuntimeEvaluationCaptureSize = true;
8618 break;
8619 }
8620
Samuel Antaocc10b852016-07-28 14:23:26 +00008621 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true);
Richard Smith772e2662019-10-04 01:25:59 +00008622 QualType PointerArrayType = Ctx.getConstantArrayType(
8623 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal,
8624 /*IndexTypeQuals=*/0);
Samuel Antaodf158d52016-04-27 22:58:19 +00008625
Samuel Antaocc10b852016-07-28 14:23:26 +00008626 Info.BasePointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008627 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
Samuel Antaocc10b852016-07-28 14:23:26 +00008628 Info.PointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008629 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
8630
8631 // If we don't have any VLA types or other types that require runtime
8632 // evaluation, we can use a constant array for the map sizes, otherwise we
8633 // need to fill up the arrays as we do for the pointers.
Alexey Bataeva90fc662019-06-25 16:00:43 +00008634 QualType Int64Ty =
8635 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Samuel Antaodf158d52016-04-27 22:58:19 +00008636 if (hasRuntimeEvaluationCaptureSize) {
Richard Smith772e2662019-10-04 01:25:59 +00008637 QualType SizeArrayType = Ctx.getConstantArrayType(
8638 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal,
8639 /*IndexTypeQuals=*/0);
Samuel Antaocc10b852016-07-28 14:23:26 +00008640 Info.SizesArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008641 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
8642 } else {
8643 // We expect all the sizes to be constant, so we collect them to create
8644 // a constant array.
8645 SmallVector<llvm::Constant *, 16> ConstSizes;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008646 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008647 ConstSizes.push_back(cast<llvm::Constant>(S));
8648
8649 auto *SizesArrayInit = llvm::ConstantArray::get(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008650 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008651 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008652 auto *SizesArrayGbl = new llvm::GlobalVariable(
8653 CGM.getModule(), SizesArrayInit->getType(),
8654 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008655 SizesArrayInit, Name);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008656 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008657 Info.SizesArray = SizesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008658 }
8659
8660 // The map types are always constant so we don't need to generate code to
8661 // fill arrays. Instead, we create an array constant.
Alexey Bataevb3638132018-07-19 16:34:13 +00008662 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0);
8663 llvm::copy(MapTypes, Mapping.begin());
Samuel Antaodf158d52016-04-27 22:58:19 +00008664 llvm::Constant *MapTypesArrayInit =
Alexey Bataevb3638132018-07-19 16:34:13 +00008665 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008666 std::string MaptypesName =
8667 CGM.getOpenMPRuntime().getName({"offload_maptypes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008668 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
8669 CGM.getModule(), MapTypesArrayInit->getType(),
8670 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008671 MapTypesArrayInit, MaptypesName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008672 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008673 Info.MapTypesArray = MapTypesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008674
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008675 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) {
8676 llvm::Value *BPVal = *BasePointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008677 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008678 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008679 Info.BasePointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008680 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8681 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008682 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8683 CGF.Builder.CreateStore(BPVal, BPAddr);
8684
Samuel Antaocc10b852016-07-28 14:23:26 +00008685 if (Info.requiresDevicePointerInfo())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008686 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl())
Alexey Bataev43a919f2018-04-13 17:48:43 +00008687 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr);
Samuel Antaocc10b852016-07-28 14:23:26 +00008688
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008689 llvm::Value *PVal = Pointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008690 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008691 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008692 Info.PointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008693 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8694 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008695 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8696 CGF.Builder.CreateStore(PVal, PAddr);
8697
8698 if (hasRuntimeEvaluationCaptureSize) {
8699 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008700 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008701 Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008702 /*Idx0=*/0,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008703 /*Idx1=*/I);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008704 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty));
Samuel Antaodf158d52016-04-27 22:58:19 +00008705 CGF.Builder.CreateStore(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008706 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true),
Samuel Antaodf158d52016-04-27 22:58:19 +00008707 SAddr);
8708 }
8709 }
8710 }
8711}
Michael Krused47b9432019-08-05 18:43:21 +00008712
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008713/// Emit the arguments to be passed to the runtime library based on the
Samuel Antaodf158d52016-04-27 22:58:19 +00008714/// arrays of pointers, sizes and map types.
8715static void emitOffloadingArraysArgument(
8716 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg,
8717 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008718 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008719 CodeGenModule &CGM = CGF.CGM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008720 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008721 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008722 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8723 Info.BasePointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008724 /*Idx0=*/0, /*Idx1=*/0);
8725 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008726 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8727 Info.PointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008728 /*Idx0=*/0,
8729 /*Idx1=*/0);
8730 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008731 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008732 /*Idx0=*/0, /*Idx1=*/0);
8733 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
George Rokos63bc9d62017-11-21 18:25:12 +00008734 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008735 Info.MapTypesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008736 /*Idx0=*/0,
8737 /*Idx1=*/0);
8738 } else {
8739 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
8740 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008741 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008742 MapTypesArrayArg =
George Rokos63bc9d62017-11-21 18:25:12 +00008743 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008744 }
Samuel Antao86ace552016-04-27 22:40:57 +00008745}
8746
Alexey Bataev7bb33532019-01-07 21:30:43 +00008747/// Check for inner distribute directive.
8748static const OMPExecutableDirective *
8749getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
8750 const auto *CS = D.getInnermostCapturedStmt();
8751 const auto *Body =
8752 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00008753 const Stmt *ChildStmt =
8754 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
Alexey Bataev7bb33532019-01-07 21:30:43 +00008755
Alexey Bataev5c427362019-04-10 19:11:33 +00008756 if (const auto *NestedDir =
8757 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008758 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind();
8759 switch (D.getDirectiveKind()) {
8760 case OMPD_target:
8761 if (isOpenMPDistributeDirective(DKind))
8762 return NestedDir;
8763 if (DKind == OMPD_teams) {
8764 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
8765 /*IgnoreCaptured=*/true);
8766 if (!Body)
8767 return nullptr;
Alexey Bataev5c427362019-04-10 19:11:33 +00008768 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
8769 if (const auto *NND =
8770 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008771 DKind = NND->getDirectiveKind();
8772 if (isOpenMPDistributeDirective(DKind))
8773 return NND;
8774 }
8775 }
8776 return nullptr;
8777 case OMPD_target_teams:
8778 if (isOpenMPDistributeDirective(DKind))
8779 return NestedDir;
8780 return nullptr;
8781 case OMPD_target_parallel:
8782 case OMPD_target_simd:
8783 case OMPD_target_parallel_for:
8784 case OMPD_target_parallel_for_simd:
8785 return nullptr;
8786 case OMPD_target_teams_distribute:
8787 case OMPD_target_teams_distribute_simd:
8788 case OMPD_target_teams_distribute_parallel_for:
8789 case OMPD_target_teams_distribute_parallel_for_simd:
8790 case OMPD_parallel:
8791 case OMPD_for:
8792 case OMPD_parallel_for:
cchen47d60942019-12-05 13:43:48 -05008793 case OMPD_parallel_master:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008794 case OMPD_parallel_sections:
8795 case OMPD_for_simd:
8796 case OMPD_parallel_for_simd:
8797 case OMPD_cancel:
8798 case OMPD_cancellation_point:
8799 case OMPD_ordered:
8800 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00008801 case OMPD_allocate:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008802 case OMPD_task:
8803 case OMPD_simd:
8804 case OMPD_sections:
8805 case OMPD_section:
8806 case OMPD_single:
8807 case OMPD_master:
8808 case OMPD_critical:
8809 case OMPD_taskyield:
8810 case OMPD_barrier:
8811 case OMPD_taskwait:
8812 case OMPD_taskgroup:
8813 case OMPD_atomic:
8814 case OMPD_flush:
8815 case OMPD_teams:
8816 case OMPD_target_data:
8817 case OMPD_target_exit_data:
8818 case OMPD_target_enter_data:
8819 case OMPD_distribute:
8820 case OMPD_distribute_simd:
8821 case OMPD_distribute_parallel_for:
8822 case OMPD_distribute_parallel_for_simd:
8823 case OMPD_teams_distribute:
8824 case OMPD_teams_distribute_simd:
8825 case OMPD_teams_distribute_parallel_for:
8826 case OMPD_teams_distribute_parallel_for_simd:
8827 case OMPD_target_update:
8828 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00008829 case OMPD_declare_variant:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008830 case OMPD_declare_target:
8831 case OMPD_end_declare_target:
8832 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00008833 case OMPD_declare_mapper:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008834 case OMPD_taskloop:
8835 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00008836 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00008837 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00008838 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04008839 case OMPD_parallel_master_taskloop_simd:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008840 case OMPD_requires:
8841 case OMPD_unknown:
8842 llvm_unreachable("Unexpected directive.");
8843 }
8844 }
8845
8846 return nullptr;
8847}
8848
Michael Krused47b9432019-08-05 18:43:21 +00008849/// Emit the user-defined mapper function. The code generation follows the
8850/// pattern in the example below.
8851/// \code
8852/// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle,
8853/// void *base, void *begin,
8854/// int64_t size, int64_t type) {
8855/// // Allocate space for an array section first.
8856/// if (size > 1 && !maptype.IsDelete)
8857/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
8858/// size*sizeof(Ty), clearToFrom(type));
8859/// // Map members.
8860/// for (unsigned i = 0; i < size; i++) {
8861/// // For each component specified by this mapper:
8862/// for (auto c : all_components) {
8863/// if (c.hasMapper())
8864/// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size,
8865/// c.arg_type);
8866/// else
8867/// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base,
8868/// c.arg_begin, c.arg_size, c.arg_type);
8869/// }
8870/// }
8871/// // Delete the array section.
8872/// if (size > 1 && maptype.IsDelete)
8873/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
8874/// size*sizeof(Ty), clearToFrom(type));
8875/// }
8876/// \endcode
8877void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D,
8878 CodeGenFunction *CGF) {
8879 if (UDMMap.count(D) > 0)
8880 return;
8881 ASTContext &C = CGM.getContext();
8882 QualType Ty = D->getType();
8883 QualType PtrTy = C.getPointerType(Ty).withRestrict();
8884 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
8885 auto *MapperVarDecl =
8886 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl());
8887 SourceLocation Loc = D->getLocation();
8888 CharUnits ElementSize = C.getTypeSizeInChars(Ty);
8889
8890 // Prepare mapper function arguments and attributes.
8891 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
8892 C.VoidPtrTy, ImplicitParamDecl::Other);
8893 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
8894 ImplicitParamDecl::Other);
8895 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
8896 C.VoidPtrTy, ImplicitParamDecl::Other);
8897 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
8898 ImplicitParamDecl::Other);
8899 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
8900 ImplicitParamDecl::Other);
8901 FunctionArgList Args;
8902 Args.push_back(&HandleArg);
8903 Args.push_back(&BaseArg);
8904 Args.push_back(&BeginArg);
8905 Args.push_back(&SizeArg);
8906 Args.push_back(&TypeArg);
8907 const CGFunctionInfo &FnInfo =
8908 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
8909 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
8910 SmallString<64> TyStr;
8911 llvm::raw_svector_ostream Out(TyStr);
8912 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out);
8913 std::string Name = getName({"omp_mapper", TyStr, D->getName()});
8914 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
8915 Name, &CGM.getModule());
8916 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
8917 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
8918 // Start the mapper function code generation.
8919 CodeGenFunction MapperCGF(CGM);
8920 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
8921 // Compute the starting and end addreses of array elements.
8922 llvm::Value *Size = MapperCGF.EmitLoadOfScalar(
8923 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false,
8924 C.getPointerType(Int64Ty), Loc);
8925 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast(
8926 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(),
8927 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy)));
8928 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size);
8929 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar(
8930 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false,
8931 C.getPointerType(Int64Ty), Loc);
8932 // Prepare common arguments for array initiation and deletion.
8933 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar(
8934 MapperCGF.GetAddrOfLocalVar(&HandleArg),
8935 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8936 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar(
8937 MapperCGF.GetAddrOfLocalVar(&BaseArg),
8938 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8939 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar(
8940 MapperCGF.GetAddrOfLocalVar(&BeginArg),
8941 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8942
8943 // Emit array initiation if this is an array section and \p MapType indicates
8944 // that memory allocation is required.
8945 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head");
8946 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
8947 ElementSize, HeadBB, /*IsInit=*/true);
8948
8949 // Emit a for loop to iterate through SizeArg of elements and map all of them.
8950
8951 // Emit the loop header block.
8952 MapperCGF.EmitBlock(HeadBB);
8953 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body");
8954 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done");
8955 // Evaluate whether the initial condition is satisfied.
8956 llvm::Value *IsEmpty =
8957 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty");
8958 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
8959 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock();
8960
8961 // Emit the loop body block.
8962 MapperCGF.EmitBlock(BodyBB);
8963 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI(
8964 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent");
8965 PtrPHI->addIncoming(PtrBegin, EntryBB);
8966 Address PtrCurrent =
8967 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg)
8968 .getAlignment()
8969 .alignmentOfArrayElement(ElementSize));
8970 // Privatize the declared variable of mapper to be the current array element.
8971 CodeGenFunction::OMPPrivateScope Scope(MapperCGF);
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08008972 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() {
Michael Krused47b9432019-08-05 18:43:21 +00008973 return MapperCGF
8974 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>())
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008975 .getAddress(MapperCGF);
Michael Krused47b9432019-08-05 18:43:21 +00008976 });
8977 (void)Scope.Privatize();
8978
8979 // Get map clause information. Fill up the arrays with all mapped variables.
8980 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
8981 MappableExprsHandler::MapValuesArrayTy Pointers;
8982 MappableExprsHandler::MapValuesArrayTy Sizes;
8983 MappableExprsHandler::MapFlagsArrayTy MapTypes;
8984 MappableExprsHandler MEHandler(*D, MapperCGF);
8985 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes);
8986
8987 // Call the runtime API __tgt_mapper_num_components to get the number of
8988 // pre-existing components.
8989 llvm::Value *OffloadingArgs[] = {Handle};
8990 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall(
8991 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs);
8992 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl(
8993 PreviousSize,
8994 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset()));
8995
8996 // Fill up the runtime mapper handle for all components.
8997 for (unsigned I = 0; I < BasePointers.size(); ++I) {
8998 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast(
8999 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
9000 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast(
9001 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
9002 llvm::Value *CurSizeArg = Sizes[I];
9003
9004 // Extract the MEMBER_OF field from the map type.
9005 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member");
9006 MapperCGF.EmitBlock(MemberBB);
9007 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]);
9008 llvm::Value *Member = MapperCGF.Builder.CreateAnd(
9009 OriMapType,
9010 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF));
9011 llvm::BasicBlock *MemberCombineBB =
9012 MapperCGF.createBasicBlock("omp.member.combine");
9013 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type");
9014 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member);
9015 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB);
9016 // Add the number of pre-existing components to the MEMBER_OF field if it
9017 // is valid.
9018 MapperCGF.EmitBlock(MemberCombineBB);
9019 llvm::Value *CombinedMember =
9020 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
9021 // Do nothing if it is not a member of previous components.
9022 MapperCGF.EmitBlock(TypeBB);
9023 llvm::PHINode *MemberMapType =
9024 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype");
9025 MemberMapType->addIncoming(OriMapType, MemberBB);
9026 MemberMapType->addIncoming(CombinedMember, MemberCombineBB);
9027
9028 // Combine the map type inherited from user-defined mapper with that
9029 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM
9030 // bits of the \a MapType, which is the input argument of the mapper
9031 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM
9032 // bits of MemberMapType.
9033 // [OpenMP 5.0], 1.2.6. map-type decay.
9034 // | alloc | to | from | tofrom | release | delete
9035 // ----------------------------------------------------------
9036 // alloc | alloc | alloc | alloc | alloc | release | delete
9037 // to | alloc | to | alloc | to | release | delete
9038 // from | alloc | alloc | from | from | release | delete
9039 // tofrom | alloc | to | from | tofrom | release | delete
9040 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd(
9041 MapType,
9042 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO |
9043 MappableExprsHandler::OMP_MAP_FROM));
9044 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc");
9045 llvm::BasicBlock *AllocElseBB =
9046 MapperCGF.createBasicBlock("omp.type.alloc.else");
9047 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to");
9048 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else");
9049 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from");
9050 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end");
9051 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom);
9052 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
9053 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM.
9054 MapperCGF.EmitBlock(AllocBB);
9055 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd(
9056 MemberMapType,
9057 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9058 MappableExprsHandler::OMP_MAP_FROM)));
9059 MapperCGF.Builder.CreateBr(EndBB);
9060 MapperCGF.EmitBlock(AllocElseBB);
9061 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ(
9062 LeftToFrom,
9063 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO));
9064 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
9065 // In case of to, clear OMP_MAP_FROM.
9066 MapperCGF.EmitBlock(ToBB);
9067 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd(
9068 MemberMapType,
9069 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM));
9070 MapperCGF.Builder.CreateBr(EndBB);
9071 MapperCGF.EmitBlock(ToElseBB);
9072 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ(
9073 LeftToFrom,
9074 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM));
9075 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB);
9076 // In case of from, clear OMP_MAP_TO.
9077 MapperCGF.EmitBlock(FromBB);
9078 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd(
9079 MemberMapType,
9080 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO));
9081 // In case of tofrom, do nothing.
9082 MapperCGF.EmitBlock(EndBB);
9083 llvm::PHINode *CurMapType =
9084 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype");
9085 CurMapType->addIncoming(AllocMapType, AllocBB);
9086 CurMapType->addIncoming(ToMapType, ToBB);
9087 CurMapType->addIncoming(FromMapType, FromBB);
9088 CurMapType->addIncoming(MemberMapType, ToElseBB);
9089
9090 // TODO: call the corresponding mapper function if a user-defined mapper is
9091 // associated with this map clause.
9092 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9093 // data structure.
9094 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg,
9095 CurSizeArg, CurMapType};
9096 MapperCGF.EmitRuntimeCall(
9097 createRuntimeFunction(OMPRTL__tgt_push_mapper_component),
9098 OffloadingArgs);
9099 }
9100
9101 // Update the pointer to point to the next element that needs to be mapped,
9102 // and check whether we have mapped all elements.
9103 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32(
9104 PtrPHI, /*Idx0=*/1, "omp.arraymap.next");
9105 PtrPHI->addIncoming(PtrNext, BodyBB);
9106 llvm::Value *IsDone =
9107 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone");
9108 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit");
9109 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
9110
9111 MapperCGF.EmitBlock(ExitBB);
9112 // Emit array deletion if this is an array section and \p MapType indicates
9113 // that deletion is required.
9114 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
9115 ElementSize, DoneBB, /*IsInit=*/false);
9116
9117 // Emit the function exit block.
9118 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true);
9119 MapperCGF.FinishFunction();
9120 UDMMap.try_emplace(D, Fn);
9121 if (CGF) {
9122 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn);
9123 Decls.second.push_back(D);
9124 }
9125}
9126
9127/// Emit the array initialization or deletion portion for user-defined mapper
9128/// code generation. First, it evaluates whether an array section is mapped and
9129/// whether the \a MapType instructs to delete this section. If \a IsInit is
9130/// true, and \a MapType indicates to not delete this array, array
9131/// initialization code is generated. If \a IsInit is false, and \a MapType
9132/// indicates to not this array, array deletion code is generated.
9133void CGOpenMPRuntime::emitUDMapperArrayInitOrDel(
9134 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base,
9135 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType,
9136 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) {
9137 StringRef Prefix = IsInit ? ".init" : ".del";
9138
9139 // Evaluate if this is an array section.
9140 llvm::BasicBlock *IsDeleteBB =
9141 MapperCGF.createBasicBlock("omp.array" + Prefix + ".evaldelete");
9142 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.array" + Prefix);
9143 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE(
9144 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray");
9145 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB);
9146
9147 // Evaluate if we are going to delete this section.
9148 MapperCGF.EmitBlock(IsDeleteBB);
9149 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd(
9150 MapType,
9151 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE));
9152 llvm::Value *DeleteCond;
9153 if (IsInit) {
9154 DeleteCond = MapperCGF.Builder.CreateIsNull(
9155 DeleteBit, "omp.array" + Prefix + ".delete");
9156 } else {
9157 DeleteCond = MapperCGF.Builder.CreateIsNotNull(
9158 DeleteBit, "omp.array" + Prefix + ".delete");
9159 }
9160 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB);
9161
9162 MapperCGF.EmitBlock(BodyBB);
9163 // Get the array size by multiplying element size and element number (i.e., \p
9164 // Size).
9165 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul(
9166 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
9167 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves
9168 // memory allocation/deletion purpose only.
9169 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd(
9170 MapType,
9171 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9172 MappableExprsHandler::OMP_MAP_FROM)));
9173 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9174 // data structure.
9175 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg};
9176 MapperCGF.EmitRuntimeCall(
9177 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs);
9178}
9179
Alexey Bataev7bb33532019-01-07 21:30:43 +00009180void CGOpenMPRuntime::emitTargetNumIterationsCall(
Alexey Bataevec7946e2019-09-23 14:06:51 +00009181 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9182 llvm::Value *DeviceID,
9183 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9184 const OMPLoopDirective &D)>
9185 SizeEmitter) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00009186 OpenMPDirectiveKind Kind = D.getDirectiveKind();
9187 const OMPExecutableDirective *TD = &D;
9188 // Get nested teams distribute kind directive, if any.
9189 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind))
9190 TD = getNestedDistributeDirective(CGM.getContext(), D);
9191 if (!TD)
9192 return;
9193 const auto *LD = cast<OMPLoopDirective>(TD);
Alexey Bataevec7946e2019-09-23 14:06:51 +00009194 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF,
Alexey Bataev7bb33532019-01-07 21:30:43 +00009195 PrePostActionTy &) {
Alexey Bataevec7946e2019-09-23 14:06:51 +00009196 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) {
9197 llvm::Value *Args[] = {DeviceID, NumIterations};
9198 CGF.EmitRuntimeCall(
9199 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args);
9200 }
Alexey Bataev7bb33532019-01-07 21:30:43 +00009201 };
9202 emitInlinedDirective(CGF, OMPD_unknown, CodeGen);
9203}
9204
Alexey Bataevec7946e2019-09-23 14:06:51 +00009205void CGOpenMPRuntime::emitTargetCall(
9206 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9207 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
9208 const Expr *Device,
9209 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9210 const OMPLoopDirective &D)>
9211 SizeEmitter) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00009212 if (!CGF.HaveInsertPoint())
9213 return;
Samuel Antaobed3c462015-10-02 16:14:20 +00009214
Samuel Antaoee8fb302016-01-06 13:42:12 +00009215 assert(OutlinedFn && "Invalid outlined function!");
9216
Alexey Bataev8451efa2018-01-15 19:06:12 +00009217 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>();
9218 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
Alexey Bataev475a7442018-01-12 19:39:11 +00009219 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009220 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF,
9221 PrePostActionTy &) {
9222 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9223 };
9224 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen);
Samuel Antao86ace552016-04-27 22:40:57 +00009225
Alexey Bataev8451efa2018-01-15 19:06:12 +00009226 CodeGenFunction::OMPTargetDataInfo InputInfo;
9227 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobed3c462015-10-02 16:14:20 +00009228 // Fill up the pointer arrays and transfer execution to the device.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009229 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo,
Alexey Bataevec7946e2019-09-23 14:06:51 +00009230 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars,
9231 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobed3c462015-10-02 16:14:20 +00009232 // On top of the arrays that were filled up, the target offloading call
9233 // takes as arguments the device id as well as the host pointer. The host
9234 // pointer is used by the runtime library to identify the current target
9235 // region, so it only has to be unique and not necessarily point to
9236 // anything. It could be the pointer to the outlined function that
9237 // implements the target region, but we aren't using that so that the
9238 // compiler doesn't need to keep that, and could therefore inline the host
9239 // function if proven worthwhile during optimization.
9240
Samuel Antaoee8fb302016-01-06 13:42:12 +00009241 // From this point on, we need to have an ID of the target region defined.
9242 assert(OutlinedFnID && "Invalid outlined function ID!");
Samuel Antaobed3c462015-10-02 16:14:20 +00009243
9244 // Emit device ID if any.
9245 llvm::Value *DeviceID;
George Rokos63bc9d62017-11-21 18:25:12 +00009246 if (Device) {
Samuel Antaobed3c462015-10-02 16:14:20 +00009247 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009248 CGF.Int64Ty, /*isSigned=*/true);
9249 } else {
9250 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9251 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009252
Samuel Antaodf158d52016-04-27 22:58:19 +00009253 // Emit the number of elements in the offloading arrays.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009254 llvm::Value *PointerNum =
9255 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaodf158d52016-04-27 22:58:19 +00009256
Samuel Antaob68e2db2016-03-03 16:20:23 +00009257 // Return value of the runtime offloading call.
9258 llvm::Value *Return;
9259
Alexey Bataev5c427362019-04-10 19:11:33 +00009260 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D);
9261 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009262
Alexey Bataevec7946e2019-09-23 14:06:51 +00009263 // Emit tripcount for the target loop-based directive.
9264 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter);
9265
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009266 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00009267 // The target region is an outlined function launched by the runtime
9268 // via calls __tgt_target() or __tgt_target_teams().
9269 //
9270 // __tgt_target() launches a target region with one team and one thread,
9271 // executing a serial region. This master thread may in turn launch
9272 // more threads within its team upon encountering a parallel region,
9273 // however, no additional teams can be launched on the device.
9274 //
9275 // __tgt_target_teams() launches a target region with one or more teams,
9276 // each with one or more threads. This call is required for target
9277 // constructs such as:
9278 // 'target teams'
9279 // 'target' / 'teams'
9280 // 'target teams distribute parallel for'
9281 // 'target parallel'
9282 // and so on.
9283 //
9284 // Note that on the host and CPU targets, the runtime implementation of
9285 // these calls simply call the outlined function without forking threads.
9286 // The outlined functions themselves have runtime calls to
9287 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by
9288 // the compiler in emitTeamsCall() and emitParallelCall().
9289 //
9290 // In contrast, on the NVPTX target, the implementation of
9291 // __tgt_target_teams() launches a GPU kernel with the requested number
9292 // of teams and threads so no additional calls to the runtime are required.
Samuel Antaob68e2db2016-03-03 16:20:23 +00009293 if (NumTeams) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00009294 // If we have NumTeams defined this means that we have an enclosed teams
9295 // region. Therefore we also expect to have NumThreads defined. These two
9296 // values should be defined in the presence of a teams directive,
9297 // regardless of having any clauses associated. If the user is using teams
9298 // but no clauses, these two values will be the default that should be
9299 // passed to the runtime library - a 32-bit integer with the value zero.
9300 assert(NumThreads && "Thread limit expression should be available along "
9301 "with number of teams.");
Alexey Bataev8451efa2018-01-15 19:06:12 +00009302 llvm::Value *OffloadingArgs[] = {DeviceID,
9303 OutlinedFnID,
9304 PointerNum,
9305 InputInfo.BasePointersArray.getPointer(),
9306 InputInfo.PointersArray.getPointer(),
9307 InputInfo.SizesArray.getPointer(),
9308 MapTypesArray,
9309 NumTeams,
9310 NumThreads};
Samuel Antaob68e2db2016-03-03 16:20:23 +00009311 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00009312 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait
9313 : OMPRTL__tgt_target_teams),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009314 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009315 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009316 llvm::Value *OffloadingArgs[] = {DeviceID,
9317 OutlinedFnID,
9318 PointerNum,
9319 InputInfo.BasePointersArray.getPointer(),
9320 InputInfo.PointersArray.getPointer(),
9321 InputInfo.SizesArray.getPointer(),
9322 MapTypesArray};
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009323 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00009324 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait
9325 : OMPRTL__tgt_target),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009326 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009327 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009328
Alexey Bataev2a007e02017-10-02 14:20:58 +00009329 // Check the error code and execute the host version if required.
9330 llvm::BasicBlock *OffloadFailedBlock =
9331 CGF.createBasicBlock("omp_offload.failed");
9332 llvm::BasicBlock *OffloadContBlock =
9333 CGF.createBasicBlock("omp_offload.cont");
9334 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return);
9335 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
9336
9337 CGF.EmitBlock(OffloadFailedBlock);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009338 if (RequiresOuterTask) {
9339 CapturedVars.clear();
9340 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9341 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009342 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev2a007e02017-10-02 14:20:58 +00009343 CGF.EmitBranch(OffloadContBlock);
9344
9345 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00009346 };
9347
Samuel Antaoee8fb302016-01-06 13:42:12 +00009348 // Notify that the host version must be executed.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009349 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars,
9350 RequiresOuterTask](CodeGenFunction &CGF,
9351 PrePostActionTy &) {
9352 if (RequiresOuterTask) {
9353 CapturedVars.clear();
9354 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9355 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009356 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009357 };
9358
9359 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray,
9360 &CapturedVars, RequiresOuterTask,
9361 &CS](CodeGenFunction &CGF, PrePostActionTy &) {
9362 // Fill up the arrays with all the captured variables.
9363 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
9364 MappableExprsHandler::MapValuesArrayTy Pointers;
9365 MappableExprsHandler::MapValuesArrayTy Sizes;
9366 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9367
Alexey Bataev8451efa2018-01-15 19:06:12 +00009368 // Get mappable expression information.
9369 MappableExprsHandler MEHandler(D, CGF);
Alexey Bataev969dbc02018-11-08 15:47:39 +00009370 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
Alexey Bataev8451efa2018-01-15 19:06:12 +00009371
9372 auto RI = CS.getCapturedRecordDecl()->field_begin();
9373 auto CV = CapturedVars.begin();
9374 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
9375 CE = CS.capture_end();
9376 CI != CE; ++CI, ++RI, ++CV) {
Alexey Bataevb3638132018-07-19 16:34:13 +00009377 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers;
9378 MappableExprsHandler::MapValuesArrayTy CurPointers;
9379 MappableExprsHandler::MapValuesArrayTy CurSizes;
9380 MappableExprsHandler::MapFlagsArrayTy CurMapTypes;
9381 MappableExprsHandler::StructRangeInfoTy PartialStruct;
Alexey Bataev8451efa2018-01-15 19:06:12 +00009382
9383 // VLA sizes are passed to the outlined region by copy and do not have map
9384 // information associated.
9385 if (CI->capturesVariableArrayType()) {
9386 CurBasePointers.push_back(*CV);
9387 CurPointers.push_back(*CV);
Alexey Bataeva90fc662019-06-25 16:00:43 +00009388 CurSizes.push_back(CGF.Builder.CreateIntCast(
9389 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev8451efa2018-01-15 19:06:12 +00009390 // Copy to the device as an argument. No need to retrieve it.
9391 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL |
Alexey Bataevf288cf92019-06-27 18:53:07 +00009392 MappableExprsHandler::OMP_MAP_TARGET_PARAM |
9393 MappableExprsHandler::OMP_MAP_IMPLICIT);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009394 } else {
9395 // If we have any information in the map clause, we use it, otherwise we
9396 // just do a default mapping.
9397 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00009398 CurSizes, CurMapTypes, PartialStruct);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009399 if (CurBasePointers.empty())
9400 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers,
9401 CurPointers, CurSizes, CurMapTypes);
Alexey Bataev60705422018-10-30 15:50:12 +00009402 // Generate correct mapping for variables captured by reference in
9403 // lambdas.
9404 if (CI->capturesVariable())
Alexey Bataev969dbc02018-11-08 15:47:39 +00009405 MEHandler.generateInfoForLambdaCaptures(
9406 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes,
9407 CurMapTypes, LambdaPointers);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009408 }
9409 // We expect to have at least an element of information for this capture.
9410 assert(!CurBasePointers.empty() &&
9411 "Non-existing map pointer for capture!");
9412 assert(CurBasePointers.size() == CurPointers.size() &&
9413 CurBasePointers.size() == CurSizes.size() &&
9414 CurBasePointers.size() == CurMapTypes.size() &&
9415 "Inconsistent map information sizes!");
9416
Alexey Bataevb3638132018-07-19 16:34:13 +00009417 // If there is an entry in PartialStruct it means we have a struct with
9418 // individual members mapped. Emit an extra combined entry.
9419 if (PartialStruct.Base.isValid())
9420 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes,
9421 CurMapTypes, PartialStruct);
9422
Alexey Bataev8451efa2018-01-15 19:06:12 +00009423 // We need to append the results of this capture to what we already have.
9424 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
9425 Pointers.append(CurPointers.begin(), CurPointers.end());
9426 Sizes.append(CurSizes.begin(), CurSizes.end());
9427 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end());
9428 }
Alexey Bataev60705422018-10-30 15:50:12 +00009429 // Adjust MEMBER_OF flags for the lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00009430 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers,
9431 Pointers, MapTypes);
Alexey Bataev92327c52018-03-26 16:40:55 +00009432 // Map other list items in the map clause which are not captured variables
9433 // but "declare target link" global variables.
Alexey Bataevb3638132018-07-19 16:34:13 +00009434 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes,
9435 MapTypes);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009436
9437 TargetDataInfo Info;
9438 // Fill up the arrays and create the arguments.
9439 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
9440 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
9441 Info.PointersArray, Info.SizesArray,
9442 Info.MapTypesArray, Info);
9443 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
9444 InputInfo.BasePointersArray =
9445 Address(Info.BasePointersArray, CGM.getPointerAlign());
9446 InputInfo.PointersArray =
9447 Address(Info.PointersArray, CGM.getPointerAlign());
9448 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign());
9449 MapTypesArray = Info.MapTypesArray;
9450 if (RequiresOuterTask)
9451 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
9452 else
9453 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
9454 };
9455
9456 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask](
9457 CodeGenFunction &CGF, PrePostActionTy &) {
9458 if (RequiresOuterTask) {
9459 CodeGenFunction::OMPTargetDataInfo InputInfo;
9460 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo);
9461 } else {
9462 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen);
9463 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009464 };
9465
9466 // If we have a target function ID it means that we need to support
9467 // offloading, otherwise, just execute on the host. We need to execute on host
9468 // regardless of the conditional in the if clause if, e.g., the user do not
9469 // specify target triples.
9470 if (OutlinedFnID) {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009471 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -05009472 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009473 } else {
9474 RegionCodeGenTy ThenRCG(TargetThenGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00009475 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00009476 }
9477 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009478 RegionCodeGenTy ElseRCG(TargetElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00009479 ElseRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00009480 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009481}
Samuel Antaoee8fb302016-01-06 13:42:12 +00009482
9483void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
9484 StringRef ParentName) {
9485 if (!S)
9486 return;
9487
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009488 // Codegen OMP target directives that offload compute to the device.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009489 bool RequiresDeviceCodegen =
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009490 isa<OMPExecutableDirective>(S) &&
9491 isOpenMPTargetExecutionDirective(
9492 cast<OMPExecutableDirective>(S)->getDirectiveKind());
Samuel Antaoee8fb302016-01-06 13:42:12 +00009493
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009494 if (RequiresDeviceCodegen) {
9495 const auto &E = *cast<OMPExecutableDirective>(S);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009496 unsigned DeviceID;
9497 unsigned FileID;
9498 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009499 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID,
Samuel Antao2de62b02016-02-13 23:35:10 +00009500 FileID, Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009501
9502 // Is this a target region that should not be emitted as an entry point? If
9503 // so just signal we are done with this target region.
Samuel Antao2de62b02016-02-13 23:35:10 +00009504 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
9505 ParentName, Line))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009506 return;
9507
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009508 switch (E.getDirectiveKind()) {
9509 case OMPD_target:
9510 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName,
9511 cast<OMPTargetDirective>(E));
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009512 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009513 case OMPD_target_parallel:
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009514 CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009515 CGM, ParentName, cast<OMPTargetParallelDirective>(E));
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009516 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009517 case OMPD_target_teams:
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009518 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009519 CGM, ParentName, cast<OMPTargetTeamsDirective>(E));
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009520 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009521 case OMPD_target_teams_distribute:
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009522 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009523 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E));
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009524 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009525 case OMPD_target_teams_distribute_simd:
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009526 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009527 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E));
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009528 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009529 case OMPD_target_parallel_for:
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009530 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009531 CGM, ParentName, cast<OMPTargetParallelForDirective>(E));
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009532 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009533 case OMPD_target_parallel_for_simd:
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009534 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009535 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E));
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009536 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009537 case OMPD_target_simd:
Alexey Bataevf8365372017-11-17 17:57:25 +00009538 CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009539 CGM, ParentName, cast<OMPTargetSimdDirective>(E));
Alexey Bataevf8365372017-11-17 17:57:25 +00009540 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009541 case OMPD_target_teams_distribute_parallel_for:
Carlo Bertolli52978c32018-01-03 21:12:44 +00009542 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
9543 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009544 cast<OMPTargetTeamsDistributeParallelForDirective>(E));
Carlo Bertolli52978c32018-01-03 21:12:44 +00009545 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009546 case OMPD_target_teams_distribute_parallel_for_simd:
Alexey Bataev647dd842018-01-15 20:59:40 +00009547 CodeGenFunction::
9548 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
9549 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009550 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E));
Alexey Bataev647dd842018-01-15 20:59:40 +00009551 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009552 case OMPD_parallel:
9553 case OMPD_for:
9554 case OMPD_parallel_for:
cchen47d60942019-12-05 13:43:48 -05009555 case OMPD_parallel_master:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009556 case OMPD_parallel_sections:
9557 case OMPD_for_simd:
9558 case OMPD_parallel_for_simd:
9559 case OMPD_cancel:
9560 case OMPD_cancellation_point:
9561 case OMPD_ordered:
9562 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00009563 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009564 case OMPD_task:
9565 case OMPD_simd:
9566 case OMPD_sections:
9567 case OMPD_section:
9568 case OMPD_single:
9569 case OMPD_master:
9570 case OMPD_critical:
9571 case OMPD_taskyield:
9572 case OMPD_barrier:
9573 case OMPD_taskwait:
9574 case OMPD_taskgroup:
9575 case OMPD_atomic:
9576 case OMPD_flush:
9577 case OMPD_teams:
9578 case OMPD_target_data:
9579 case OMPD_target_exit_data:
9580 case OMPD_target_enter_data:
9581 case OMPD_distribute:
9582 case OMPD_distribute_simd:
9583 case OMPD_distribute_parallel_for:
9584 case OMPD_distribute_parallel_for_simd:
9585 case OMPD_teams_distribute:
9586 case OMPD_teams_distribute_simd:
9587 case OMPD_teams_distribute_parallel_for:
9588 case OMPD_teams_distribute_parallel_for_simd:
9589 case OMPD_target_update:
9590 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00009591 case OMPD_declare_variant:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009592 case OMPD_declare_target:
9593 case OMPD_end_declare_target:
9594 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00009595 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009596 case OMPD_taskloop:
9597 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00009598 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00009599 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00009600 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04009601 case OMPD_parallel_master_taskloop_simd:
Kelvin Li1408f912018-09-26 04:28:39 +00009602 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009603 case OMPD_unknown:
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009604 llvm_unreachable("Unknown target directive for OpenMP device codegen.");
9605 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009606 return;
9607 }
9608
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009609 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
Alexey Bataev475a7442018-01-12 19:39:11 +00009610 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009611 return;
9612
9613 scanForTargetRegionsFunctions(
Alexey Bataev475a7442018-01-12 19:39:11 +00009614 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009615 return;
9616 }
9617
9618 // If this is a lambda function, look into its body.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009619 if (const auto *L = dyn_cast<LambdaExpr>(S))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009620 S = L->getBody();
9621
9622 // Keep looking for target regions recursively.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009623 for (const Stmt *II : S->children())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009624 scanForTargetRegionsFunctions(II, ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009625}
9626
9627bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009628 // If emitting code for the host, we do not process FD here. Instead we do
9629 // the normal code generation.
Alexey Bataev729e2422019-08-23 16:11:14 +00009630 if (!CGM.getLangOpts().OpenMPIsDevice) {
9631 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) {
9632 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9633 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9634 // Do not emit device_type(nohost) functions for the host.
9635 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
9636 return true;
9637 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009638 return false;
Alexey Bataev729e2422019-08-23 16:11:14 +00009639 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009640
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009641 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009642 StringRef Name = CGM.getMangledName(GD);
9643 // Try to detect target regions in the function.
Alexey Bataev729e2422019-08-23 16:11:14 +00009644 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009645 scanForTargetRegionsFunctions(FD->getBody(), Name);
Alexey Bataev729e2422019-08-23 16:11:14 +00009646 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9647 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9648 // Do not emit device_type(nohost) functions for the host.
9649 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
9650 return true;
9651 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009652
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009653 // Do not to emit function if it is not marked as declare target.
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009654 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009655 AlreadyEmittedTargetFunctions.count(Name) == 0;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009656}
9657
9658bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
9659 if (!CGM.getLangOpts().OpenMPIsDevice)
9660 return false;
9661
9662 // Check if there are Ctors/Dtors in this declaration and look for target
9663 // regions in it. We use the complete variant to produce the kernel name
9664 // mangling.
9665 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009666 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
9667 for (const CXXConstructorDecl *Ctor : RD->ctors()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009668 StringRef ParentName =
9669 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
9670 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
9671 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009672 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009673 StringRef ParentName =
9674 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
9675 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
9676 }
9677 }
9678
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009679 // Do not to emit variable if it is not marked as declare target.
Alexey Bataev92327c52018-03-26 16:40:55 +00009680 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009681 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
9682 cast<VarDecl>(GD.getDecl()));
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009683 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
9684 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9685 HasRequiresUnifiedSharedMemory)) {
Alexey Bataevd01b7492018-08-15 19:45:12 +00009686 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009687 return true;
9688 }
9689 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009690}
9691
Alexey Bataev1af5bd52019-03-05 17:47:18 +00009692llvm::Constant *
9693CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF,
9694 const VarDecl *VD) {
9695 assert(VD->getType().isConstant(CGM.getContext()) &&
9696 "Expected constant variable.");
9697 StringRef VarName;
9698 llvm::Constant *Addr;
9699 llvm::GlobalValue::LinkageTypes Linkage;
9700 QualType Ty = VD->getType();
9701 SmallString<128> Buffer;
9702 {
9703 unsigned DeviceID;
9704 unsigned FileID;
9705 unsigned Line;
9706 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID,
9707 FileID, Line);
9708 llvm::raw_svector_ostream OS(Buffer);
9709 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID)
9710 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
9711 VarName = OS.str();
9712 }
9713 Linkage = llvm::GlobalValue::InternalLinkage;
9714 Addr =
9715 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName,
9716 getDefaultFirstprivateAddressSpace());
9717 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage);
9718 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty);
9719 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr));
9720 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9721 VarName, Addr, VarSize,
9722 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage);
9723 return Addr;
9724}
9725
Alexey Bataev03f270c2018-03-30 18:31:07 +00009726void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
9727 llvm::Constant *Addr) {
Alexey Bataev36724b72019-10-03 16:46:49 +00009728 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
9729 !CGM.getLangOpts().OpenMPIsDevice)
Alexey Bataev4db9dc62019-09-23 15:53:51 +00009730 return;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009731 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9732 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
9733 if (!Res) {
9734 if (CGM.getLangOpts().OpenMPIsDevice) {
9735 // Register non-target variables being emitted in device code (debug info
9736 // may cause this).
9737 StringRef VarName = CGM.getMangledName(VD);
9738 EmittedNonTargetVariables.try_emplace(VarName, Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009739 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009740 return;
Alexey Bataev03f270c2018-03-30 18:31:07 +00009741 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009742 // Register declare target variables.
9743 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
9744 StringRef VarName;
9745 CharUnits VarSize;
9746 llvm::GlobalValue::LinkageTypes Linkage;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009747
9748 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9749 !HasRequiresUnifiedSharedMemory) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009750 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9751 VarName = CGM.getMangledName(VD);
9752 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) {
9753 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType());
9754 assert(!VarSize.isZero() && "Expected non-zero size of the variable");
9755 } else {
9756 VarSize = CharUnits::Zero();
9757 }
9758 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
9759 // Temp solution to prevent optimizations of the internal variables.
9760 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) {
9761 std::string RefName = getName({VarName, "ref"});
9762 if (!CGM.GetGlobalValue(RefName)) {
9763 llvm::Constant *AddrRef =
9764 getOrCreateInternalVariable(Addr->getType(), RefName);
9765 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef);
9766 GVAddrRef->setConstant(/*Val=*/true);
9767 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage);
9768 GVAddrRef->setInitializer(Addr);
9769 CGM.addCompilerUsedGlobal(GVAddrRef);
9770 }
9771 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009772 } else {
9773 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
9774 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9775 HasRequiresUnifiedSharedMemory)) &&
9776 "Declare target attribute must link or to with unified memory.");
9777 if (*Res == OMPDeclareTargetDeclAttr::MT_Link)
9778 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink;
9779 else
9780 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9781
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009782 if (CGM.getLangOpts().OpenMPIsDevice) {
9783 VarName = Addr->getName();
9784 Addr = nullptr;
9785 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009786 VarName = getAddrOfDeclareTargetVar(VD).getName();
9787 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009788 }
9789 VarSize = CGM.getPointerSize();
9790 Linkage = llvm::GlobalValue::WeakAnyLinkage;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009791 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009792
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009793 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9794 VarName, Addr, VarSize, Flags, Linkage);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009795}
9796
Samuel Antaoee8fb302016-01-06 13:42:12 +00009797bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009798 if (isa<FunctionDecl>(GD.getDecl()) ||
9799 isa<OMPDeclareReductionDecl>(GD.getDecl()))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009800 return emitTargetFunctions(GD);
9801
9802 return emitTargetGlobalVariable(GD);
9803}
9804
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009805void CGOpenMPRuntime::emitDeferredTargetDecls() const {
9806 for (const VarDecl *VD : DeferredGlobalVariables) {
9807 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009808 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009809 if (!Res)
9810 continue;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009811 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9812 !HasRequiresUnifiedSharedMemory) {
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009813 CGM.EmitGlobal(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009814 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009815 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
9816 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9817 HasRequiresUnifiedSharedMemory)) &&
9818 "Expected link clause or to clause with unified memory.");
9819 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009820 }
9821 }
9822}
9823
Alexey Bataev60705422018-10-30 15:50:12 +00009824void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas(
9825 CodeGenFunction &CGF, const OMPExecutableDirective &D) const {
9826 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) &&
9827 " Expected target-based directive.");
9828}
9829
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009830void CGOpenMPRuntime::checkArchForUnifiedAddressing(
9831 const OMPRequiresDecl *D) {
9832 for (const OMPClause *Clause : D->clauselists()) {
9833 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
9834 HasRequiresUnifiedSharedMemory = true;
9835 break;
9836 }
9837 }
9838}
9839
Alexey Bataevc5687252019-03-21 19:35:27 +00009840bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD,
9841 LangAS &AS) {
9842 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())
9843 return false;
9844 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
9845 switch(A->getAllocatorType()) {
9846 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
9847 // Not supported, fallback to the default mem space.
9848 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
9849 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
9850 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
9851 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
9852 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
9853 case OMPAllocateDeclAttr::OMPConstMemAlloc:
9854 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
9855 AS = LangAS::Default;
9856 return true;
9857 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
9858 llvm_unreachable("Expected predefined allocator for the variables with the "
9859 "static storage.");
9860 }
9861 return false;
9862}
9863
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00009864bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const {
9865 return HasRequiresUnifiedSharedMemory;
9866}
9867
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009868CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
9869 CodeGenModule &CGM)
9870 : CGM(CGM) {
9871 if (CGM.getLangOpts().OpenMPIsDevice) {
9872 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
9873 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
9874 }
9875}
9876
9877CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() {
9878 if (CGM.getLangOpts().OpenMPIsDevice)
9879 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
9880}
9881
Alexey Bataev6d944102018-05-02 15:45:28 +00009882bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009883 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal)
9884 return true;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009885
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009886 StringRef Name = CGM.getMangledName(GD);
Alexey Bataev6d944102018-05-02 15:45:28 +00009887 const auto *D = cast<FunctionDecl>(GD.getDecl());
Alexey Bataev34f8a702018-03-28 14:28:54 +00009888 // Do not to emit function if it is marked as declare target as it was already
9889 // emitted.
Alexey Bataev97b72212018-08-14 18:31:20 +00009890 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009891 if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) {
9892 if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name)))
Alexey Bataev34f8a702018-03-28 14:28:54 +00009893 return !F->isDeclaration();
9894 return false;
9895 }
9896 return true;
9897 }
9898
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009899 return !AlreadyEmittedTargetFunctions.insert(Name).second;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009900}
9901
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009902llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() {
9903 // If we don't have entries or if we are emitting code for the device, we
9904 // don't need to do anything.
9905 if (CGM.getLangOpts().OMPTargetTriples.empty() ||
9906 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice ||
9907 (OffloadEntriesInfoManager.empty() &&
9908 !HasEmittedDeclareTargetRegion &&
9909 !HasEmittedTargetRegion))
9910 return nullptr;
9911
9912 // Create and register the function that handles the requires directives.
9913 ASTContext &C = CGM.getContext();
9914
9915 llvm::Function *RequiresRegFn;
9916 {
9917 CodeGenFunction CGF(CGM);
9918 const auto &FI = CGM.getTypes().arrangeNullaryFunction();
9919 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
9920 std::string ReqName = getName({"omp_offloading", "requires_reg"});
9921 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI);
9922 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {});
9923 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE;
9924 // TODO: check for other requires clauses.
9925 // The requires directive takes effect only when a target region is
9926 // present in the compilation unit. Otherwise it is ignored and not
9927 // passed to the runtime. This avoids the runtime from throwing an error
9928 // for mismatching requires clauses across compilation units that don't
9929 // contain at least 1 target region.
9930 assert((HasEmittedTargetRegion ||
9931 HasEmittedDeclareTargetRegion ||
9932 !OffloadEntriesInfoManager.empty()) &&
9933 "Target or declare target region expected.");
9934 if (HasRequiresUnifiedSharedMemory)
9935 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY;
9936 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires),
9937 llvm::ConstantInt::get(CGM.Int64Ty, Flags));
9938 CGF.FinishFunction();
9939 }
9940 return RequiresRegFn;
9941}
9942
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009943void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
9944 const OMPExecutableDirective &D,
9945 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00009946 llvm::Function *OutlinedFn,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009947 ArrayRef<llvm::Value *> CapturedVars) {
9948 if (!CGF.HaveInsertPoint())
9949 return;
9950
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009951 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009952 CodeGenFunction::RunCleanupsScope Scope(CGF);
9953
9954 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
9955 llvm::Value *Args[] = {
9956 RTLoc,
9957 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
9958 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
9959 llvm::SmallVector<llvm::Value *, 16> RealArgs;
9960 RealArgs.append(std::begin(Args), std::end(Args));
9961 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
9962
James Y Knight9871db02019-02-05 16:42:33 +00009963 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009964 CGF.EmitRuntimeCall(RTLFn, RealArgs);
9965}
9966
9967void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
Carlo Bertollic6872252016-04-04 15:55:02 +00009968 const Expr *NumTeams,
9969 const Expr *ThreadLimit,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009970 SourceLocation Loc) {
9971 if (!CGF.HaveInsertPoint())
9972 return;
9973
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009974 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009975
Carlo Bertollic6872252016-04-04 15:55:02 +00009976 llvm::Value *NumTeamsVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009977 NumTeams
Carlo Bertollic6872252016-04-04 15:55:02 +00009978 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
9979 CGF.CGM.Int32Ty, /* isSigned = */ true)
9980 : CGF.Builder.getInt32(0);
9981
9982 llvm::Value *ThreadLimitVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009983 ThreadLimit
Carlo Bertollic6872252016-04-04 15:55:02 +00009984 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
9985 CGF.CGM.Int32Ty, /* isSigned = */ true)
9986 : CGF.Builder.getInt32(0);
9987
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009988 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
Carlo Bertollic6872252016-04-04 15:55:02 +00009989 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
9990 ThreadLimitVal};
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009991 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams),
9992 PushNumTeamsArgs);
9993}
Samuel Antaodf158d52016-04-27 22:58:19 +00009994
Samuel Antaocc10b852016-07-28 14:23:26 +00009995void CGOpenMPRuntime::emitTargetDataCalls(
9996 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
9997 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009998 if (!CGF.HaveInsertPoint())
9999 return;
10000
Samuel Antaocc10b852016-07-28 14:23:26 +000010001 // Action used to replace the default codegen action and turn privatization
10002 // off.
10003 PrePostActionTy NoPrivAction;
Samuel Antaodf158d52016-04-27 22:58:19 +000010004
10005 // Generate the code for the opening of the data environment. Capture all the
10006 // arguments of the runtime call by reference because they are used in the
10007 // closing of the region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010008 auto &&BeginThenGen = [this, &D, Device, &Info,
10009 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaodf158d52016-04-27 22:58:19 +000010010 // Fill up the arrays with all the mapped variables.
Samuel Antaocc10b852016-07-28 14:23:26 +000010011 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
Samuel Antaodf158d52016-04-27 22:58:19 +000010012 MappableExprsHandler::MapValuesArrayTy Pointers;
10013 MappableExprsHandler::MapValuesArrayTy Sizes;
10014 MappableExprsHandler::MapFlagsArrayTy MapTypes;
10015
10016 // Get map clause information.
10017 MappableExprsHandler MCHandler(D, CGF);
10018 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
Samuel Antaodf158d52016-04-27 22:58:19 +000010019
10020 // Fill up the arrays and create the arguments.
Samuel Antaocc10b852016-07-28 14:23:26 +000010021 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +000010022
10023 llvm::Value *BasePointersArrayArg = nullptr;
10024 llvm::Value *PointersArrayArg = nullptr;
10025 llvm::Value *SizesArrayArg = nullptr;
10026 llvm::Value *MapTypesArrayArg = nullptr;
10027 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +000010028 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +000010029
10030 // Emit device ID if any.
10031 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010032 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +000010033 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010034 CGF.Int64Ty, /*isSigned=*/true);
10035 } else {
10036 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10037 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010038
10039 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010040 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +000010041
10042 llvm::Value *OffloadingArgs[] = {
10043 DeviceID, PointerNum, BasePointersArrayArg,
10044 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010045 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin),
Samuel Antaodf158d52016-04-27 22:58:19 +000010046 OffloadingArgs);
Samuel Antaocc10b852016-07-28 14:23:26 +000010047
10048 // If device pointer privatization is required, emit the body of the region
10049 // here. It will have to be duplicated: with and without privatization.
10050 if (!Info.CaptureDeviceAddrMap.empty())
10051 CodeGen(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010052 };
10053
10054 // Generate code for the closing of the data region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010055 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF,
10056 PrePostActionTy &) {
Samuel Antaocc10b852016-07-28 14:23:26 +000010057 assert(Info.isValid() && "Invalid data environment closing arguments.");
Samuel Antaodf158d52016-04-27 22:58:19 +000010058
10059 llvm::Value *BasePointersArrayArg = nullptr;
10060 llvm::Value *PointersArrayArg = nullptr;
10061 llvm::Value *SizesArrayArg = nullptr;
10062 llvm::Value *MapTypesArrayArg = nullptr;
10063 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +000010064 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +000010065
10066 // Emit device ID if any.
10067 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010068 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +000010069 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010070 CGF.Int64Ty, /*isSigned=*/true);
10071 } else {
10072 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10073 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010074
10075 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010076 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +000010077
10078 llvm::Value *OffloadingArgs[] = {
10079 DeviceID, PointerNum, BasePointersArrayArg,
10080 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010081 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end),
Samuel Antaodf158d52016-04-27 22:58:19 +000010082 OffloadingArgs);
10083 };
10084
Samuel Antaocc10b852016-07-28 14:23:26 +000010085 // If we need device pointer privatization, we need to emit the body of the
10086 // region with no privatization in the 'else' branch of the conditional.
10087 // Otherwise, we don't have to do anything.
10088 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF,
10089 PrePostActionTy &) {
10090 if (!Info.CaptureDeviceAddrMap.empty()) {
10091 CodeGen.setAction(NoPrivAction);
10092 CodeGen(CGF);
10093 }
10094 };
10095
10096 // We don't have to do anything to close the region if the if clause evaluates
10097 // to false.
10098 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
Samuel Antaodf158d52016-04-27 22:58:19 +000010099
10100 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -050010101 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +000010102 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +000010103 RegionCodeGenTy RCG(BeginThenGen);
10104 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010105 }
10106
Samuel Antaocc10b852016-07-28 14:23:26 +000010107 // If we don't require privatization of device pointers, we emit the body in
10108 // between the runtime calls. This avoids duplicating the body code.
10109 if (Info.CaptureDeviceAddrMap.empty()) {
10110 CodeGen.setAction(NoPrivAction);
10111 CodeGen(CGF);
10112 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010113
10114 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -050010115 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +000010116 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +000010117 RegionCodeGenTy RCG(EndThenGen);
10118 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010119 }
10120}
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010121
Samuel Antao8d2d7302016-05-26 18:30:22 +000010122void CGOpenMPRuntime::emitTargetDataStandAloneCall(
Samuel Antao8dd66282016-04-27 23:14:30 +000010123 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10124 const Expr *Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010125 if (!CGF.HaveInsertPoint())
10126 return;
10127
Samuel Antao8dd66282016-04-27 23:14:30 +000010128 assert((isa<OMPTargetEnterDataDirective>(D) ||
Samuel Antao8d2d7302016-05-26 18:30:22 +000010129 isa<OMPTargetExitDataDirective>(D) ||
10130 isa<OMPTargetUpdateDirective>(D)) &&
10131 "Expecting either target enter, exit data, or update directives.");
Samuel Antao8dd66282016-04-27 23:14:30 +000010132
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010133 CodeGenFunction::OMPTargetDataInfo InputInfo;
10134 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010135 // Generate the code for the opening of the data environment.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010136 auto &&ThenGen = [this, &D, Device, &InputInfo,
10137 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010138 // Emit device ID if any.
10139 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010140 if (Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010141 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010142 CGF.Int64Ty, /*isSigned=*/true);
10143 } else {
10144 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10145 }
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010146
10147 // Emit the number of elements in the offloading arrays.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010148 llvm::Constant *PointerNum =
10149 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010150
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010151 llvm::Value *OffloadingArgs[] = {DeviceID,
10152 PointerNum,
10153 InputInfo.BasePointersArray.getPointer(),
10154 InputInfo.PointersArray.getPointer(),
10155 InputInfo.SizesArray.getPointer(),
10156 MapTypesArray};
Samuel Antao8d2d7302016-05-26 18:30:22 +000010157
Samuel Antao8d2d7302016-05-26 18:30:22 +000010158 // Select the right runtime function call for each expected standalone
10159 // directive.
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010160 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Samuel Antao8d2d7302016-05-26 18:30:22 +000010161 OpenMPRTLFunction RTLFn;
10162 switch (D.getDirectiveKind()) {
Samuel Antao8d2d7302016-05-26 18:30:22 +000010163 case OMPD_target_enter_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010164 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait
10165 : OMPRTL__tgt_target_data_begin;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010166 break;
10167 case OMPD_target_exit_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010168 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait
10169 : OMPRTL__tgt_target_data_end;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010170 break;
10171 case OMPD_target_update:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010172 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait
10173 : OMPRTL__tgt_target_data_update;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010174 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010175 case OMPD_parallel:
10176 case OMPD_for:
10177 case OMPD_parallel_for:
cchen47d60942019-12-05 13:43:48 -050010178 case OMPD_parallel_master:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010179 case OMPD_parallel_sections:
10180 case OMPD_for_simd:
10181 case OMPD_parallel_for_simd:
10182 case OMPD_cancel:
10183 case OMPD_cancellation_point:
10184 case OMPD_ordered:
10185 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +000010186 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010187 case OMPD_task:
10188 case OMPD_simd:
10189 case OMPD_sections:
10190 case OMPD_section:
10191 case OMPD_single:
10192 case OMPD_master:
10193 case OMPD_critical:
10194 case OMPD_taskyield:
10195 case OMPD_barrier:
10196 case OMPD_taskwait:
10197 case OMPD_taskgroup:
10198 case OMPD_atomic:
10199 case OMPD_flush:
10200 case OMPD_teams:
10201 case OMPD_target_data:
10202 case OMPD_distribute:
10203 case OMPD_distribute_simd:
10204 case OMPD_distribute_parallel_for:
10205 case OMPD_distribute_parallel_for_simd:
10206 case OMPD_teams_distribute:
10207 case OMPD_teams_distribute_simd:
10208 case OMPD_teams_distribute_parallel_for:
10209 case OMPD_teams_distribute_parallel_for_simd:
10210 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +000010211 case OMPD_declare_variant:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010212 case OMPD_declare_target:
10213 case OMPD_end_declare_target:
10214 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +000010215 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010216 case OMPD_taskloop:
10217 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +000010218 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +000010219 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +000010220 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -040010221 case OMPD_parallel_master_taskloop_simd:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010222 case OMPD_target:
10223 case OMPD_target_simd:
10224 case OMPD_target_teams_distribute:
10225 case OMPD_target_teams_distribute_simd:
10226 case OMPD_target_teams_distribute_parallel_for:
10227 case OMPD_target_teams_distribute_parallel_for_simd:
10228 case OMPD_target_teams:
10229 case OMPD_target_parallel:
10230 case OMPD_target_parallel_for:
10231 case OMPD_target_parallel_for_simd:
Kelvin Li1408f912018-09-26 04:28:39 +000010232 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010233 case OMPD_unknown:
10234 llvm_unreachable("Unexpected standalone target data directive.");
10235 break;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010236 }
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010237 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010238 };
10239
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010240 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray](
10241 CodeGenFunction &CGF, PrePostActionTy &) {
10242 // Fill up the arrays with all the mapped variables.
10243 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
10244 MappableExprsHandler::MapValuesArrayTy Pointers;
10245 MappableExprsHandler::MapValuesArrayTy Sizes;
10246 MappableExprsHandler::MapFlagsArrayTy MapTypes;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010247
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010248 // Get map clause information.
10249 MappableExprsHandler MEHandler(D, CGF);
10250 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
10251
10252 TargetDataInfo Info;
10253 // Fill up the arrays and create the arguments.
10254 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
10255 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
10256 Info.PointersArray, Info.SizesArray,
10257 Info.MapTypesArray, Info);
10258 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
10259 InputInfo.BasePointersArray =
10260 Address(Info.BasePointersArray, CGM.getPointerAlign());
10261 InputInfo.PointersArray =
10262 Address(Info.PointersArray, CGM.getPointerAlign());
10263 InputInfo.SizesArray =
10264 Address(Info.SizesArray, CGM.getPointerAlign());
10265 MapTypesArray = Info.MapTypesArray;
10266 if (D.hasClausesOfKind<OMPDependClause>())
10267 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
10268 else
Alexey Bataev768f1f22018-01-09 19:59:25 +000010269 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010270 };
10271
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010272 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -050010273 emitIfClause(CGF, IfCond, TargetThenGen,
10274 [](CodeGenFunction &CGF, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010275 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010276 RegionCodeGenTy ThenRCG(TargetThenGen);
10277 ThenRCG(CGF);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010278 }
10279}
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010280
10281namespace {
10282 /// Kind of parameter in a function with 'declare simd' directive.
10283 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector };
10284 /// Attribute set of the parameter.
10285 struct ParamAttrTy {
10286 ParamKindTy Kind = Vector;
10287 llvm::APSInt StrideOrArg;
10288 llvm::APSInt Alignment;
10289 };
10290} // namespace
10291
10292static unsigned evaluateCDTSize(const FunctionDecl *FD,
10293 ArrayRef<ParamAttrTy> ParamAttrs) {
10294 // Every vector variant of a SIMD-enabled function has a vector length (VLEN).
10295 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument
10296 // of that clause. The VLEN value must be power of 2.
10297 // In other case the notion of the function`s "characteristic data type" (CDT)
10298 // is used to compute the vector length.
10299 // CDT is defined in the following order:
10300 // a) For non-void function, the CDT is the return type.
10301 // b) If the function has any non-uniform, non-linear parameters, then the
10302 // CDT is the type of the first such parameter.
10303 // c) If the CDT determined by a) or b) above is struct, union, or class
10304 // type which is pass-by-value (except for the type that maps to the
10305 // built-in complex data type), the characteristic data type is int.
10306 // d) If none of the above three cases is applicable, the CDT is int.
10307 // The VLEN is then determined based on the CDT and the size of vector
10308 // register of that ISA for which current vector version is generated. The
10309 // VLEN is computed using the formula below:
10310 // VLEN = sizeof(vector_register) / sizeof(CDT),
10311 // where vector register size specified in section 3.2.1 Registers and the
10312 // Stack Frame of original AMD64 ABI document.
10313 QualType RetType = FD->getReturnType();
10314 if (RetType.isNull())
10315 return 0;
10316 ASTContext &C = FD->getASTContext();
10317 QualType CDT;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010318 if (!RetType.isNull() && !RetType->isVoidType()) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010319 CDT = RetType;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010320 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010321 unsigned Offset = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010322 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010323 if (ParamAttrs[Offset].Kind == Vector)
10324 CDT = C.getPointerType(C.getRecordType(MD->getParent()));
10325 ++Offset;
10326 }
10327 if (CDT.isNull()) {
10328 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10329 if (ParamAttrs[I + Offset].Kind == Vector) {
10330 CDT = FD->getParamDecl(I)->getType();
10331 break;
10332 }
10333 }
10334 }
10335 }
10336 if (CDT.isNull())
10337 CDT = C.IntTy;
10338 CDT = CDT->getCanonicalTypeUnqualified();
10339 if (CDT->isRecordType() || CDT->isUnionType())
10340 CDT = C.IntTy;
10341 return C.getTypeSize(CDT);
10342}
10343
10344static void
10345emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
Benjamin Kramer81cb4b72016-11-24 16:01:20 +000010346 const llvm::APSInt &VLENVal,
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010347 ArrayRef<ParamAttrTy> ParamAttrs,
10348 OMPDeclareSimdDeclAttr::BranchStateTy State) {
10349 struct ISADataTy {
10350 char ISA;
10351 unsigned VecRegSize;
10352 };
10353 ISADataTy ISAData[] = {
10354 {
10355 'b', 128
10356 }, // SSE
10357 {
10358 'c', 256
10359 }, // AVX
10360 {
10361 'd', 256
10362 }, // AVX2
10363 {
10364 'e', 512
10365 }, // AVX512
10366 };
10367 llvm::SmallVector<char, 2> Masked;
10368 switch (State) {
10369 case OMPDeclareSimdDeclAttr::BS_Undefined:
10370 Masked.push_back('N');
10371 Masked.push_back('M');
10372 break;
10373 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10374 Masked.push_back('N');
10375 break;
10376 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10377 Masked.push_back('M');
10378 break;
10379 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010380 for (char Mask : Masked) {
10381 for (const ISADataTy &Data : ISAData) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010382 SmallString<256> Buffer;
10383 llvm::raw_svector_ostream Out(Buffer);
10384 Out << "_ZGV" << Data.ISA << Mask;
10385 if (!VLENVal) {
Simon Pilgrim823a99c2019-05-22 13:02:19 +000010386 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs);
10387 assert(NumElts && "Non-zero simdlen/cdtsize expected");
10388 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010389 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010390 Out << VLENVal;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010391 }
10392 for (const ParamAttrTy &ParamAttr : ParamAttrs) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010393 switch (ParamAttr.Kind){
10394 case LinearWithVarStride:
10395 Out << 's' << ParamAttr.StrideOrArg;
10396 break;
10397 case Linear:
10398 Out << 'l';
10399 if (!!ParamAttr.StrideOrArg)
10400 Out << ParamAttr.StrideOrArg;
10401 break;
10402 case Uniform:
10403 Out << 'u';
10404 break;
10405 case Vector:
10406 Out << 'v';
10407 break;
10408 }
10409 if (!!ParamAttr.Alignment)
10410 Out << 'a' << ParamAttr.Alignment;
10411 }
10412 Out << '_' << Fn->getName();
10413 Fn->addFnAttr(Out.str());
10414 }
10415 }
10416}
10417
Alexey Bataeva0a22642019-04-16 13:56:21 +000010418// This are the Functions that are needed to mangle the name of the
10419// vector functions generated by the compiler, according to the rules
10420// defined in the "Vector Function ABI specifications for AArch64",
10421// available at
10422// https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi.
10423
10424/// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI.
10425///
10426/// TODO: Need to implement the behavior for reference marked with a
10427/// var or no linear modifiers (1.b in the section). For this, we
10428/// need to extend ParamKindTy to support the linear modifiers.
10429static bool getAArch64MTV(QualType QT, ParamKindTy Kind) {
10430 QT = QT.getCanonicalType();
10431
10432 if (QT->isVoidType())
10433 return false;
10434
10435 if (Kind == ParamKindTy::Uniform)
10436 return false;
10437
10438 if (Kind == ParamKindTy::Linear)
10439 return false;
10440
10441 // TODO: Handle linear references with modifiers
10442
10443 if (Kind == ParamKindTy::LinearWithVarStride)
10444 return false;
10445
10446 return true;
10447}
10448
10449/// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
10450static bool getAArch64PBV(QualType QT, ASTContext &C) {
10451 QT = QT.getCanonicalType();
10452 unsigned Size = C.getTypeSize(QT);
10453
10454 // Only scalars and complex within 16 bytes wide set PVB to true.
10455 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
10456 return false;
10457
10458 if (QT->isFloatingType())
10459 return true;
10460
10461 if (QT->isIntegerType())
10462 return true;
10463
10464 if (QT->isPointerType())
10465 return true;
10466
10467 // TODO: Add support for complex types (section 3.1.2, item 2).
10468
10469 return false;
10470}
10471
10472/// Computes the lane size (LS) of a return type or of an input parameter,
10473/// as defined by `LS(P)` in 3.2.1 of the AAVFABI.
10474/// TODO: Add support for references, section 3.2.1, item 1.
10475static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) {
10476 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) {
10477 QualType PTy = QT.getCanonicalType()->getPointeeType();
10478 if (getAArch64PBV(PTy, C))
10479 return C.getTypeSize(PTy);
10480 }
10481 if (getAArch64PBV(QT, C))
10482 return C.getTypeSize(QT);
10483
10484 return C.getTypeSize(C.getUIntPtrType());
10485}
10486
10487// Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the
10488// signature of the scalar function, as defined in 3.2.2 of the
10489// AAVFABI.
10490static std::tuple<unsigned, unsigned, bool>
10491getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) {
10492 QualType RetType = FD->getReturnType().getCanonicalType();
10493
10494 ASTContext &C = FD->getASTContext();
10495
10496 bool OutputBecomesInput = false;
10497
10498 llvm::SmallVector<unsigned, 8> Sizes;
10499 if (!RetType->isVoidType()) {
10500 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C));
10501 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {}))
10502 OutputBecomesInput = true;
10503 }
10504 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10505 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType();
10506 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C));
10507 }
10508
10509 assert(!Sizes.empty() && "Unable to determine NDS and WDS.");
10510 // The LS of a function parameter / return value can only be a power
10511 // of 2, starting from 8 bits, up to 128.
10512 assert(std::all_of(Sizes.begin(), Sizes.end(),
10513 [](unsigned Size) {
10514 return Size == 8 || Size == 16 || Size == 32 ||
10515 Size == 64 || Size == 128;
10516 }) &&
10517 "Invalid size");
10518
10519 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)),
10520 *std::max_element(std::begin(Sizes), std::end(Sizes)),
10521 OutputBecomesInput);
10522}
10523
10524/// Mangle the parameter part of the vector function name according to
10525/// their OpenMP classification. The mangling function is defined in
10526/// section 3.5 of the AAVFABI.
10527static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) {
10528 SmallString<256> Buffer;
10529 llvm::raw_svector_ostream Out(Buffer);
10530 for (const auto &ParamAttr : ParamAttrs) {
10531 switch (ParamAttr.Kind) {
10532 case LinearWithVarStride:
10533 Out << "ls" << ParamAttr.StrideOrArg;
10534 break;
10535 case Linear:
10536 Out << 'l';
10537 // Don't print the step value if it is not present or if it is
10538 // equal to 1.
10539 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1)
10540 Out << ParamAttr.StrideOrArg;
10541 break;
10542 case Uniform:
10543 Out << 'u';
10544 break;
10545 case Vector:
10546 Out << 'v';
10547 break;
10548 }
10549
10550 if (!!ParamAttr.Alignment)
10551 Out << 'a' << ParamAttr.Alignment;
10552 }
10553
10554 return Out.str();
10555}
10556
10557// Function used to add the attribute. The parameter `VLEN` is
10558// templated to allow the use of "x" when targeting scalable functions
10559// for SVE.
10560template <typename T>
10561static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix,
10562 char ISA, StringRef ParSeq,
10563 StringRef MangledName, bool OutputBecomesInput,
10564 llvm::Function *Fn) {
10565 SmallString<256> Buffer;
10566 llvm::raw_svector_ostream Out(Buffer);
10567 Out << Prefix << ISA << LMask << VLEN;
10568 if (OutputBecomesInput)
10569 Out << "v";
10570 Out << ParSeq << "_" << MangledName;
10571 Fn->addFnAttr(Out.str());
10572}
10573
10574// Helper function to generate the Advanced SIMD names depending on
10575// the value of the NDS when simdlen is not present.
10576static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask,
10577 StringRef Prefix, char ISA,
10578 StringRef ParSeq, StringRef MangledName,
10579 bool OutputBecomesInput,
10580 llvm::Function *Fn) {
10581 switch (NDS) {
10582 case 8:
10583 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10584 OutputBecomesInput, Fn);
10585 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName,
10586 OutputBecomesInput, Fn);
10587 break;
10588 case 16:
10589 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10590 OutputBecomesInput, Fn);
10591 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10592 OutputBecomesInput, Fn);
10593 break;
10594 case 32:
10595 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10596 OutputBecomesInput, Fn);
10597 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10598 OutputBecomesInput, Fn);
10599 break;
10600 case 64:
10601 case 128:
10602 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10603 OutputBecomesInput, Fn);
10604 break;
10605 default:
10606 llvm_unreachable("Scalar type is too wide.");
10607 }
10608}
10609
10610/// Emit vector function attributes for AArch64, as defined in the AAVFABI.
10611static void emitAArch64DeclareSimdFunction(
10612 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN,
10613 ArrayRef<ParamAttrTy> ParamAttrs,
10614 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
10615 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) {
10616
10617 // Get basic data for building the vector signature.
10618 const auto Data = getNDSWDS(FD, ParamAttrs);
10619 const unsigned NDS = std::get<0>(Data);
10620 const unsigned WDS = std::get<1>(Data);
10621 const bool OutputBecomesInput = std::get<2>(Data);
10622
10623 // Check the values provided via `simdlen` by the user.
10624 // 1. A `simdlen(1)` doesn't produce vector signatures,
10625 if (UserVLEN == 1) {
10626 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10627 DiagnosticsEngine::Warning,
10628 "The clause simdlen(1) has no effect when targeting aarch64.");
10629 CGM.getDiags().Report(SLoc, DiagID);
10630 return;
10631 }
10632
10633 // 2. Section 3.3.1, item 1: user input must be a power of 2 for
10634 // Advanced SIMD output.
10635 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
10636 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10637 DiagnosticsEngine::Warning, "The value specified in simdlen must be a "
10638 "power of 2 when targeting Advanced SIMD.");
10639 CGM.getDiags().Report(SLoc, DiagID);
10640 return;
10641 }
10642
10643 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural
10644 // limits.
10645 if (ISA == 's' && UserVLEN != 0) {
10646 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
10647 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10648 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit "
10649 "lanes in the architectural constraints "
10650 "for SVE (min is 128-bit, max is "
10651 "2048-bit, by steps of 128-bit)");
10652 CGM.getDiags().Report(SLoc, DiagID) << WDS;
10653 return;
10654 }
10655 }
10656
10657 // Sort out parameter sequence.
10658 const std::string ParSeq = mangleVectorParameters(ParamAttrs);
10659 StringRef Prefix = "_ZGV";
10660 // Generate simdlen from user input (if any).
10661 if (UserVLEN) {
10662 if (ISA == 's') {
10663 // SVE generates only a masked function.
10664 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10665 OutputBecomesInput, Fn);
10666 } else {
10667 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10668 // Advanced SIMD generates one or two functions, depending on
10669 // the `[not]inbranch` clause.
10670 switch (State) {
10671 case OMPDeclareSimdDeclAttr::BS_Undefined:
10672 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10673 OutputBecomesInput, Fn);
10674 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10675 OutputBecomesInput, Fn);
10676 break;
10677 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10678 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10679 OutputBecomesInput, Fn);
10680 break;
10681 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10682 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10683 OutputBecomesInput, Fn);
10684 break;
10685 }
10686 }
10687 } else {
10688 // If no user simdlen is provided, follow the AAVFABI rules for
10689 // generating the vector length.
10690 if (ISA == 's') {
10691 // SVE, section 3.4.1, item 1.
10692 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName,
10693 OutputBecomesInput, Fn);
10694 } else {
10695 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10696 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or
10697 // two vector names depending on the use of the clause
10698 // `[not]inbranch`.
10699 switch (State) {
10700 case OMPDeclareSimdDeclAttr::BS_Undefined:
10701 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10702 OutputBecomesInput, Fn);
10703 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10704 OutputBecomesInput, Fn);
10705 break;
10706 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10707 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10708 OutputBecomesInput, Fn);
10709 break;
10710 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10711 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10712 OutputBecomesInput, Fn);
10713 break;
10714 }
10715 }
10716 }
10717}
10718
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010719void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
10720 llvm::Function *Fn) {
10721 ASTContext &C = CGM.getContext();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010722 FD = FD->getMostRecentDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010723 // Map params to their positions in function decl.
10724 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
10725 if (isa<CXXMethodDecl>(FD))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010726 ParamPositions.try_emplace(FD, 0);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010727 unsigned ParamPos = ParamPositions.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010728 for (const ParmVarDecl *P : FD->parameters()) {
10729 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010730 ++ParamPos;
10731 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010732 while (FD) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010733 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010734 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
10735 // Mark uniform parameters.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010736 for (const Expr *E : Attr->uniforms()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010737 E = E->IgnoreParenImpCasts();
10738 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010739 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010740 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010741 } else {
10742 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10743 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010744 Pos = ParamPositions[PVD];
10745 }
10746 ParamAttrs[Pos].Kind = Uniform;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010747 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010748 // Get alignment info.
10749 auto NI = Attr->alignments_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010750 for (const Expr *E : Attr->aligneds()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010751 E = E->IgnoreParenImpCasts();
10752 unsigned Pos;
10753 QualType ParmTy;
10754 if (isa<CXXThisExpr>(E)) {
10755 Pos = ParamPositions[FD];
10756 ParmTy = E->getType();
10757 } else {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010758 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10759 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010760 Pos = ParamPositions[PVD];
10761 ParmTy = PVD->getType();
10762 }
10763 ParamAttrs[Pos].Alignment =
10764 (*NI)
10765 ? (*NI)->EvaluateKnownConstInt(C)
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010766 : llvm::APSInt::getUnsigned(
10767 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy))
10768 .getQuantity());
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010769 ++NI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010770 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010771 // Mark linear parameters.
10772 auto SI = Attr->steps_begin();
10773 auto MI = Attr->modifiers_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010774 for (const Expr *E : Attr->linears()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010775 E = E->IgnoreParenImpCasts();
10776 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010777 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010778 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010779 } else {
10780 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10781 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010782 Pos = ParamPositions[PVD];
10783 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010784 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010785 ParamAttr.Kind = Linear;
10786 if (*SI) {
Fangrui Song407659a2018-11-30 23:41:18 +000010787 Expr::EvalResult Result;
10788 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010789 if (const auto *DRE =
10790 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
10791 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010792 ParamAttr.Kind = LinearWithVarStride;
10793 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(
10794 ParamPositions[StridePVD->getCanonicalDecl()]);
10795 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010796 }
Fangrui Song407659a2018-11-30 23:41:18 +000010797 } else {
10798 ParamAttr.StrideOrArg = Result.Val.getInt();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010799 }
10800 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010801 ++SI;
10802 ++MI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010803 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010804 llvm::APSInt VLENVal;
Alexey Bataeva0a22642019-04-16 13:56:21 +000010805 SourceLocation ExprLoc;
10806 const Expr *VLENExpr = Attr->getSimdlen();
10807 if (VLENExpr) {
10808 VLENVal = VLENExpr->EvaluateKnownConstInt(C);
10809 ExprLoc = VLENExpr->getExprLoc();
10810 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010811 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
10812 if (CGM.getTriple().getArch() == llvm::Triple::x86 ||
Alexey Bataeva0a22642019-04-16 13:56:21 +000010813 CGM.getTriple().getArch() == llvm::Triple::x86_64) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010814 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
Alexey Bataeva0a22642019-04-16 13:56:21 +000010815 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) {
10816 unsigned VLEN = VLENVal.getExtValue();
10817 StringRef MangledName = Fn->getName();
10818 if (CGM.getTarget().hasFeature("sve"))
10819 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10820 MangledName, 's', 128, Fn, ExprLoc);
10821 if (CGM.getTarget().hasFeature("neon"))
10822 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10823 MangledName, 'n', 128, Fn, ExprLoc);
10824 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010825 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010826 FD = FD->getPreviousDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010827 }
10828}
Alexey Bataev8b427062016-05-25 12:36:08 +000010829
10830namespace {
10831/// Cleanup action for doacross support.
10832class DoacrossCleanupTy final : public EHScopeStack::Cleanup {
10833public:
10834 static const int DoacrossFinArgs = 2;
10835
10836private:
James Y Knight9871db02019-02-05 16:42:33 +000010837 llvm::FunctionCallee RTLFn;
Alexey Bataev8b427062016-05-25 12:36:08 +000010838 llvm::Value *Args[DoacrossFinArgs];
10839
10840public:
James Y Knight9871db02019-02-05 16:42:33 +000010841 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
10842 ArrayRef<llvm::Value *> CallArgs)
Alexey Bataev8b427062016-05-25 12:36:08 +000010843 : RTLFn(RTLFn) {
10844 assert(CallArgs.size() == DoacrossFinArgs);
10845 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10846 }
10847 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10848 if (!CGF.HaveInsertPoint())
10849 return;
10850 CGF.EmitRuntimeCall(RTLFn, Args);
10851 }
10852};
10853} // namespace
10854
10855void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000010856 const OMPLoopDirective &D,
10857 ArrayRef<Expr *> NumIterations) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010858 if (!CGF.HaveInsertPoint())
10859 return;
10860
10861 ASTContext &C = CGM.getContext();
10862 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
10863 RecordDecl *RD;
10864 if (KmpDimTy.isNull()) {
10865 // Build struct kmp_dim { // loop bounds info casted to kmp_int64
10866 // kmp_int64 lo; // lower
10867 // kmp_int64 up; // upper
10868 // kmp_int64 st; // stride
10869 // };
10870 RD = C.buildImplicitRecord("kmp_dim");
10871 RD->startDefinition();
10872 addFieldToRecordDecl(C, RD, Int64Ty);
10873 addFieldToRecordDecl(C, RD, Int64Ty);
10874 addFieldToRecordDecl(C, RD, Int64Ty);
10875 RD->completeDefinition();
10876 KmpDimTy = C.getRecordType(RD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010877 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010878 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010879 }
Alexey Bataevf138fda2018-08-13 19:04:24 +000010880 llvm::APInt Size(/*numBits=*/32, NumIterations.size());
10881 QualType ArrayTy =
Richard Smith772e2662019-10-04 01:25:59 +000010882 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0);
Alexey Bataev8b427062016-05-25 12:36:08 +000010883
Alexey Bataevf138fda2018-08-13 19:04:24 +000010884 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
10885 CGF.EmitNullInitialization(DimsAddr, ArrayTy);
Alexey Bataev8b427062016-05-25 12:36:08 +000010886 enum { LowerFD = 0, UpperFD, StrideFD };
10887 // Fill dims with data.
Alexey Bataevf138fda2018-08-13 19:04:24 +000010888 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +000010889 LValue DimsLVal = CGF.MakeAddrLValue(
10890 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010891 // dims.upper = num_iterations;
10892 LValue UpperLVal = CGF.EmitLValueForField(
10893 DimsLVal, *std::next(RD->field_begin(), UpperFD));
10894 llvm::Value *NumIterVal =
10895 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]),
10896 D.getNumIterations()->getType(), Int64Ty,
10897 D.getNumIterations()->getExprLoc());
10898 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
10899 // dims.stride = 1;
10900 LValue StrideLVal = CGF.EmitLValueForField(
10901 DimsLVal, *std::next(RD->field_begin(), StrideFD));
10902 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
10903 StrideLVal);
10904 }
Alexey Bataev8b427062016-05-25 12:36:08 +000010905
10906 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
10907 // kmp_int32 num_dims, struct kmp_dim * dims);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010908 llvm::Value *Args[] = {
10909 emitUpdateLocation(CGF, D.getBeginLoc()),
10910 getThreadID(CGF, D.getBeginLoc()),
10911 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()),
10912 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knight751fe282019-02-09 22:22:28 +000010913 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(),
Alexey Bataevf138fda2018-08-13 19:04:24 +000010914 CGM.VoidPtrTy)};
Alexey Bataev8b427062016-05-25 12:36:08 +000010915
James Y Knight9871db02019-02-05 16:42:33 +000010916 llvm::FunctionCallee RTLFn =
10917 createRuntimeFunction(OMPRTL__kmpc_doacross_init);
Alexey Bataev8b427062016-05-25 12:36:08 +000010918 CGF.EmitRuntimeCall(RTLFn, Args);
10919 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
Stephen Kelly1c301dc2018-08-09 21:09:38 +000010920 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())};
James Y Knight9871db02019-02-05 16:42:33 +000010921 llvm::FunctionCallee FiniRTLFn =
10922 createRuntimeFunction(OMPRTL__kmpc_doacross_fini);
Alexey Bataev8b427062016-05-25 12:36:08 +000010923 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
10924 llvm::makeArrayRef(FiniArgs));
10925}
10926
10927void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
10928 const OMPDependClause *C) {
10929 QualType Int64Ty =
10930 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010931 llvm::APInt Size(/*numBits=*/32, C->getNumLoops());
10932 QualType ArrayTy = CGM.getContext().getConstantArrayType(
Richard Smith772e2662019-10-04 01:25:59 +000010933 Int64Ty, Size, nullptr, ArrayType::Normal, 0);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010934 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr");
10935 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) {
10936 const Expr *CounterVal = C->getLoopData(I);
10937 assert(CounterVal);
10938 llvm::Value *CntVal = CGF.EmitScalarConversion(
10939 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
10940 CounterVal->getExprLoc());
James Y Knight751fe282019-02-09 22:22:28 +000010941 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I),
10942 /*Volatile=*/false, Int64Ty);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010943 }
10944 llvm::Value *Args[] = {
10945 emitUpdateLocation(CGF, C->getBeginLoc()),
10946 getThreadID(CGF, C->getBeginLoc()),
James Y Knight751fe282019-02-09 22:22:28 +000010947 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()};
James Y Knight9871db02019-02-05 16:42:33 +000010948 llvm::FunctionCallee RTLFn;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010949 if (C->getDependencyKind() == OMPC_DEPEND_source) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010950 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010951 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010952 assert(C->getDependencyKind() == OMPC_DEPEND_sink);
10953 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait);
10954 }
10955 CGF.EmitRuntimeCall(RTLFn, Args);
10956}
10957
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010958void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000010959 llvm::FunctionCallee Callee,
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010960 ArrayRef<llvm::Value *> Args) const {
10961 assert(Loc.isValid() && "Outlined function call location must be valid.");
Alexey Bataev3c595a62017-08-14 15:01:03 +000010962 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
10963
James Y Knight9871db02019-02-05 16:42:33 +000010964 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010965 if (Fn->doesNotThrow()) {
Alexey Bataev3c595a62017-08-14 15:01:03 +000010966 CGF.EmitNounwindRuntimeCall(Fn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010967 return;
10968 }
10969 }
Alexey Bataev3c595a62017-08-14 15:01:03 +000010970 CGF.EmitRuntimeCall(Callee, Args);
10971}
10972
10973void CGOpenMPRuntime::emitOutlinedFunctionCall(
James Y Knight9871db02019-02-05 16:42:33 +000010974 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn,
Alexey Bataev3c595a62017-08-14 15:01:03 +000010975 ArrayRef<llvm::Value *> Args) const {
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010976 emitCall(CGF, Loc, OutlinedFn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010977}
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010978
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +000010979void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) {
10980 if (const auto *FD = dyn_cast<FunctionDecl>(D))
10981 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
10982 HasEmittedDeclareTargetRegion = true;
10983}
10984
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010985Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
10986 const VarDecl *NativeParam,
10987 const VarDecl *TargetParam) const {
10988 return CGF.GetAddrOfLocalVar(NativeParam);
10989}
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010990
Alexey Bataev4f680db2019-03-19 16:41:16 +000010991namespace {
10992/// Cleanup action for allocate support.
10993class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup {
10994public:
10995 static const int CleanupArgs = 3;
10996
10997private:
10998 llvm::FunctionCallee RTLFn;
10999 llvm::Value *Args[CleanupArgs];
11000
11001public:
11002 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
11003 ArrayRef<llvm::Value *> CallArgs)
11004 : RTLFn(RTLFn) {
11005 assert(CallArgs.size() == CleanupArgs &&
11006 "Size of arguments does not match.");
11007 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
11008 }
11009 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
11010 if (!CGF.HaveInsertPoint())
11011 return;
11012 CGF.EmitRuntimeCall(RTLFn, Args);
11013 }
11014};
11015} // namespace
11016
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000011017Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF,
11018 const VarDecl *VD) {
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011019 if (!VD)
11020 return Address::invalid();
Alexey Bataev4f680db2019-03-19 16:41:16 +000011021 const VarDecl *CVD = VD->getCanonicalDecl();
11022 if (!CVD->hasAttr<OMPAllocateDeclAttr>())
11023 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011024 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
11025 // Use the default allocation.
Alexey Bataev0fd3c682019-04-02 19:44:46 +000011026 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
11027 !AA->getAllocator())
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011028 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011029 llvm::Value *Size;
11030 CharUnits Align = CGM.getContext().getDeclAlign(CVD);
11031 if (CVD->getType()->isVariablyModifiedType()) {
11032 Size = CGF.getTypeSize(CVD->getType());
Alexey Bataev9c397812019-04-03 17:57:06 +000011033 // Align the size: ((size + align - 1) / align) * align
11034 Size = CGF.Builder.CreateNUWAdd(
11035 Size, CGM.getSize(Align - CharUnits::fromQuantity(1)));
11036 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align));
11037 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align));
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011038 } else {
11039 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType());
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011040 Size = CGM.getSize(Sz.alignTo(Align));
Alexey Bataev4f680db2019-03-19 16:41:16 +000011041 }
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011042 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc());
11043 assert(AA->getAllocator() &&
11044 "Expected allocator expression for non-default allocator.");
11045 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator());
Alexey Bataev6cf7b712019-04-08 19:06:42 +000011046 // According to the standard, the original allocator type is a enum (integer).
11047 // Convert to pointer type, if required.
11048 if (Allocator->getType()->isIntegerTy())
11049 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy);
11050 else if (Allocator->getType()->isPointerTy())
11051 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator,
11052 CGM.VoidPtrTy);
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011053 llvm::Value *Args[] = {ThreadID, Size, Allocator};
11054
11055 llvm::Value *Addr =
11056 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args,
11057 CVD->getName() + ".void.addr");
11058 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr,
11059 Allocator};
11060 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free);
11061
11062 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
11063 llvm::makeArrayRef(FiniArgs));
11064 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11065 Addr,
11066 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())),
11067 CVD->getName() + ".addr");
11068 return Address(Addr, Align);
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000011069}
11070
Alexey Bataevfde11e92019-11-07 11:03:10 -050011071namespace {
11072using OMPContextSelectorData =
Alexey Bataevf8ff3d72019-11-21 16:36:49 -050011073 OpenMPCtxSelectorData<ArrayRef<StringRef>, llvm::APSInt>;
Alexey Bataevfde11e92019-11-07 11:03:10 -050011074using CompleteOMPContextSelectorData = SmallVector<OMPContextSelectorData, 4>;
11075} // anonymous namespace
11076
Alexey Bataev2df5f122019-10-01 20:18:32 +000011077/// Checks current context and returns true if it matches the context selector.
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011078template <OpenMPContextSelectorSetKind CtxSet, OpenMPContextSelectorKind Ctx,
11079 typename... Arguments>
11080static bool checkContext(const OMPContextSelectorData &Data,
11081 Arguments... Params) {
Alexey Bataevfde11e92019-11-07 11:03:10 -050011082 assert(Data.CtxSet != OMP_CTX_SET_unknown && Data.Ctx != OMP_CTX_unknown &&
Alexey Bataev2df5f122019-10-01 20:18:32 +000011083 "Unknown context selector or context selector set.");
11084 return false;
11085}
11086
11087/// Checks for implementation={vendor(<vendor>)} context selector.
11088/// \returns true iff <vendor>="llvm", false otherwise.
11089template <>
Alexey Bataevfde11e92019-11-07 11:03:10 -050011090bool checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(
11091 const OMPContextSelectorData &Data) {
11092 return llvm::all_of(Data.Names,
Alexey Bataev303657a2019-10-08 19:44:16 +000011093 [](StringRef S) { return !S.compare_lower("llvm"); });
Alexey Bataev2df5f122019-10-01 20:18:32 +000011094}
11095
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011096/// Checks for device={kind(<kind>)} context selector.
11097/// \returns true if <kind>="host" and compilation is for host.
11098/// true if <kind>="nohost" and compilation is for device.
11099/// true if <kind>="cpu" and compilation is for Arm, X86 or PPC CPU.
11100/// true if <kind>="gpu" and compilation is for NVPTX or AMDGCN.
11101/// false otherwise.
11102template <>
11103bool checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>(
11104 const OMPContextSelectorData &Data, CodeGenModule &CGM) {
11105 for (StringRef Name : Data.Names) {
11106 if (!Name.compare_lower("host")) {
11107 if (CGM.getLangOpts().OpenMPIsDevice)
11108 return false;
11109 continue;
11110 }
11111 if (!Name.compare_lower("nohost")) {
11112 if (!CGM.getLangOpts().OpenMPIsDevice)
11113 return false;
11114 continue;
11115 }
11116 switch (CGM.getTriple().getArch()) {
11117 case llvm::Triple::arm:
11118 case llvm::Triple::armeb:
11119 case llvm::Triple::aarch64:
11120 case llvm::Triple::aarch64_be:
11121 case llvm::Triple::aarch64_32:
11122 case llvm::Triple::ppc:
11123 case llvm::Triple::ppc64:
11124 case llvm::Triple::ppc64le:
11125 case llvm::Triple::x86:
11126 case llvm::Triple::x86_64:
11127 if (Name.compare_lower("cpu"))
11128 return false;
11129 break;
11130 case llvm::Triple::amdgcn:
11131 case llvm::Triple::nvptx:
11132 case llvm::Triple::nvptx64:
11133 if (Name.compare_lower("gpu"))
11134 return false;
11135 break;
11136 case llvm::Triple::UnknownArch:
11137 case llvm::Triple::arc:
11138 case llvm::Triple::avr:
11139 case llvm::Triple::bpfel:
11140 case llvm::Triple::bpfeb:
11141 case llvm::Triple::hexagon:
11142 case llvm::Triple::mips:
11143 case llvm::Triple::mipsel:
11144 case llvm::Triple::mips64:
11145 case llvm::Triple::mips64el:
11146 case llvm::Triple::msp430:
11147 case llvm::Triple::r600:
11148 case llvm::Triple::riscv32:
11149 case llvm::Triple::riscv64:
11150 case llvm::Triple::sparc:
11151 case llvm::Triple::sparcv9:
11152 case llvm::Triple::sparcel:
11153 case llvm::Triple::systemz:
11154 case llvm::Triple::tce:
11155 case llvm::Triple::tcele:
11156 case llvm::Triple::thumb:
11157 case llvm::Triple::thumbeb:
11158 case llvm::Triple::xcore:
11159 case llvm::Triple::le32:
11160 case llvm::Triple::le64:
11161 case llvm::Triple::amdil:
11162 case llvm::Triple::amdil64:
11163 case llvm::Triple::hsail:
11164 case llvm::Triple::hsail64:
11165 case llvm::Triple::spir:
11166 case llvm::Triple::spir64:
11167 case llvm::Triple::kalimba:
11168 case llvm::Triple::shave:
11169 case llvm::Triple::lanai:
11170 case llvm::Triple::wasm32:
11171 case llvm::Triple::wasm64:
11172 case llvm::Triple::renderscript32:
11173 case llvm::Triple::renderscript64:
11174 return false;
11175 }
11176 }
11177 return true;
11178}
11179
11180bool matchesContext(CodeGenModule &CGM,
11181 const CompleteOMPContextSelectorData &ContextData) {
Alexey Bataevfde11e92019-11-07 11:03:10 -050011182 for (const OMPContextSelectorData &Data : ContextData) {
Alexey Bataev5459a902019-11-22 11:42:08 -050011183 switch (Data.Ctx) {
11184 case OMP_CTX_vendor:
11185 assert(Data.CtxSet == OMP_CTX_SET_implementation &&
11186 "Expected implementation context selector set.");
11187 if (!checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(Data))
11188 return false;
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011189 break;
Alexey Bataev5459a902019-11-22 11:42:08 -050011190 case OMP_CTX_kind:
11191 assert(Data.CtxSet == OMP_CTX_SET_device &&
11192 "Expected device context selector set.");
11193 if (!checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>(Data,
11194 CGM))
11195 return false;
Alexey Bataevfde11e92019-11-07 11:03:10 -050011196 break;
Alexey Bataev5459a902019-11-22 11:42:08 -050011197 case OMP_CTX_unknown:
11198 llvm_unreachable("Unknown context selector kind.");
Alexey Bataevfde11e92019-11-07 11:03:10 -050011199 }
11200 }
11201 return true;
11202}
11203
11204static CompleteOMPContextSelectorData
11205translateAttrToContextSelectorData(ASTContext &C,
11206 const OMPDeclareVariantAttr *A) {
11207 CompleteOMPContextSelectorData Data;
11208 for (unsigned I = 0, E = A->scores_size(); I < E; ++I) {
11209 Data.emplace_back();
11210 auto CtxSet = static_cast<OpenMPContextSelectorSetKind>(
11211 *std::next(A->ctxSelectorSets_begin(), I));
11212 auto Ctx = static_cast<OpenMPContextSelectorKind>(
11213 *std::next(A->ctxSelectors_begin(), I));
11214 Data.back().CtxSet = CtxSet;
11215 Data.back().Ctx = Ctx;
11216 const Expr *Score = *std::next(A->scores_begin(), I);
11217 Data.back().Score = Score->EvaluateKnownConstInt(C);
Alexey Bataev5459a902019-11-22 11:42:08 -050011218 switch (Ctx) {
11219 case OMP_CTX_vendor:
11220 assert(CtxSet == OMP_CTX_SET_implementation &&
11221 "Expected implementation context selector set.");
11222 Data.back().Names =
11223 llvm::makeArrayRef(A->implVendors_begin(), A->implVendors_end());
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011224 break;
Alexey Bataev5459a902019-11-22 11:42:08 -050011225 case OMP_CTX_kind:
11226 assert(CtxSet == OMP_CTX_SET_device &&
11227 "Expected device context selector set.");
11228 Data.back().Names =
11229 llvm::makeArrayRef(A->deviceKinds_begin(), A->deviceKinds_end());
Alexey Bataevfde11e92019-11-07 11:03:10 -050011230 break;
Alexey Bataev5459a902019-11-22 11:42:08 -050011231 case OMP_CTX_unknown:
11232 llvm_unreachable("Unknown context selector kind.");
Alexey Bataevfde11e92019-11-07 11:03:10 -050011233 }
11234 }
11235 return Data;
11236}
11237
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011238static bool isStrictSubset(const CompleteOMPContextSelectorData &LHS,
11239 const CompleteOMPContextSelectorData &RHS) {
11240 llvm::SmallDenseMap<std::pair<int, int>, llvm::StringSet<>, 4> RHSData;
11241 for (const OMPContextSelectorData &D : RHS) {
11242 auto &Pair = RHSData.FindAndConstruct(std::make_pair(D.CtxSet, D.Ctx));
11243 Pair.getSecond().insert(D.Names.begin(), D.Names.end());
11244 }
11245 bool AllSetsAreEqual = true;
11246 for (const OMPContextSelectorData &D : LHS) {
11247 auto It = RHSData.find(std::make_pair(D.CtxSet, D.Ctx));
11248 if (It == RHSData.end())
11249 return false;
11250 if (D.Names.size() > It->getSecond().size())
11251 return false;
11252 if (llvm::set_union(It->getSecond(), D.Names))
11253 return false;
11254 AllSetsAreEqual =
11255 AllSetsAreEqual && (D.Names.size() == It->getSecond().size());
11256 }
11257
11258 return LHS.size() != RHS.size() || !AllSetsAreEqual;
11259}
11260
Alexey Bataevfde11e92019-11-07 11:03:10 -050011261static bool greaterCtxScore(const CompleteOMPContextSelectorData &LHS,
11262 const CompleteOMPContextSelectorData &RHS) {
11263 // Score is calculated as sum of all scores + 1.
11264 llvm::APSInt LHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false);
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011265 bool RHSIsSubsetOfLHS = isStrictSubset(RHS, LHS);
11266 if (RHSIsSubsetOfLHS) {
11267 LHSScore = llvm::APSInt::get(0);
11268 } else {
11269 for (const OMPContextSelectorData &Data : LHS) {
11270 if (Data.Score.getBitWidth() > LHSScore.getBitWidth()) {
11271 LHSScore = LHSScore.extend(Data.Score.getBitWidth()) + Data.Score;
11272 } else if (Data.Score.getBitWidth() < LHSScore.getBitWidth()) {
11273 LHSScore += Data.Score.extend(LHSScore.getBitWidth());
11274 } else {
11275 LHSScore += Data.Score;
11276 }
Alexey Bataevfde11e92019-11-07 11:03:10 -050011277 }
11278 }
11279 llvm::APSInt RHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false);
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011280 if (!RHSIsSubsetOfLHS && isStrictSubset(LHS, RHS)) {
11281 RHSScore = llvm::APSInt::get(0);
11282 } else {
11283 for (const OMPContextSelectorData &Data : RHS) {
11284 if (Data.Score.getBitWidth() > RHSScore.getBitWidth()) {
11285 RHSScore = RHSScore.extend(Data.Score.getBitWidth()) + Data.Score;
11286 } else if (Data.Score.getBitWidth() < RHSScore.getBitWidth()) {
11287 RHSScore += Data.Score.extend(RHSScore.getBitWidth());
11288 } else {
11289 RHSScore += Data.Score;
11290 }
Alexey Bataevfde11e92019-11-07 11:03:10 -050011291 }
11292 }
11293 return llvm::APSInt::compareValues(LHSScore, RHSScore) >= 0;
Alexey Bataev0364c762019-10-03 20:49:48 +000011294}
11295
Alexey Bataev2df5f122019-10-01 20:18:32 +000011296/// Finds the variant function that matches current context with its context
11297/// selector.
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011298static const FunctionDecl *getDeclareVariantFunction(CodeGenModule &CGM,
Alexey Bataev0364c762019-10-03 20:49:48 +000011299 const FunctionDecl *FD) {
Alexey Bataev2df5f122019-10-01 20:18:32 +000011300 if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>())
11301 return FD;
11302 // Iterate through all DeclareVariant attributes and check context selectors.
Alexey Bataev0364c762019-10-03 20:49:48 +000011303 const OMPDeclareVariantAttr *TopMostAttr = nullptr;
Alexey Bataevfde11e92019-11-07 11:03:10 -050011304 CompleteOMPContextSelectorData TopMostData;
Alexey Bataev0364c762019-10-03 20:49:48 +000011305 for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) {
Alexey Bataevfde11e92019-11-07 11:03:10 -050011306 CompleteOMPContextSelectorData Data =
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011307 translateAttrToContextSelectorData(CGM.getContext(), A);
11308 if (!matchesContext(CGM, Data))
Alexey Bataevfde11e92019-11-07 11:03:10 -050011309 continue;
Alexey Bataev0364c762019-10-03 20:49:48 +000011310 // If the attribute matches the context, find the attribute with the highest
11311 // score.
Alexey Bataevfde11e92019-11-07 11:03:10 -050011312 if (!TopMostAttr || !greaterCtxScore(TopMostData, Data)) {
11313 TopMostAttr = A;
11314 TopMostData.swap(Data);
11315 }
Alexey Bataev2df5f122019-10-01 20:18:32 +000011316 }
Alexey Bataev0364c762019-10-03 20:49:48 +000011317 if (!TopMostAttr)
Alexey Bataev2df5f122019-10-01 20:18:32 +000011318 return FD;
Alexey Bataev2df5f122019-10-01 20:18:32 +000011319 return cast<FunctionDecl>(
Alexey Bataev0364c762019-10-03 20:49:48 +000011320 cast<DeclRefExpr>(TopMostAttr->getVariantFuncRef()->IgnoreParenImpCasts())
Alexey Bataev2df5f122019-10-01 20:18:32 +000011321 ->getDecl());
11322}
11323
11324bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) {
11325 const auto *D = cast<FunctionDecl>(GD.getDecl());
11326 // If the original function is defined already, use its definition.
11327 StringRef MangledName = CGM.getMangledName(GD);
11328 llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName);
11329 if (Orig && !Orig->isDeclaration())
11330 return false;
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011331 const FunctionDecl *NewFD = getDeclareVariantFunction(CGM, D);
Alexey Bataev2df5f122019-10-01 20:18:32 +000011332 // Emit original function if it does not have declare variant attribute or the
11333 // context does not match.
11334 if (NewFD == D)
11335 return false;
11336 GlobalDecl NewGD = GD.getWithDecl(NewFD);
Alexey Bataevc2cd2d42019-10-10 17:28:10 +000011337 if (tryEmitDeclareVariant(NewGD, GD, Orig, IsForDefinition)) {
Alexey Bataev2df5f122019-10-01 20:18:32 +000011338 DeferredVariantFunction.erase(D);
11339 return true;
11340 }
11341 DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD)));
11342 return true;
11343}
11344
Alexey Bataev0860db92019-12-19 10:01:10 -050011345CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII(
11346 CodeGenModule &CGM, const OMPLoopDirective &S)
11347 : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) {
11348 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode.");
11349 if (!NeedToPush)
11350 return;
11351 NontemporalDeclsSet &DS =
11352 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
11353 for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) {
11354 for (const Stmt *Ref : C->private_refs()) {
11355 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts();
11356 const ValueDecl *VD;
11357 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
11358 VD = DRE->getDecl();
11359 } else {
11360 const auto *ME = cast<MemberExpr>(SimpleRefExpr);
11361 assert((ME->isImplicitCXXThis() ||
11362 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) &&
11363 "Expected member of current class.");
11364 VD = ME->getMemberDecl();
11365 }
11366 DS.insert(VD);
11367 }
11368 }
11369}
11370
11371CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() {
11372 if (!NeedToPush)
11373 return;
11374 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
11375}
11376
11377bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const {
11378 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode.");
11379
11380 return llvm::any_of(
11381 CGM.getOpenMPRuntime().NontemporalDeclsStack,
11382 [VD](const NontemporalDeclsSet &Set) { return Set.count(VD) > 0; });
11383}
11384
James Y Knight9871db02019-02-05 16:42:33 +000011385llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011386 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11387 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11388 llvm_unreachable("Not supported in SIMD-only mode");
11389}
11390
James Y Knight9871db02019-02-05 16:42:33 +000011391llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011392 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11393 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11394 llvm_unreachable("Not supported in SIMD-only mode");
11395}
11396
James Y Knight9871db02019-02-05 16:42:33 +000011397llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011398 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11399 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
11400 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
11401 bool Tied, unsigned &NumberOfParts) {
11402 llvm_unreachable("Not supported in SIMD-only mode");
11403}
11404
11405void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF,
11406 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000011407 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011408 ArrayRef<llvm::Value *> CapturedVars,
11409 const Expr *IfCond) {
11410 llvm_unreachable("Not supported in SIMD-only mode");
11411}
11412
11413void CGOpenMPSIMDRuntime::emitCriticalRegion(
11414 CodeGenFunction &CGF, StringRef CriticalName,
11415 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
11416 const Expr *Hint) {
11417 llvm_unreachable("Not supported in SIMD-only mode");
11418}
11419
11420void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF,
11421 const RegionCodeGenTy &MasterOpGen,
11422 SourceLocation Loc) {
11423 llvm_unreachable("Not supported in SIMD-only mode");
11424}
11425
11426void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
11427 SourceLocation Loc) {
11428 llvm_unreachable("Not supported in SIMD-only mode");
11429}
11430
11431void CGOpenMPSIMDRuntime::emitTaskgroupRegion(
11432 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen,
11433 SourceLocation Loc) {
11434 llvm_unreachable("Not supported in SIMD-only mode");
11435}
11436
11437void CGOpenMPSIMDRuntime::emitSingleRegion(
11438 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen,
11439 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars,
11440 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs,
11441 ArrayRef<const Expr *> AssignmentOps) {
11442 llvm_unreachable("Not supported in SIMD-only mode");
11443}
11444
11445void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF,
11446 const RegionCodeGenTy &OrderedOpGen,
11447 SourceLocation Loc,
11448 bool IsThreads) {
11449 llvm_unreachable("Not supported in SIMD-only mode");
11450}
11451
11452void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF,
11453 SourceLocation Loc,
11454 OpenMPDirectiveKind Kind,
11455 bool EmitChecks,
11456 bool ForceSimpleCall) {
11457 llvm_unreachable("Not supported in SIMD-only mode");
11458}
11459
11460void CGOpenMPSIMDRuntime::emitForDispatchInit(
11461 CodeGenFunction &CGF, SourceLocation Loc,
11462 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
11463 bool Ordered, const DispatchRTInput &DispatchValues) {
11464 llvm_unreachable("Not supported in SIMD-only mode");
11465}
11466
11467void CGOpenMPSIMDRuntime::emitForStaticInit(
11468 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind,
11469 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) {
11470 llvm_unreachable("Not supported in SIMD-only mode");
11471}
11472
11473void CGOpenMPSIMDRuntime::emitDistributeStaticInit(
11474 CodeGenFunction &CGF, SourceLocation Loc,
11475 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) {
11476 llvm_unreachable("Not supported in SIMD-only mode");
11477}
11478
11479void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
11480 SourceLocation Loc,
11481 unsigned IVSize,
11482 bool IVSigned) {
11483 llvm_unreachable("Not supported in SIMD-only mode");
11484}
11485
11486void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF,
11487 SourceLocation Loc,
11488 OpenMPDirectiveKind DKind) {
11489 llvm_unreachable("Not supported in SIMD-only mode");
11490}
11491
11492llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF,
11493 SourceLocation Loc,
11494 unsigned IVSize, bool IVSigned,
11495 Address IL, Address LB,
11496 Address UB, Address ST) {
11497 llvm_unreachable("Not supported in SIMD-only mode");
11498}
11499
11500void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
11501 llvm::Value *NumThreads,
11502 SourceLocation Loc) {
11503 llvm_unreachable("Not supported in SIMD-only mode");
11504}
11505
11506void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF,
11507 OpenMPProcBindClauseKind ProcBind,
11508 SourceLocation Loc) {
11509 llvm_unreachable("Not supported in SIMD-only mode");
11510}
11511
11512Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
11513 const VarDecl *VD,
11514 Address VDAddr,
11515 SourceLocation Loc) {
11516 llvm_unreachable("Not supported in SIMD-only mode");
11517}
11518
11519llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition(
11520 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit,
11521 CodeGenFunction *CGF) {
11522 llvm_unreachable("Not supported in SIMD-only mode");
11523}
11524
11525Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate(
11526 CodeGenFunction &CGF, QualType VarType, StringRef Name) {
11527 llvm_unreachable("Not supported in SIMD-only mode");
11528}
11529
11530void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF,
11531 ArrayRef<const Expr *> Vars,
11532 SourceLocation Loc) {
11533 llvm_unreachable("Not supported in SIMD-only mode");
11534}
11535
11536void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
11537 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000011538 llvm::Function *TaskFunction,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011539 QualType SharedsTy, Address Shareds,
11540 const Expr *IfCond,
11541 const OMPTaskDataTy &Data) {
11542 llvm_unreachable("Not supported in SIMD-only mode");
11543}
11544
11545void CGOpenMPSIMDRuntime::emitTaskLoopCall(
11546 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000011547 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011548 const Expr *IfCond, const OMPTaskDataTy &Data) {
11549 llvm_unreachable("Not supported in SIMD-only mode");
11550}
11551
11552void CGOpenMPSIMDRuntime::emitReduction(
11553 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates,
11554 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
11555 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) {
11556 assert(Options.SimpleReduction && "Only simple reduction is expected.");
11557 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
11558 ReductionOps, Options);
11559}
11560
11561llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit(
11562 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
11563 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
11564 llvm_unreachable("Not supported in SIMD-only mode");
11565}
11566
11567void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
11568 SourceLocation Loc,
11569 ReductionCodeGen &RCG,
11570 unsigned N) {
11571 llvm_unreachable("Not supported in SIMD-only mode");
11572}
11573
11574Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
11575 SourceLocation Loc,
11576 llvm::Value *ReductionsPtr,
11577 LValue SharedLVal) {
11578 llvm_unreachable("Not supported in SIMD-only mode");
11579}
11580
11581void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
11582 SourceLocation Loc) {
11583 llvm_unreachable("Not supported in SIMD-only mode");
11584}
11585
11586void CGOpenMPSIMDRuntime::emitCancellationPointCall(
11587 CodeGenFunction &CGF, SourceLocation Loc,
11588 OpenMPDirectiveKind CancelRegion) {
11589 llvm_unreachable("Not supported in SIMD-only mode");
11590}
11591
11592void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF,
11593 SourceLocation Loc, const Expr *IfCond,
11594 OpenMPDirectiveKind CancelRegion) {
11595 llvm_unreachable("Not supported in SIMD-only mode");
11596}
11597
11598void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction(
11599 const OMPExecutableDirective &D, StringRef ParentName,
11600 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
11601 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
11602 llvm_unreachable("Not supported in SIMD-only mode");
11603}
11604
Alexey Bataevec7946e2019-09-23 14:06:51 +000011605void CGOpenMPSIMDRuntime::emitTargetCall(
11606 CodeGenFunction &CGF, const OMPExecutableDirective &D,
11607 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
11608 const Expr *Device,
11609 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
11610 const OMPLoopDirective &D)>
11611 SizeEmitter) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011612 llvm_unreachable("Not supported in SIMD-only mode");
11613}
11614
11615bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) {
11616 llvm_unreachable("Not supported in SIMD-only mode");
11617}
11618
11619bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
11620 llvm_unreachable("Not supported in SIMD-only mode");
11621}
11622
11623bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) {
11624 return false;
11625}
11626
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011627void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF,
11628 const OMPExecutableDirective &D,
11629 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000011630 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011631 ArrayRef<llvm::Value *> CapturedVars) {
11632 llvm_unreachable("Not supported in SIMD-only mode");
11633}
11634
11635void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
11636 const Expr *NumTeams,
11637 const Expr *ThreadLimit,
11638 SourceLocation Loc) {
11639 llvm_unreachable("Not supported in SIMD-only mode");
11640}
11641
11642void CGOpenMPSIMDRuntime::emitTargetDataCalls(
11643 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
11644 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
11645 llvm_unreachable("Not supported in SIMD-only mode");
11646}
11647
11648void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
11649 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
11650 const Expr *Device) {
11651 llvm_unreachable("Not supported in SIMD-only mode");
11652}
11653
11654void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000011655 const OMPLoopDirective &D,
11656 ArrayRef<Expr *> NumIterations) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011657 llvm_unreachable("Not supported in SIMD-only mode");
11658}
11659
11660void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
11661 const OMPDependClause *C) {
11662 llvm_unreachable("Not supported in SIMD-only mode");
11663}
11664
11665const VarDecl *
11666CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD,
11667 const VarDecl *NativeParam) const {
11668 llvm_unreachable("Not supported in SIMD-only mode");
11669}
11670
11671Address
11672CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF,
11673 const VarDecl *NativeParam,
11674 const VarDecl *TargetParam) const {
11675 llvm_unreachable("Not supported in SIMD-only mode");
11676}