blob: fe672f34612889f57f265b0a9a31ca717565853d [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"
Alexey Bataeva58da1a2019-12-27 09:44:43 -050022#include "clang/AST/StmtVisitor.h"
Richard Smithbf5bcf22018-06-26 23:20:26 +000023#include "clang/Basic/BitmaskEnum.h"
Alexey Bataev2d4f80f2020-02-11 15:15:21 -050024#include "clang/Basic/OpenMPKinds.h"
Reid Kleckner98031782019-12-09 16:11:56 -080025#include "clang/CodeGen/ConstantInitBuilder.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000026#include "llvm/ADT/ArrayRef.h"
Alexey Bataev4e8231b2019-11-05 15:13:30 -050027#include "llvm/ADT/SetOperations.h"
Alexey Bataev8b321922020-01-16 15:46:34 -050028#include "llvm/ADT/StringExtras.h"
Teresa Johnsonffc4e242016-11-11 05:35:12 +000029#include "llvm/Bitcode/BitcodeReader.h"
Johannes Doerfertb3c06db2019-11-04 23:00:36 -060030#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000031#include "llvm/IR/DerivedTypes.h"
32#include "llvm/IR/GlobalValue.h"
33#include "llvm/IR/Value.h"
Alexey Bataev2d4f80f2020-02-11 15:15:21 -050034#include "llvm/Support/AtomicOrdering.h"
Samuel Antaoee8fb302016-01-06 13:42:12 +000035#include "llvm/Support/Format.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000036#include "llvm/Support/raw_ostream.h"
Alexey Bataev23b69422014-06-18 07:08:49 +000037#include <cassert>
Alexey Bataev9959db52014-05-06 10:08:46 +000038
39using namespace clang;
40using namespace CodeGen;
Johannes Doerferteb3e81f2019-11-04 22:00:49 -060041using namespace llvm::omp;
Alexey Bataev9959db52014-05-06 10:08:46 +000042
Benjamin Kramerc52193f2014-10-10 13:57:57 +000043namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000044/// Base class for handling code generation inside OpenMP regions.
Alexey Bataev18095712014-10-10 12:19:54 +000045class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
46public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000047 /// Kinds of OpenMP regions used in codegen.
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000048 enum CGOpenMPRegionKind {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000049 /// Region with outlined function for standalone 'parallel'
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000050 /// directive.
51 ParallelOutlinedRegion,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000052 /// Region with outlined function for standalone 'task' directive.
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000053 TaskOutlinedRegion,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000054 /// Region for constructs that do not require function outlining,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000055 /// like 'for', 'sections', 'atomic' etc. directives.
56 InlinedRegion,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000057 /// Region with outlined function for standalone 'target' directive.
Samuel Antaobed3c462015-10-02 16:14:20 +000058 TargetRegion,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000059 };
Alexey Bataev18095712014-10-10 12:19:54 +000060
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000061 CGOpenMPRegionInfo(const CapturedStmt &CS,
62 const CGOpenMPRegionKind RegionKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +000063 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
64 bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000065 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
Alexey Bataev25e5b442015-09-15 12:52:43 +000066 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000067
68 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +000069 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
70 bool HasCancel)
Alexey Bataev81c7ea02015-07-03 09:56:58 +000071 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
Alexey Bataev25e5b442015-09-15 12:52:43 +000072 Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000073
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000074 /// Get a variable or parameter for storing global thread id
Alexey Bataev18095712014-10-10 12:19:54 +000075 /// inside OpenMP construct.
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000076 virtual const VarDecl *getThreadIDVariable() const = 0;
Alexey Bataev18095712014-10-10 12:19:54 +000077
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000078 /// Emit the captured statement body.
Hans Wennborg7eb54642015-09-10 17:07:54 +000079 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000080
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000081 /// Get an LValue for the current ThreadID variable.
Alexey Bataev62b63b12015-03-10 07:28:44 +000082 /// \return LValue for thread id variable. This LValue always has type int32*.
83 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
Alexey Bataev18095712014-10-10 12:19:54 +000084
Alexey Bataev48591dd2016-04-20 04:01:36 +000085 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {}
86
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000087 CGOpenMPRegionKind getRegionKind() const { return RegionKind; }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000088
Alexey Bataev81c7ea02015-07-03 09:56:58 +000089 OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
90
Alexey Bataev25e5b442015-09-15 12:52:43 +000091 bool hasCancel() const { return HasCancel; }
92
Alexey Bataev18095712014-10-10 12:19:54 +000093 static bool classof(const CGCapturedStmtInfo *Info) {
94 return Info->getKind() == CR_OpenMP;
95 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000096
Alexey Bataev48591dd2016-04-20 04:01:36 +000097 ~CGOpenMPRegionInfo() override = default;
98
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000099protected:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000100 CGOpenMPRegionKind RegionKind;
Hans Wennborg45c74392016-01-12 20:54:36 +0000101 RegionCodeGenTy CodeGen;
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000102 OpenMPDirectiveKind Kind;
Alexey Bataev25e5b442015-09-15 12:52:43 +0000103 bool HasCancel;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000104};
Alexey Bataev18095712014-10-10 12:19:54 +0000105
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000106/// API for captured statement code generation in OpenMP constructs.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000107class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000108public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000109 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000110 const RegionCodeGenTy &CodeGen,
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +0000111 OpenMPDirectiveKind Kind, bool HasCancel,
112 StringRef HelperName)
Alexey Bataev25e5b442015-09-15 12:52:43 +0000113 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind,
114 HasCancel),
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +0000115 ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000116 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
117 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000118
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000119 /// Get a variable or parameter for storing global thread id
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000120 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000121 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000122
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000123 /// Get the name of the capture helper.
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +0000124 StringRef getHelperName() const override { return HelperName; }
Alexey Bataev18095712014-10-10 12:19:54 +0000125
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000126 static bool classof(const CGCapturedStmtInfo *Info) {
127 return CGOpenMPRegionInfo::classof(Info) &&
128 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
129 ParallelOutlinedRegion;
130 }
131
Alexey Bataev18095712014-10-10 12:19:54 +0000132private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000133 /// A variable or parameter storing global thread id for OpenMP
Alexey Bataev18095712014-10-10 12:19:54 +0000134 /// constructs.
135 const VarDecl *ThreadIDVar;
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +0000136 StringRef HelperName;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000137};
138
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000139/// API for captured statement code generation in OpenMP constructs.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000140class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000141public:
Alexey Bataev48591dd2016-04-20 04:01:36 +0000142 class UntiedTaskActionTy final : public PrePostActionTy {
143 bool Untied;
144 const VarDecl *PartIDVar;
145 const RegionCodeGenTy UntiedCodeGen;
146 llvm::SwitchInst *UntiedSwitch = nullptr;
147
148 public:
149 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar,
150 const RegionCodeGenTy &UntiedCodeGen)
151 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
152 void Enter(CodeGenFunction &CGF) override {
153 if (Untied) {
154 // Emit task switching point.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000155 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue(
Alexey Bataev48591dd2016-04-20 04:01:36 +0000156 CGF.GetAddrOfLocalVar(PartIDVar),
157 PartIDVar->getType()->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000158 llvm::Value *Res =
159 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation());
160 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done.");
Alexey Bataev48591dd2016-04-20 04:01:36 +0000161 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB);
162 CGF.EmitBlock(DoneBB);
163 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
164 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
165 UntiedSwitch->addCase(CGF.Builder.getInt32(0),
166 CGF.Builder.GetInsertBlock());
167 emitUntiedSwitch(CGF);
168 }
169 }
170 void emitUntiedSwitch(CodeGenFunction &CGF) const {
171 if (Untied) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000172 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue(
Alexey Bataev48591dd2016-04-20 04:01:36 +0000173 CGF.GetAddrOfLocalVar(PartIDVar),
174 PartIDVar->getType()->castAs<PointerType>());
175 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
176 PartIdLVal);
177 UntiedCodeGen(CGF);
178 CodeGenFunction::JumpDest CurPoint =
179 CGF.getJumpDestInCurrentScope(".untied.next.");
180 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
181 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
182 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
183 CGF.Builder.GetInsertBlock());
184 CGF.EmitBranchThroughCleanup(CurPoint);
185 CGF.EmitBlock(CurPoint.getBlock());
186 }
187 }
188 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); }
189 };
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000190 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
Alexey Bataev62b63b12015-03-10 07:28:44 +0000191 const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000192 const RegionCodeGenTy &CodeGen,
Alexey Bataev48591dd2016-04-20 04:01:36 +0000193 OpenMPDirectiveKind Kind, bool HasCancel,
194 const UntiedTaskActionTy &Action)
Alexey Bataev25e5b442015-09-15 12:52:43 +0000195 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel),
Alexey Bataev48591dd2016-04-20 04:01:36 +0000196 ThreadIDVar(ThreadIDVar), Action(Action) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000197 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
198 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000199
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000200 /// Get a variable or parameter for storing global thread id
Alexey Bataev62b63b12015-03-10 07:28:44 +0000201 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000202 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000203
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000204 /// Get an LValue for the current ThreadID variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000205 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000206
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000207 /// Get the name of the capture helper.
Alexey Bataev62b63b12015-03-10 07:28:44 +0000208 StringRef getHelperName() const override { return ".omp_outlined."; }
209
Alexey Bataev48591dd2016-04-20 04:01:36 +0000210 void emitUntiedSwitch(CodeGenFunction &CGF) override {
211 Action.emitUntiedSwitch(CGF);
212 }
213
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000214 static bool classof(const CGCapturedStmtInfo *Info) {
215 return CGOpenMPRegionInfo::classof(Info) &&
216 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
217 TaskOutlinedRegion;
218 }
219
Alexey Bataev62b63b12015-03-10 07:28:44 +0000220private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000221 /// A variable or parameter storing global thread id for OpenMP
Alexey Bataev62b63b12015-03-10 07:28:44 +0000222 /// constructs.
223 const VarDecl *ThreadIDVar;
Alexey Bataev48591dd2016-04-20 04:01:36 +0000224 /// Action for emitting code for untied tasks.
225 const UntiedTaskActionTy &Action;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000226};
227
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000228/// API for inlined captured statement code generation in OpenMP
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000229/// constructs.
230class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
231public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000232 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000233 const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000234 OpenMPDirectiveKind Kind, bool HasCancel)
235 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel),
236 OldCSI(OldCSI),
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000237 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000238
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000239 // Retrieve the value of the context parameter.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000240 llvm::Value *getContextValue() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000241 if (OuterRegionInfo)
242 return OuterRegionInfo->getContextValue();
243 llvm_unreachable("No context value for inlined OpenMP region");
244 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000245
Hans Wennborg7eb54642015-09-10 17:07:54 +0000246 void setContextValue(llvm::Value *V) override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000247 if (OuterRegionInfo) {
248 OuterRegionInfo->setContextValue(V);
249 return;
250 }
251 llvm_unreachable("No context value for inlined OpenMP region");
252 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000253
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000254 /// Lookup the captured field decl for a variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000255 const FieldDecl *lookup(const VarDecl *VD) const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000256 if (OuterRegionInfo)
257 return OuterRegionInfo->lookup(VD);
Alexey Bataev69c62a92015-04-15 04:52:20 +0000258 // If there is no outer outlined region,no need to lookup in a list of
259 // captured variables, we can use the original one.
260 return nullptr;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000261 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000262
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000263 FieldDecl *getThisFieldDecl() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000264 if (OuterRegionInfo)
265 return OuterRegionInfo->getThisFieldDecl();
266 return nullptr;
267 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000268
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000269 /// Get a variable or parameter for storing global thread id
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000270 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000271 const VarDecl *getThreadIDVariable() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000272 if (OuterRegionInfo)
273 return OuterRegionInfo->getThreadIDVariable();
274 return nullptr;
275 }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000276
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000277 /// Get an LValue for the current ThreadID variable.
Alexey Bataev311a9282017-10-12 13:51:32 +0000278 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override {
279 if (OuterRegionInfo)
280 return OuterRegionInfo->getThreadIDVariableLValue(CGF);
281 llvm_unreachable("No LValue for inlined OpenMP construct");
282 }
283
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000284 /// Get the name of the capture helper.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000285 StringRef getHelperName() const override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000286 if (auto *OuterRegionInfo = getOldCSI())
287 return OuterRegionInfo->getHelperName();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000288 llvm_unreachable("No helper name for inlined OpenMP construct");
289 }
290
Alexey Bataev48591dd2016-04-20 04:01:36 +0000291 void emitUntiedSwitch(CodeGenFunction &CGF) override {
292 if (OuterRegionInfo)
293 OuterRegionInfo->emitUntiedSwitch(CGF);
294 }
295
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000296 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; }
297
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000298 static bool classof(const CGCapturedStmtInfo *Info) {
299 return CGOpenMPRegionInfo::classof(Info) &&
300 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
301 }
302
Alexey Bataev48591dd2016-04-20 04:01:36 +0000303 ~CGOpenMPInlinedRegionInfo() override = default;
304
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000305private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000306 /// CodeGen info about outer OpenMP region.
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000307 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
308 CGOpenMPRegionInfo *OuterRegionInfo;
Alexey Bataev18095712014-10-10 12:19:54 +0000309};
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000310
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000311/// API for captured statement code generation in OpenMP target
Samuel Antaobed3c462015-10-02 16:14:20 +0000312/// constructs. For this captures, implicit parameters are used instead of the
Samuel Antaoee8fb302016-01-06 13:42:12 +0000313/// captured fields. The name of the target region has to be unique in a given
314/// application so it is provided by the client, because only the client has
315/// the information to generate that.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000316class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo {
Samuel Antaobed3c462015-10-02 16:14:20 +0000317public:
318 CGOpenMPTargetRegionInfo(const CapturedStmt &CS,
Samuel Antaoee8fb302016-01-06 13:42:12 +0000319 const RegionCodeGenTy &CodeGen, StringRef HelperName)
Samuel Antaobed3c462015-10-02 16:14:20 +0000320 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
Samuel Antaoee8fb302016-01-06 13:42:12 +0000321 /*HasCancel=*/false),
322 HelperName(HelperName) {}
Samuel Antaobed3c462015-10-02 16:14:20 +0000323
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000324 /// This is unused for target regions because each starts executing
Samuel Antaobed3c462015-10-02 16:14:20 +0000325 /// with a single thread.
326 const VarDecl *getThreadIDVariable() const override { return nullptr; }
327
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000328 /// Get the name of the capture helper.
Samuel Antaoee8fb302016-01-06 13:42:12 +0000329 StringRef getHelperName() const override { return HelperName; }
Samuel Antaobed3c462015-10-02 16:14:20 +0000330
331 static bool classof(const CGCapturedStmtInfo *Info) {
332 return CGOpenMPRegionInfo::classof(Info) &&
333 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion;
334 }
Samuel Antaoee8fb302016-01-06 13:42:12 +0000335
336private:
337 StringRef HelperName;
Samuel Antaobed3c462015-10-02 16:14:20 +0000338};
339
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000340static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000341 llvm_unreachable("No codegen for expressions");
342}
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000343/// API for generation of expressions captured in a innermost OpenMP
Samuel Antaob68e2db2016-03-03 16:20:23 +0000344/// region.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000345class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000346public:
347 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS)
348 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
349 OMPD_unknown,
350 /*HasCancel=*/false),
351 PrivScope(CGF) {
352 // Make sure the globals captured in the provided statement are local by
353 // using the privatization logic. We assume the same variable is not
354 // captured more than once.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000355 for (const auto &C : CS.captures()) {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000356 if (!C.capturesVariable() && !C.capturesVariableByCopy())
357 continue;
358
359 const VarDecl *VD = C.getCapturedVar();
360 if (VD->isLocalVarDeclOrParm())
361 continue;
362
Bruno Ricci5fc4db72018-12-21 14:10:18 +0000363 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
Samuel Antaob68e2db2016-03-03 16:20:23 +0000364 /*RefersToEnclosingVariableOrCapture=*/false,
365 VD->getType().getNonReferenceType(), VK_LValue,
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000366 C.getLocation());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000367 PrivScope.addPrivate(
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800368 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(CGF); });
Samuel Antaob68e2db2016-03-03 16:20:23 +0000369 }
370 (void)PrivScope.Privatize();
371 }
372
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000373 /// Lookup the captured field decl for a variable.
Samuel Antaob68e2db2016-03-03 16:20:23 +0000374 const FieldDecl *lookup(const VarDecl *VD) const override {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000375 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
Samuel Antaob68e2db2016-03-03 16:20:23 +0000376 return FD;
377 return nullptr;
378 }
379
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000380 /// Emit the captured statement body.
Samuel Antaob68e2db2016-03-03 16:20:23 +0000381 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override {
382 llvm_unreachable("No body for expressions");
383 }
384
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000385 /// Get a variable or parameter for storing global thread id
Samuel Antaob68e2db2016-03-03 16:20:23 +0000386 /// inside OpenMP construct.
387 const VarDecl *getThreadIDVariable() const override {
388 llvm_unreachable("No thread id for expressions");
389 }
390
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000391 /// Get the name of the capture helper.
Samuel Antaob68e2db2016-03-03 16:20:23 +0000392 StringRef getHelperName() const override {
393 llvm_unreachable("No helper name for expressions");
394 }
395
396 static bool classof(const CGCapturedStmtInfo *Info) { return false; }
397
398private:
399 /// Private scope to capture global variables.
400 CodeGenFunction::OMPPrivateScope PrivScope;
401};
402
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000403/// RAII for emitting code of OpenMP constructs.
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000404class InlinedOpenMPRegionRAII {
405 CodeGenFunction &CGF;
Alexey Bataev4ba78a42016-04-27 07:56:03 +0000406 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
407 FieldDecl *LambdaThisCaptureField = nullptr;
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000408 const CodeGen::CGBlockInfo *BlockInfo = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000409
410public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000411 /// Constructs region for combined constructs.
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000412 /// \param CodeGen Code generation sequence for combined directives. Includes
413 /// a list of functions used for code generation of implicitly inlined
414 /// regions.
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000415 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000416 OpenMPDirectiveKind Kind, bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000417 : CGF(CGF) {
418 // Start emission for the construct.
Alexey Bataev25e5b442015-09-15 12:52:43 +0000419 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(
420 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
Alexey Bataev4ba78a42016-04-27 07:56:03 +0000421 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
422 LambdaThisCaptureField = CGF.LambdaThisCaptureField;
423 CGF.LambdaThisCaptureField = nullptr;
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000424 BlockInfo = CGF.BlockInfo;
425 CGF.BlockInfo = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000426 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000427
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000428 ~InlinedOpenMPRegionRAII() {
429 // Restore original CapturedStmtInfo only if we're done with code emission.
430 auto *OldCSI =
431 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
432 delete CGF.CapturedStmtInfo;
433 CGF.CapturedStmtInfo = OldCSI;
Alexey Bataev4ba78a42016-04-27 07:56:03 +0000434 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
435 CGF.LambdaThisCaptureField = LambdaThisCaptureField;
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000436 CGF.BlockInfo = BlockInfo;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000437 }
438};
439
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000440/// Values for bit flags used in the ident_t to describe the fields.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000441/// All enumeric elements are named and described in accordance with the code
James Y Knight5d71fc52019-01-29 16:37:27 +0000442/// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h
Alexey Bataev0f87dbe2017-08-14 17:56:13 +0000443enum OpenMPLocationFlags : unsigned {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000444 /// Use trampoline for internal microtask.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000445 OMP_IDENT_IMD = 0x01,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000446 /// Use c-style ident structure.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000447 OMP_IDENT_KMPC = 0x02,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000448 /// Atomic reduction option for kmpc_reduce.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000449 OMP_ATOMIC_REDUCE = 0x10,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000450 /// Explicit 'barrier' directive.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000451 OMP_IDENT_BARRIER_EXPL = 0x20,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000452 /// Implicit barrier in code.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000453 OMP_IDENT_BARRIER_IMPL = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000454 /// Implicit barrier in 'for' directive.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000455 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000456 /// Implicit barrier in 'sections' directive.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000457 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000458 /// Implicit barrier in 'single' directive.
Alexey Bataev0f87dbe2017-08-14 17:56:13 +0000459 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
460 /// Call of __kmp_for_static_init for static loop.
461 OMP_IDENT_WORK_LOOP = 0x200,
462 /// Call of __kmp_for_static_init for sections.
463 OMP_IDENT_WORK_SECTIONS = 0x400,
464 /// Call of __kmp_for_static_init for distribute.
465 OMP_IDENT_WORK_DISTRIBUTE = 0x800,
466 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE)
Alexey Bataev50b3c952016-02-19 10:38:26 +0000467};
468
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +0000469namespace {
470LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
471/// Values for bit flags for marking which requires clauses have been used.
472enum OpenMPOffloadingRequiresDirFlags : int64_t {
473 /// flag undefined.
474 OMP_REQ_UNDEFINED = 0x000,
475 /// no requires clause present.
476 OMP_REQ_NONE = 0x001,
477 /// reverse_offload clause.
478 OMP_REQ_REVERSE_OFFLOAD = 0x002,
479 /// unified_address clause.
480 OMP_REQ_UNIFIED_ADDRESS = 0x004,
481 /// unified_shared_memory clause.
482 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
483 /// dynamic_allocators clause.
484 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010,
485 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS)
486};
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +0000487
488enum OpenMPOffloadingReservedDeviceIDs {
489 /// Device ID if the device was not defined, runtime should get it
490 /// from environment variables in the spec.
491 OMP_DEVICEID_UNDEF = -1,
492};
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +0000493} // anonymous namespace
494
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000495/// Describes ident structure that describes a source location.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000496/// All descriptions are taken from
James Y Knight5d71fc52019-01-29 16:37:27 +0000497/// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h
Alexey Bataev50b3c952016-02-19 10:38:26 +0000498/// Original structure:
499/// typedef struct ident {
500/// kmp_int32 reserved_1; /**< might be used in Fortran;
501/// see above */
502/// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags;
503/// KMP_IDENT_KMPC identifies this union
504/// member */
505/// kmp_int32 reserved_2; /**< not really used in Fortran any more;
506/// see above */
507///#if USE_ITT_BUILD
508/// /* but currently used for storing
509/// region-specific ITT */
510/// /* contextual information. */
511///#endif /* USE_ITT_BUILD */
512/// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for
513/// C++ */
514/// char const *psource; /**< String describing the source location.
515/// The string is composed of semi-colon separated
516// fields which describe the source file,
517/// the function and a pair of line numbers that
518/// delimit the construct.
519/// */
520/// } ident_t;
521enum IdentFieldIndex {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000522 /// might be used in Fortran
Alexey Bataev50b3c952016-02-19 10:38:26 +0000523 IdentField_Reserved_1,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000524 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000525 IdentField_Flags,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000526 /// Not really used in Fortran any more
Alexey Bataev50b3c952016-02-19 10:38:26 +0000527 IdentField_Reserved_2,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000528 /// Source[4] in Fortran, do not use for C++
Alexey Bataev50b3c952016-02-19 10:38:26 +0000529 IdentField_Reserved_3,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000530 /// String describing the source location. The string is composed of
Alexey Bataev50b3c952016-02-19 10:38:26 +0000531 /// semi-colon separated fields which describe the source file, the function
532 /// and a pair of line numbers that delimit the construct.
533 IdentField_PSource
534};
535
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000536/// Schedule types for 'omp for' loops (these enumerators are taken from
Alexey Bataev50b3c952016-02-19 10:38:26 +0000537/// the enum sched_type in kmp.h).
538enum OpenMPSchedType {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000539 /// Lower bound for default (unordered) versions.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000540 OMP_sch_lower = 32,
541 OMP_sch_static_chunked = 33,
542 OMP_sch_static = 34,
543 OMP_sch_dynamic_chunked = 35,
544 OMP_sch_guided_chunked = 36,
545 OMP_sch_runtime = 37,
546 OMP_sch_auto = 38,
Alexey Bataev6cff6242016-05-30 13:05:14 +0000547 /// static with chunk adjustment (e.g., simd)
Samuel Antao4c8035b2016-12-12 18:00:20 +0000548 OMP_sch_static_balanced_chunked = 45,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000549 /// Lower bound for 'ordered' versions.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000550 OMP_ord_lower = 64,
551 OMP_ord_static_chunked = 65,
552 OMP_ord_static = 66,
553 OMP_ord_dynamic_chunked = 67,
554 OMP_ord_guided_chunked = 68,
555 OMP_ord_runtime = 69,
556 OMP_ord_auto = 70,
557 OMP_sch_default = OMP_sch_static,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000558 /// dist_schedule types
Carlo Bertollifc35ad22016-03-07 16:04:49 +0000559 OMP_dist_sch_static_chunked = 91,
560 OMP_dist_sch_static = 92,
Alexey Bataev9ebd7422016-05-10 09:57:36 +0000561 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers.
562 /// Set if the monotonic schedule modifier was present.
563 OMP_sch_modifier_monotonic = (1 << 29),
564 /// Set if the nonmonotonic schedule modifier was present.
565 OMP_sch_modifier_nonmonotonic = (1 << 30),
Alexey Bataev50b3c952016-02-19 10:38:26 +0000566};
567
568enum OpenMPRTLFunction {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000569 /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000570 /// kmpc_micro microtask, ...);
571 OMPRTL__kmpc_fork_call,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000572 /// Call to void *__kmpc_threadprivate_cached(ident_t *loc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000573 /// kmp_int32 global_tid, void *data, size_t size, void ***cache);
574 OMPRTL__kmpc_threadprivate_cached,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000575 /// Call to void __kmpc_threadprivate_register( ident_t *,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000576 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
577 OMPRTL__kmpc_threadprivate_register,
578 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc);
579 OMPRTL__kmpc_global_thread_num,
580 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
581 // kmp_critical_name *crit);
582 OMPRTL__kmpc_critical,
583 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32
584 // global_tid, kmp_critical_name *crit, uintptr_t hint);
585 OMPRTL__kmpc_critical_with_hint,
586 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
587 // kmp_critical_name *crit);
588 OMPRTL__kmpc_end_critical,
589 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
590 // global_tid);
591 OMPRTL__kmpc_cancel_barrier,
592 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
593 OMPRTL__kmpc_barrier,
594 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
595 OMPRTL__kmpc_for_static_fini,
596 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
597 // global_tid);
598 OMPRTL__kmpc_serialized_parallel,
599 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
600 // global_tid);
601 OMPRTL__kmpc_end_serialized_parallel,
602 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
603 // kmp_int32 num_threads);
604 OMPRTL__kmpc_push_num_threads,
605 // Call to void __kmpc_flush(ident_t *loc);
606 OMPRTL__kmpc_flush,
607 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid);
608 OMPRTL__kmpc_master,
609 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid);
610 OMPRTL__kmpc_end_master,
611 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
612 // int end_part);
613 OMPRTL__kmpc_omp_taskyield,
614 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid);
615 OMPRTL__kmpc_single,
616 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid);
617 OMPRTL__kmpc_end_single,
618 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
619 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
620 // kmp_routine_entry_t *task_entry);
621 OMPRTL__kmpc_omp_task_alloc,
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +0000622 // Call to kmp_task_t * __kmpc_omp_target_task_alloc(ident_t *,
623 // kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t,
624 // size_t sizeof_shareds, kmp_routine_entry_t *task_entry,
625 // kmp_int64 device_id);
626 OMPRTL__kmpc_omp_target_task_alloc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000627 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *
628 // new_task);
629 OMPRTL__kmpc_omp_task,
630 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
631 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
632 // kmp_int32 didit);
633 OMPRTL__kmpc_copyprivate,
634 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
635 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
636 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
637 OMPRTL__kmpc_reduce,
638 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
639 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
640 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
641 // *lck);
642 OMPRTL__kmpc_reduce_nowait,
643 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
644 // kmp_critical_name *lck);
645 OMPRTL__kmpc_end_reduce,
646 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
647 // kmp_critical_name *lck);
648 OMPRTL__kmpc_end_reduce_nowait,
649 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
650 // kmp_task_t * new_task);
651 OMPRTL__kmpc_omp_task_begin_if0,
652 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
653 // kmp_task_t * new_task);
654 OMPRTL__kmpc_omp_task_complete_if0,
655 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
656 OMPRTL__kmpc_ordered,
657 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
658 OMPRTL__kmpc_end_ordered,
659 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
660 // global_tid);
661 OMPRTL__kmpc_omp_taskwait,
662 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
663 OMPRTL__kmpc_taskgroup,
664 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
665 OMPRTL__kmpc_end_taskgroup,
666 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
667 // int proc_bind);
668 OMPRTL__kmpc_push_proc_bind,
669 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32
670 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t
671 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
672 OMPRTL__kmpc_omp_task_with_deps,
673 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32
674 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
675 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
676 OMPRTL__kmpc_omp_wait_deps,
677 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
678 // global_tid, kmp_int32 cncl_kind);
679 OMPRTL__kmpc_cancellationpoint,
680 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
681 // kmp_int32 cncl_kind);
682 OMPRTL__kmpc_cancel,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000683 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid,
684 // kmp_int32 num_teams, kmp_int32 thread_limit);
685 OMPRTL__kmpc_push_num_teams,
Alexey Bataev7292c292016-04-25 12:22:29 +0000686 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
687 // microtask, ...);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000688 OMPRTL__kmpc_fork_teams,
Alexey Bataev7292c292016-04-25 12:22:29 +0000689 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
690 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
691 // sched, kmp_uint64 grainsize, void *task_dup);
692 OMPRTL__kmpc_taskloop,
Alexey Bataev8b427062016-05-25 12:36:08 +0000693 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32
694 // num_dims, struct kmp_dim *dims);
695 OMPRTL__kmpc_doacross_init,
696 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid);
697 OMPRTL__kmpc_doacross_fini,
698 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64
699 // *vec);
700 OMPRTL__kmpc_doacross_post,
701 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64
702 // *vec);
703 OMPRTL__kmpc_doacross_wait,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000704 // Call to void *__kmpc_task_reduction_init(int gtid, int num_data, void
705 // *data);
706 OMPRTL__kmpc_task_reduction_init,
707 // Call to void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
708 // *d);
709 OMPRTL__kmpc_task_reduction_get_th_data,
Alexey Bataev6cf7b712019-04-08 19:06:42 +0000710 // Call to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al);
Alexey Bataev4f680db2019-03-19 16:41:16 +0000711 OMPRTL__kmpc_alloc,
Alexey Bataev6cf7b712019-04-08 19:06:42 +0000712 // Call to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al);
Alexey Bataev4f680db2019-03-19 16:41:16 +0000713 OMPRTL__kmpc_free,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000714
715 //
716 // Offloading related calls
717 //
Alexey Bataev7bb33532019-01-07 21:30:43 +0000718 // Call to void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64
719 // size);
720 OMPRTL__kmpc_push_target_tripcount,
George Rokos63bc9d62017-11-21 18:25:12 +0000721 // Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +0000722 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev50b3c952016-02-19 10:38:26 +0000723 // *arg_types);
724 OMPRTL__tgt_target,
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000725 // Call to int32_t __tgt_target_nowait(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
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000727 // *arg_types);
728 OMPRTL__tgt_target_nowait,
George Rokos63bc9d62017-11-21 18:25:12 +0000729 // Call to int32_t __tgt_target_teams(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +0000730 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
George Rokos63bc9d62017-11-21 18:25:12 +0000731 // *arg_types, int32_t num_teams, int32_t thread_limit);
Samuel Antaob68e2db2016-03-03 16:20:23 +0000732 OMPRTL__tgt_target_teams,
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000733 // Call to int32_t __tgt_target_teams_nowait(int64_t device_id, void
Alexey Bataeva90fc662019-06-25 16:00:43 +0000734 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000735 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
736 OMPRTL__tgt_target_teams_nowait,
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +0000737 // Call to void __tgt_register_requires(int64_t flags);
738 OMPRTL__tgt_register_requires,
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 }
Benjamin Krameradcd0262020-01-28 20:23:46 +01001349 return std::string(OS.str());
Alexey Bataev18fa2322018-05-02 14:20:50 +00001350}
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
Benjamin Kramerdf186502020-01-14 14:06:12 +01001444namespace {
Johannes Doerfertf9c3c5da2019-12-25 10:33:56 -06001445// Temporary RAII solution to perform a push/pop stack event on the OpenMP IR
1446// Builder if one is present.
1447struct PushAndPopStackRAII {
1448 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder, CodeGenFunction &CGF,
1449 bool HasCancel)
1450 : OMPBuilder(OMPBuilder) {
1451 if (!OMPBuilder)
1452 return;
1453
1454 // The following callback is the crucial part of clangs cleanup process.
1455 //
1456 // NOTE:
1457 // Once the OpenMPIRBuilder is used to create parallel regions (and
1458 // similar), the cancellation destination (Dest below) is determined via
1459 // IP. That means if we have variables to finalize we split the block at IP,
1460 // use the new block (=BB) as destination to build a JumpDest (via
1461 // getJumpDestInCurrentScope(BB)) which then is fed to
1462 // EmitBranchThroughCleanup. Furthermore, there will not be the need
1463 // to push & pop an FinalizationInfo object.
1464 // The FiniCB will still be needed but at the point where the
1465 // OpenMPIRBuilder is asked to construct a parallel (or similar) construct.
1466 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) {
1467 assert(IP.getBlock()->end() == IP.getPoint() &&
1468 "Clang CG should cause non-terminated block!");
1469 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
1470 CGF.Builder.restoreIP(IP);
1471 CodeGenFunction::JumpDest Dest =
1472 CGF.getOMPCancelDestination(OMPD_parallel);
1473 CGF.EmitBranchThroughCleanup(Dest);
1474 };
1475
1476 // TODO: Remove this once we emit parallel regions through the
1477 // OpenMPIRBuilder as it can do this setup internally.
1478 llvm::OpenMPIRBuilder::FinalizationInfo FI(
1479 {FiniCB, OMPD_parallel, HasCancel});
1480 OMPBuilder->pushFinalizationCB(std::move(FI));
1481 }
1482 ~PushAndPopStackRAII() {
1483 if (OMPBuilder)
1484 OMPBuilder->popFinalizationCB();
1485 }
1486 llvm::OpenMPIRBuilder *OMPBuilder;
1487};
Benjamin Kramerdf186502020-01-14 14:06:12 +01001488} // namespace
Johannes Doerfertf9c3c5da2019-12-25 10:33:56 -06001489
James Y Knight9871db02019-02-05 16:42:33 +00001490static llvm::Function *emitParallelOrTeamsOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001491 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS,
1492 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind,
1493 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00001494 assert(ThreadIDVar->getType()->isPointerType() &&
1495 "thread id variable must be of type kmp_int32 *");
Alexey Bataev18095712014-10-10 12:19:54 +00001496 CodeGenFunction CGF(CGM, true);
Alexey Bataev25e5b442015-09-15 12:52:43 +00001497 bool HasCancel = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001498 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001499 HasCancel = OPD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001500 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001501 HasCancel = OPSD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001502 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001503 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001504 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
Alexey Bataev2139ed62017-11-16 18:20:21 +00001505 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001506 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
Alexey Bataev10a54312017-11-27 16:54:08 +00001507 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001508 else if (const auto *OPFD =
1509 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
Alexey Bataev10a54312017-11-27 16:54:08 +00001510 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001511 else if (const auto *OPFD =
Alexey Bataev10a54312017-11-27 16:54:08 +00001512 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1513 HasCancel = OPFD->hasCancel();
Johannes Doerfertf9c3c5da2019-12-25 10:33:56 -06001514
1515 // TODO: Temporarily inform the OpenMPIRBuilder, if any, about the new
1516 // parallel region to make cancellation barriers work properly.
1517 llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder();
1518 PushAndPopStackRAII PSR(OMPBuilder, CGF, HasCancel);
Alexey Bataev25e5b442015-09-15 12:52:43 +00001519 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001520 HasCancel, OutlinedHelperName);
Alexey Bataevd157d472015-06-24 03:35:38 +00001521 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataevc33ba8c2020-01-17 14:05:40 -05001522 return CGF.GenerateOpenMPCapturedStmtFunction(*CS, D.getBeginLoc());
Alexey Bataev18095712014-10-10 12:19:54 +00001523}
1524
James Y Knight9871db02019-02-05 16:42:33 +00001525llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001526 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1527 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1528 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1529 return emitParallelOrTeamsOutlinedFunction(
1530 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1531}
1532
James Y Knight9871db02019-02-05 16:42:33 +00001533llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001534 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1535 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1536 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1537 return emitParallelOrTeamsOutlinedFunction(
1538 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1539}
1540
James Y Knight9871db02019-02-05 16:42:33 +00001541llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001542 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
Alexey Bataev48591dd2016-04-20 04:01:36 +00001543 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
1544 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
1545 bool Tied, unsigned &NumberOfParts) {
1546 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF,
1547 PrePostActionTy &) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00001548 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc());
1549 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc());
Alexey Bataev48591dd2016-04-20 04:01:36 +00001550 llvm::Value *TaskArgs[] = {
1551 UpLoc, ThreadID,
1552 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1553 TaskTVar->getType()->castAs<PointerType>())
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001554 .getPointer(CGF)};
Alexey Bataev48591dd2016-04-20 04:01:36 +00001555 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs);
1556 };
1557 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1558 UntiedCodeGen);
1559 CodeGen.setAction(Action);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001560 assert(!ThreadIDVar->getType()->isPointerType() &&
1561 "thread id variable must be of type kmp_int32 for tasks");
Alexey Bataev475a7442018-01-12 19:39:11 +00001562 const OpenMPDirectiveKind Region =
1563 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop
1564 : OMPD_task;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001565 const CapturedStmt *CS = D.getCapturedStmt(Region);
Alexey Bataeve0ca4792020-02-12 16:12:53 -05001566 bool HasCancel = false;
1567 if (const auto *TD = dyn_cast<OMPTaskDirective>(&D))
1568 HasCancel = TD->hasCancel();
1569 else if (const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D))
1570 HasCancel = TD->hasCancel();
1571 else if (const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D))
1572 HasCancel = TD->hasCancel();
1573 else if (const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D))
1574 HasCancel = TD->hasCancel();
1575
Alexey Bataev62b63b12015-03-10 07:28:44 +00001576 CodeGenFunction CGF(CGM, true);
Alexey Bataev7292c292016-04-25 12:22:29 +00001577 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
Alexey Bataeve0ca4792020-02-12 16:12:53 -05001578 InnermostKind, HasCancel, Action);
Alexey Bataevd157d472015-06-24 03:35:38 +00001579 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
James Y Knight9871db02019-02-05 16:42:33 +00001580 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
Alexey Bataev48591dd2016-04-20 04:01:36 +00001581 if (!Tied)
1582 NumberOfParts = Action.getNumberOfParts();
1583 return Res;
Alexey Bataev62b63b12015-03-10 07:28:44 +00001584}
1585
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001586static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM,
1587 const RecordDecl *RD, const CGRecordLayout &RL,
1588 ArrayRef<llvm::Constant *> Data) {
1589 llvm::StructType *StructTy = RL.getLLVMType();
1590 unsigned PrevIdx = 0;
1591 ConstantInitBuilder CIBuilder(CGM);
1592 auto DI = Data.begin();
1593 for (const FieldDecl *FD : RD->fields()) {
1594 unsigned Idx = RL.getLLVMFieldNo(FD);
1595 // Fill the alignment.
1596 for (unsigned I = PrevIdx; I < Idx; ++I)
1597 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I)));
1598 PrevIdx = Idx + 1;
1599 Fields.add(*DI);
1600 ++DI;
1601 }
1602}
1603
1604template <class... As>
1605static llvm::GlobalVariable *
Mike Ricee1ca7b62018-08-29 15:45:11 +00001606createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant,
1607 ArrayRef<llvm::Constant *> Data, const Twine &Name,
1608 As &&... Args) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001609 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1610 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1611 ConstantInitBuilder CIBuilder(CGM);
1612 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType());
1613 buildStructValue(Fields, CGM, RD, RL, Data);
1614 return Fields.finishAndCreateGlobal(
Mike Ricee1ca7b62018-08-29 15:45:11 +00001615 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant,
1616 std::forward<As>(Args)...);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001617}
1618
1619template <typename T>
Benjamin Kramer651d0bf2018-05-15 21:26:47 +00001620static void
1621createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty,
1622 ArrayRef<llvm::Constant *> Data,
1623 T &Parent) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001624 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1625 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1626 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType());
1627 buildStructValue(Fields, CGM, RD, RL, Data);
1628 Fields.finishAndAddTo(Parent);
1629}
1630
Alexey Bataev50b3c952016-02-19 10:38:26 +00001631Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001632 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy);
Alexey Bataevceeaa482018-11-21 21:04:34 +00001633 unsigned Reserved2Flags = getDefaultLocationReserved2Flags();
1634 FlagsTy FlagsKey(Flags, Reserved2Flags);
1635 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey);
Alexey Bataev9959db52014-05-06 10:08:46 +00001636 if (!Entry) {
1637 if (!DefaultOpenMPPSource) {
1638 // Initialize default location for psource field of ident_t structure of
1639 // all ident_t objects. Format is ";file;function;line;column;;".
1640 // Taken from
James Y Knight5d71fc52019-01-29 16:37:27 +00001641 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp
Alexey Bataev9959db52014-05-06 10:08:46 +00001642 DefaultOpenMPPSource =
John McCall7f416cc2015-09-08 08:05:57 +00001643 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001644 DefaultOpenMPPSource =
1645 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
1646 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001647
Alexey Bataevceeaa482018-11-21 21:04:34 +00001648 llvm::Constant *Data[] = {
1649 llvm::ConstantInt::getNullValue(CGM.Int32Ty),
1650 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
1651 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags),
1652 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource};
Mike Ricee1ca7b62018-08-29 15:45:11 +00001653 llvm::GlobalValue *DefaultOpenMPLocation =
Alexey Bataevceeaa482018-11-21 21:04:34 +00001654 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "",
Mike Ricee1ca7b62018-08-29 15:45:11 +00001655 llvm::GlobalValue::PrivateLinkage);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001656 DefaultOpenMPLocation->setUnnamedAddr(
1657 llvm::GlobalValue::UnnamedAddr::Global);
John McCall6c9f1fdb2016-11-19 08:17:24 +00001658
Alexey Bataevceeaa482018-11-21 21:04:34 +00001659 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation;
Alexey Bataev9959db52014-05-06 10:08:46 +00001660 }
John McCall7f416cc2015-09-08 08:05:57 +00001661 return Address(Entry, Align);
Alexey Bataev9959db52014-05-06 10:08:46 +00001662}
1663
Alexey Bataevfd006c42018-10-05 15:08:53 +00001664void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF,
1665 bool AtCurrentPoint) {
1666 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1667 assert(!Elem.second.ServiceInsertPt && "Insert point is set already.");
1668
1669 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty);
1670 if (AtCurrentPoint) {
1671 Elem.second.ServiceInsertPt = new llvm::BitCastInst(
1672 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock());
1673 } else {
1674 Elem.second.ServiceInsertPt =
1675 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt");
1676 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt);
1677 }
1678}
1679
1680void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) {
1681 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1682 if (Elem.second.ServiceInsertPt) {
1683 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt;
1684 Elem.second.ServiceInsertPt = nullptr;
1685 Ptr->eraseFromParent();
1686 }
1687}
1688
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001689llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
1690 SourceLocation Loc,
Alexey Bataev50b3c952016-02-19 10:38:26 +00001691 unsigned Flags) {
1692 Flags |= OMP_IDENT_KMPC;
Alexey Bataev9959db52014-05-06 10:08:46 +00001693 // If no debug info is generated - return global default location.
Benjamin Kramer8c305922016-02-02 11:06:51 +00001694 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo ||
Alexey Bataev9959db52014-05-06 10:08:46 +00001695 Loc.isInvalid())
John McCall7f416cc2015-09-08 08:05:57 +00001696 return getOrCreateDefaultLocation(Flags).getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001697
1698 assert(CGF.CurFn && "No function in current CodeGenFunction.");
1699
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001700 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy);
John McCall7f416cc2015-09-08 08:05:57 +00001701 Address LocValue = Address::invalid();
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001702 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
1703 if (I != OpenMPLocThreadIDMap.end())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001704 LocValue = Address(I->second.DebugLoc, Align);
John McCall7f416cc2015-09-08 08:05:57 +00001705
Alexander Musmanc6388682014-12-15 07:07:06 +00001706 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
1707 // GetOpenMPThreadID was called before this routine.
John McCall7f416cc2015-09-08 08:05:57 +00001708 if (!LocValue.isValid()) {
Alexey Bataev15007ba2014-05-07 06:18:01 +00001709 // Generate "ident_t .kmpc_loc.addr;"
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001710 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr");
Alexey Bataev18095712014-10-10 12:19:54 +00001711 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
John McCall7f416cc2015-09-08 08:05:57 +00001712 Elem.second.DebugLoc = AI.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001713 LocValue = AI;
1714
Alexey Bataevfd006c42018-10-05 15:08:53 +00001715 if (!Elem.second.ServiceInsertPt)
1716 setLocThreadIdInsertPt(CGF);
Alexey Bataev9959db52014-05-06 10:08:46 +00001717 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001718 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001719 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001720 CGF.getTypeSize(IdentQTy));
Alexey Bataev9959db52014-05-06 10:08:46 +00001721 }
1722
1723 // char **psource = &.kmpc_loc_<flags>.addr.psource;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001724 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy);
1725 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin();
1726 LValue PSource =
1727 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource));
Alexey Bataev9959db52014-05-06 10:08:46 +00001728
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001729 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
Alexey Bataevf002aca2014-05-30 05:48:40 +00001730 if (OMPDebugLoc == nullptr) {
1731 SmallString<128> Buffer2;
1732 llvm::raw_svector_ostream OS2(Buffer2);
1733 // Build debug location
1734 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
1735 OS2 << ";" << PLoc.getFilename() << ";";
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001736 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl))
Alexey Bataevf002aca2014-05-30 05:48:40 +00001737 OS2 << FD->getQualifiedNameAsString();
Alexey Bataevf002aca2014-05-30 05:48:40 +00001738 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
1739 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
1740 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
Alexey Bataev9959db52014-05-06 10:08:46 +00001741 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001742 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001743 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource);
Alexey Bataevf002aca2014-05-30 05:48:40 +00001744
John McCall7f416cc2015-09-08 08:05:57 +00001745 // Our callers always pass this to a runtime function, so for
1746 // convenience, go ahead and return a naked pointer.
1747 return LocValue.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001748}
1749
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001750llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
1751 SourceLocation Loc) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001752 assert(CGF.CurFn && "No function in current CodeGenFunction.");
1753
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001754 llvm::Value *ThreadID = nullptr;
Alexey Bataev18095712014-10-10 12:19:54 +00001755 // Check whether we've already cached a load of the thread id in this
1756 // function.
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001757 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
Alexey Bataev18095712014-10-10 12:19:54 +00001758 if (I != OpenMPLocThreadIDMap.end()) {
1759 ThreadID = I->second.ThreadID;
Alexey Bataev03b340a2014-10-21 03:16:40 +00001760 if (ThreadID != nullptr)
1761 return ThreadID;
1762 }
Alexey Bataevaee18552017-08-16 14:01:00 +00001763 // If exceptions are enabled, do not use parameter to avoid possible crash.
Alexey Bataev780f5552019-10-17 17:12:03 +00001764 if (auto *OMPRegionInfo =
1765 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
1766 if (OMPRegionInfo->getThreadIDVariable()) {
1767 // Check if this an outlined function with thread id passed as argument.
1768 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
1769 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent();
1770 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions ||
1771 !CGF.getLangOpts().CXXExceptions ||
1772 CGF.Builder.GetInsertBlock() == TopBlock ||
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001773 !isa<llvm::Instruction>(LVal.getPointer(CGF)) ||
1774 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() ==
1775 TopBlock ||
1776 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() ==
Alexey Bataev780f5552019-10-17 17:12:03 +00001777 CGF.Builder.GetInsertBlock()) {
Alexey Bataev1e491372018-01-23 18:44:14 +00001778 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc);
Alexey Bataevaee18552017-08-16 14:01:00 +00001779 // If value loaded in entry block, cache it and use it everywhere in
1780 // function.
Alexey Bataev780f5552019-10-17 17:12:03 +00001781 if (CGF.Builder.GetInsertBlock() == TopBlock) {
Alexey Bataevaee18552017-08-16 14:01:00 +00001782 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1783 Elem.second.ThreadID = ThreadID;
1784 }
1785 return ThreadID;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001786 }
Alexey Bataevd6c57552014-07-25 07:55:17 +00001787 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001788 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001789
1790 // This is not an outlined function region - need to call __kmpc_int32
1791 // kmpc_global_thread_num(ident_t *loc).
1792 // Generate thread id value and cache this value for use across the
1793 // function.
Alexey Bataevfd006c42018-10-05 15:08:53 +00001794 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1795 if (!Elem.second.ServiceInsertPt)
1796 setLocThreadIdInsertPt(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001797 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001798 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001799 llvm::CallInst *Call = CGF.Builder.CreateCall(
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001800 createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
1801 emitUpdateLocation(CGF, Loc));
1802 Call->setCallingConv(CGF.getRuntimeCC());
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001803 Elem.second.ThreadID = Call;
1804 return Call;
Alexey Bataev9959db52014-05-06 10:08:46 +00001805}
1806
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001807void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001808 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataevfd006c42018-10-05 15:08:53 +00001809 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) {
1810 clearLocThreadIdInsertPt(CGF);
Alexey Bataev03b340a2014-10-21 03:16:40 +00001811 OpenMPLocThreadIDMap.erase(CGF.CurFn);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001812 }
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001813 if (FunctionUDRMap.count(CGF.CurFn) > 0) {
Alexey Bataev46978742020-01-30 10:46:11 -05001814 for(const auto *D : FunctionUDRMap[CGF.CurFn])
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001815 UDRMap.erase(D);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001816 FunctionUDRMap.erase(CGF.CurFn);
1817 }
Michael Krused47b9432019-08-05 18:43:21 +00001818 auto I = FunctionUDMMap.find(CGF.CurFn);
1819 if (I != FunctionUDMMap.end()) {
Alexey Bataev46978742020-01-30 10:46:11 -05001820 for(const auto *D : I->second)
Michael Krused47b9432019-08-05 18:43:21 +00001821 UDMMap.erase(D);
1822 FunctionUDMMap.erase(I);
1823 }
Alexey Bataev46978742020-01-30 10:46:11 -05001824 LastprivateConditionalToTypes.erase(CGF.CurFn);
Alexey Bataev9959db52014-05-06 10:08:46 +00001825}
1826
1827llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001828 return IdentTy->getPointerTo();
Alexey Bataev9959db52014-05-06 10:08:46 +00001829}
1830
1831llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001832 if (!Kmpc_MicroTy) {
1833 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
1834 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
1835 llvm::PointerType::getUnqual(CGM.Int32Ty)};
1836 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
1837 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001838 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
1839}
1840
James Y Knight9871db02019-02-05 16:42:33 +00001841llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
1842 llvm::FunctionCallee RTLFn = nullptr;
Alexey Bataev50b3c952016-02-19 10:38:26 +00001843 switch (static_cast<OpenMPRTLFunction>(Function)) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001844 case OMPRTL__kmpc_fork_call: {
1845 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
1846 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +00001847 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1848 getKmpc_MicroPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001849 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001850 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
Alexey Bataev9959db52014-05-06 10:08:46 +00001851 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
James Y Knight9871db02019-02-05 16:42:33 +00001852 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) {
Johannes Doerfertac991bb2019-01-19 05:36:54 +00001853 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
1854 llvm::LLVMContext &Ctx = F->getContext();
1855 llvm::MDBuilder MDB(Ctx);
1856 // Annotate the callback behavior of the __kmpc_fork_call:
1857 // - The callback callee is argument number 2 (microtask).
1858 // - The first two arguments of the callback callee are unknown (-1).
1859 // - All variadic arguments to the __kmpc_fork_call are passed to the
1860 // callback callee.
1861 F->addMetadata(
1862 llvm::LLVMContext::MD_callback,
1863 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
1864 2, {-1, -1},
1865 /* VarArgsArePassed */ true)}));
1866 }
1867 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001868 break;
1869 }
1870 case OMPRTL__kmpc_global_thread_num: {
1871 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +00001872 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001873 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001874 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
Alexey Bataev9959db52014-05-06 10:08:46 +00001875 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
1876 break;
1877 }
Alexey Bataev97720002014-11-11 04:05:39 +00001878 case OMPRTL__kmpc_threadprivate_cached: {
1879 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
1880 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
1881 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1882 CGM.VoidPtrTy, CGM.SizeTy,
1883 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001884 auto *FnTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001885 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
1886 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
1887 break;
1888 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001889 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001890 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
1891 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001892 llvm::Type *TypeParams[] = {
1893 getIdentTyPointerTy(), CGM.Int32Ty,
1894 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001895 auto *FnTy =
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001896 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1897 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
1898 break;
1899 }
Alexey Bataevfc57d162015-12-15 10:55:09 +00001900 case OMPRTL__kmpc_critical_with_hint: {
1901 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid,
1902 // kmp_critical_name *crit, uintptr_t hint);
1903 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1904 llvm::PointerType::getUnqual(KmpCriticalNameTy),
1905 CGM.IntPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001906 auto *FnTy =
Alexey Bataevfc57d162015-12-15 10:55:09 +00001907 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1908 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint");
1909 break;
1910 }
Alexey Bataev97720002014-11-11 04:05:39 +00001911 case OMPRTL__kmpc_threadprivate_register: {
1912 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
1913 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
1914 // typedef void *(*kmpc_ctor)(void *);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001915 auto *KmpcCtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001916 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1917 /*isVarArg*/ false)->getPointerTo();
1918 // typedef void *(*kmpc_cctor)(void *, void *);
1919 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001920 auto *KmpcCopyCtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001921 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001922 /*isVarArg*/ false)
1923 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00001924 // typedef void (*kmpc_dtor)(void *);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001925 auto *KmpcDtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001926 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
1927 ->getPointerTo();
1928 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
1929 KmpcCopyCtorTy, KmpcDtorTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001930 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
Alexey Bataev97720002014-11-11 04:05:39 +00001931 /*isVarArg*/ false);
1932 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
1933 break;
1934 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001935 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001936 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
1937 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001938 llvm::Type *TypeParams[] = {
1939 getIdentTyPointerTy(), CGM.Int32Ty,
1940 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001941 auto *FnTy =
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001942 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1943 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
1944 break;
1945 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001946 case OMPRTL__kmpc_cancel_barrier: {
1947 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
1948 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001949 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001950 auto *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001951 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1952 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001953 break;
1954 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001955 case OMPRTL__kmpc_barrier: {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001956 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001957 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001958 auto *FnTy =
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001959 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1960 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
1961 break;
1962 }
Alexander Musmanc6388682014-12-15 07:07:06 +00001963 case OMPRTL__kmpc_for_static_fini: {
1964 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
1965 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001966 auto *FnTy =
Alexander Musmanc6388682014-12-15 07:07:06 +00001967 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1968 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
1969 break;
1970 }
Alexey Bataevb2059782014-10-13 08:23:51 +00001971 case OMPRTL__kmpc_push_num_threads: {
1972 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
1973 // kmp_int32 num_threads)
1974 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1975 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001976 auto *FnTy =
Alexey Bataevb2059782014-10-13 08:23:51 +00001977 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1978 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
1979 break;
1980 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001981 case OMPRTL__kmpc_serialized_parallel: {
1982 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
1983 // global_tid);
1984 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001985 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001986 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1987 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
1988 break;
1989 }
1990 case OMPRTL__kmpc_end_serialized_parallel: {
1991 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
1992 // global_tid);
1993 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001994 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001995 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1996 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
1997 break;
1998 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001999 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +00002000 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00002001 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002002 auto *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +00002003 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00002004 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
2005 break;
2006 }
Alexey Bataev8d690652014-12-04 07:23:53 +00002007 case OMPRTL__kmpc_master: {
2008 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
2009 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002010 auto *FnTy =
Alexey Bataev8d690652014-12-04 07:23:53 +00002011 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2012 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
2013 break;
2014 }
2015 case OMPRTL__kmpc_end_master: {
2016 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
2017 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002018 auto *FnTy =
Alexey Bataev8d690652014-12-04 07:23:53 +00002019 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2020 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
2021 break;
2022 }
Alexey Bataev9f797f32015-02-05 05:57:51 +00002023 case OMPRTL__kmpc_omp_taskyield: {
2024 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
2025 // int end_part);
2026 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002027 auto *FnTy =
Alexey Bataev9f797f32015-02-05 05:57:51 +00002028 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2029 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
2030 break;
2031 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002032 case OMPRTL__kmpc_single: {
2033 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
2034 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002035 auto *FnTy =
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002036 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2037 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
2038 break;
2039 }
2040 case OMPRTL__kmpc_end_single: {
2041 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
2042 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002043 auto *FnTy =
Alexey Bataev6956e2e2015-02-05 06:35:41 +00002044 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2045 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
2046 break;
2047 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002048 case OMPRTL__kmpc_omp_task_alloc: {
2049 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
2050 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
2051 // kmp_routine_entry_t *task_entry);
2052 assert(KmpRoutineEntryPtrTy != nullptr &&
2053 "Type kmp_routine_entry_t must be created.");
2054 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
2055 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
2056 // Return void * and then cast to particular kmp_task_t type.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002057 auto *FnTy =
Alexey Bataev62b63b12015-03-10 07:28:44 +00002058 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2059 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
2060 break;
2061 }
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00002062 case OMPRTL__kmpc_omp_target_task_alloc: {
2063 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid,
2064 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
2065 // kmp_routine_entry_t *task_entry, kmp_int64 device_id);
2066 assert(KmpRoutineEntryPtrTy != nullptr &&
2067 "Type kmp_routine_entry_t must be created.");
2068 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
2069 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy,
2070 CGM.Int64Ty};
2071 // Return void * and then cast to particular kmp_task_t type.
2072 auto *FnTy =
2073 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2074 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc");
2075 break;
2076 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002077 case OMPRTL__kmpc_omp_task: {
2078 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2079 // *new_task);
2080 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2081 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002082 auto *FnTy =
Alexey Bataev62b63b12015-03-10 07:28:44 +00002083 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2084 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
2085 break;
2086 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00002087 case OMPRTL__kmpc_copyprivate: {
2088 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
Alexey Bataev66beaa92015-04-30 03:47:32 +00002089 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
Alexey Bataeva63048e2015-03-23 06:18:07 +00002090 // kmp_int32 didit);
2091 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2092 auto *CpyFnTy =
2093 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
Alexey Bataev66beaa92015-04-30 03:47:32 +00002094 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
Alexey Bataeva63048e2015-03-23 06:18:07 +00002095 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
2096 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002097 auto *FnTy =
Alexey Bataeva63048e2015-03-23 06:18:07 +00002098 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2099 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
2100 break;
2101 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002102 case OMPRTL__kmpc_reduce: {
2103 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
2104 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
2105 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
2106 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2107 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
2108 /*isVarArg=*/false);
2109 llvm::Type *TypeParams[] = {
2110 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
2111 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
2112 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002113 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002114 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2115 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
2116 break;
2117 }
2118 case OMPRTL__kmpc_reduce_nowait: {
2119 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
2120 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
2121 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
2122 // *lck);
2123 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2124 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
2125 /*isVarArg=*/false);
2126 llvm::Type *TypeParams[] = {
2127 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
2128 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
2129 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002130 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002131 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2132 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
2133 break;
2134 }
2135 case OMPRTL__kmpc_end_reduce: {
2136 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
2137 // kmp_critical_name *lck);
2138 llvm::Type *TypeParams[] = {
2139 getIdentTyPointerTy(), CGM.Int32Ty,
2140 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002141 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002142 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2143 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
2144 break;
2145 }
2146 case OMPRTL__kmpc_end_reduce_nowait: {
2147 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
2148 // kmp_critical_name *lck);
2149 llvm::Type *TypeParams[] = {
2150 getIdentTyPointerTy(), CGM.Int32Ty,
2151 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002152 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002153 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2154 RTLFn =
2155 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
2156 break;
2157 }
Alexey Bataev1d677132015-04-22 13:57:31 +00002158 case OMPRTL__kmpc_omp_task_begin_if0: {
2159 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2160 // *new_task);
2161 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2162 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002163 auto *FnTy =
Alexey Bataev1d677132015-04-22 13:57:31 +00002164 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2165 RTLFn =
2166 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
2167 break;
2168 }
2169 case OMPRTL__kmpc_omp_task_complete_if0: {
2170 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2171 // *new_task);
2172 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2173 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002174 auto *FnTy =
Alexey Bataev1d677132015-04-22 13:57:31 +00002175 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2176 RTLFn = CGM.CreateRuntimeFunction(FnTy,
2177 /*Name=*/"__kmpc_omp_task_complete_if0");
2178 break;
2179 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002180 case OMPRTL__kmpc_ordered: {
2181 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
2182 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002183 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002184 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2185 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
2186 break;
2187 }
2188 case OMPRTL__kmpc_end_ordered: {
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002189 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002190 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002191 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002192 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2193 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
2194 break;
2195 }
Alexey Bataev8b8e2022015-04-27 05:22:09 +00002196 case OMPRTL__kmpc_omp_taskwait: {
2197 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
2198 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002199 auto *FnTy =
Alexey Bataev8b8e2022015-04-27 05:22:09 +00002200 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2201 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
2202 break;
2203 }
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002204 case OMPRTL__kmpc_taskgroup: {
2205 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
2206 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002207 auto *FnTy =
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002208 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2209 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
2210 break;
2211 }
2212 case OMPRTL__kmpc_end_taskgroup: {
2213 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
2214 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002215 auto *FnTy =
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002216 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2217 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
2218 break;
2219 }
Alexey Bataev7f210c62015-06-18 13:40:03 +00002220 case OMPRTL__kmpc_push_proc_bind: {
2221 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
2222 // int proc_bind)
2223 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002224 auto *FnTy =
Alexey Bataev7f210c62015-06-18 13:40:03 +00002225 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2226 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
2227 break;
2228 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002229 case OMPRTL__kmpc_omp_task_with_deps: {
2230 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
2231 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
2232 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
2233 llvm::Type *TypeParams[] = {
2234 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
2235 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002236 auto *FnTy =
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002237 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2238 RTLFn =
2239 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
2240 break;
2241 }
2242 case OMPRTL__kmpc_omp_wait_deps: {
2243 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
2244 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
2245 // kmp_depend_info_t *noalias_dep_list);
2246 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2247 CGM.Int32Ty, CGM.VoidPtrTy,
2248 CGM.Int32Ty, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002249 auto *FnTy =
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002250 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2251 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
2252 break;
2253 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00002254 case OMPRTL__kmpc_cancellationpoint: {
2255 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
2256 // global_tid, kmp_int32 cncl_kind)
2257 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002258 auto *FnTy =
Alexey Bataev0f34da12015-07-02 04:17:07 +00002259 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2260 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
2261 break;
2262 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002263 case OMPRTL__kmpc_cancel: {
2264 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
2265 // kmp_int32 cncl_kind)
2266 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002267 auto *FnTy =
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002268 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2269 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
2270 break;
2271 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002272 case OMPRTL__kmpc_push_num_teams: {
2273 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid,
2274 // kmp_int32 num_teams, kmp_int32 num_threads)
2275 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
2276 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002277 auto *FnTy =
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002278 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2279 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams");
2280 break;
2281 }
2282 case OMPRTL__kmpc_fork_teams: {
2283 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
2284 // microtask, ...);
2285 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2286 getKmpc_MicroPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002287 auto *FnTy =
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002288 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
2289 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams");
James Y Knight9871db02019-02-05 16:42:33 +00002290 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) {
Johannes Doerfertac991bb2019-01-19 05:36:54 +00002291 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
2292 llvm::LLVMContext &Ctx = F->getContext();
2293 llvm::MDBuilder MDB(Ctx);
2294 // Annotate the callback behavior of the __kmpc_fork_teams:
2295 // - The callback callee is argument number 2 (microtask).
2296 // - The first two arguments of the callback callee are unknown (-1).
2297 // - All variadic arguments to the __kmpc_fork_teams are passed to the
2298 // callback callee.
2299 F->addMetadata(
2300 llvm::LLVMContext::MD_callback,
2301 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
2302 2, {-1, -1},
2303 /* VarArgsArePassed */ true)}));
2304 }
2305 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002306 break;
2307 }
Alexey Bataev7292c292016-04-25 12:22:29 +00002308 case OMPRTL__kmpc_taskloop: {
2309 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
2310 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
2311 // sched, kmp_uint64 grainsize, void *task_dup);
2312 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
2313 CGM.IntTy,
2314 CGM.VoidPtrTy,
2315 CGM.IntTy,
2316 CGM.Int64Ty->getPointerTo(),
2317 CGM.Int64Ty->getPointerTo(),
2318 CGM.Int64Ty,
2319 CGM.IntTy,
2320 CGM.IntTy,
2321 CGM.Int64Ty,
2322 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002323 auto *FnTy =
Alexey Bataev7292c292016-04-25 12:22:29 +00002324 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2325 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop");
2326 break;
2327 }
Alexey Bataev8b427062016-05-25 12:36:08 +00002328 case OMPRTL__kmpc_doacross_init: {
2329 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32
2330 // num_dims, struct kmp_dim *dims);
2331 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
2332 CGM.Int32Ty,
2333 CGM.Int32Ty,
2334 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002335 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002336 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2337 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init");
2338 break;
2339 }
2340 case OMPRTL__kmpc_doacross_fini: {
2341 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid);
2342 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002343 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002344 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2345 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini");
2346 break;
2347 }
2348 case OMPRTL__kmpc_doacross_post: {
2349 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64
2350 // *vec);
2351 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2352 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002353 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002354 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2355 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post");
2356 break;
2357 }
2358 case OMPRTL__kmpc_doacross_wait: {
2359 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64
2360 // *vec);
2361 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2362 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002363 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002364 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2365 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait");
2366 break;
2367 }
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002368 case OMPRTL__kmpc_task_reduction_init: {
2369 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void
2370 // *data);
2371 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002372 auto *FnTy =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002373 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2374 RTLFn =
2375 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init");
2376 break;
2377 }
2378 case OMPRTL__kmpc_task_reduction_get_th_data: {
2379 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
2380 // *d);
2381 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002382 auto *FnTy =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002383 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2384 RTLFn = CGM.CreateRuntimeFunction(
2385 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data");
2386 break;
2387 }
Alexey Bataev4f680db2019-03-19 16:41:16 +00002388 case OMPRTL__kmpc_alloc: {
Alexey Bataev6cf7b712019-04-08 19:06:42 +00002389 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t
2390 // al); omp_allocator_handle_t type is void *.
2391 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy};
Alexey Bataev4f680db2019-03-19 16:41:16 +00002392 auto *FnTy =
2393 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2394 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc");
2395 break;
2396 }
2397 case OMPRTL__kmpc_free: {
Alexey Bataev6cf7b712019-04-08 19:06:42 +00002398 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t
2399 // al); omp_allocator_handle_t type is void *.
2400 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataev4f680db2019-03-19 16:41:16 +00002401 auto *FnTy =
2402 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2403 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free");
2404 break;
2405 }
Alexey Bataev7bb33532019-01-07 21:30:43 +00002406 case OMPRTL__kmpc_push_target_tripcount: {
2407 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64
2408 // size);
2409 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty};
2410 llvm::FunctionType *FnTy =
2411 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2412 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount");
2413 break;
2414 }
Samuel Antaobed3c462015-10-02 16:14:20 +00002415 case OMPRTL__tgt_target: {
George Rokos63bc9d62017-11-21 18:25:12 +00002416 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002417 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Samuel Antaobed3c462015-10-02 16:14:20 +00002418 // *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002419 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaobed3c462015-10-02 16:14:20 +00002420 CGM.VoidPtrTy,
2421 CGM.Int32Ty,
2422 CGM.VoidPtrPtrTy,
2423 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002424 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002425 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002426 auto *FnTy =
Samuel Antaobed3c462015-10-02 16:14:20 +00002427 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2428 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
2429 break;
2430 }
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002431 case OMPRTL__tgt_target_nowait: {
2432 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002433 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes,
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002434 // int64_t *arg_types);
2435 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2436 CGM.VoidPtrTy,
2437 CGM.Int32Ty,
2438 CGM.VoidPtrPtrTy,
2439 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002440 CGM.Int64Ty->getPointerTo(),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002441 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002442 auto *FnTy =
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002443 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2444 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait");
2445 break;
2446 }
Samuel Antaob68e2db2016-03-03 16:20:23 +00002447 case OMPRTL__tgt_target_teams: {
George Rokos63bc9d62017-11-21 18:25:12 +00002448 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002449 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes,
George Rokos63bc9d62017-11-21 18:25:12 +00002450 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
2451 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaob68e2db2016-03-03 16:20:23 +00002452 CGM.VoidPtrTy,
2453 CGM.Int32Ty,
2454 CGM.VoidPtrPtrTy,
2455 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002456 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002457 CGM.Int64Ty->getPointerTo(),
Samuel Antaob68e2db2016-03-03 16:20:23 +00002458 CGM.Int32Ty,
2459 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002460 auto *FnTy =
Samuel Antaob68e2db2016-03-03 16:20:23 +00002461 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2462 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams");
2463 break;
2464 }
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002465 case OMPRTL__tgt_target_teams_nowait: {
2466 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void
Alexey Bataeva90fc662019-06-25 16:00:43 +00002467 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002468 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
2469 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2470 CGM.VoidPtrTy,
2471 CGM.Int32Ty,
2472 CGM.VoidPtrPtrTy,
2473 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002474 CGM.Int64Ty->getPointerTo(),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002475 CGM.Int64Ty->getPointerTo(),
2476 CGM.Int32Ty,
2477 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002478 auto *FnTy =
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002479 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2480 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait");
2481 break;
2482 }
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00002483 case OMPRTL__tgt_register_requires: {
2484 // Build void __tgt_register_requires(int64_t flags);
2485 llvm::Type *TypeParams[] = {CGM.Int64Ty};
2486 auto *FnTy =
2487 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2488 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires");
2489 break;
2490 }
Samuel Antaodf158d52016-04-27 22:58:19 +00002491 case OMPRTL__tgt_target_data_begin: {
George Rokos63bc9d62017-11-21 18:25:12 +00002492 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002493 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002494 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaodf158d52016-04-27 22:58:19 +00002495 CGM.Int32Ty,
2496 CGM.VoidPtrPtrTy,
2497 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002498 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002499 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002500 auto *FnTy =
Samuel Antaodf158d52016-04-27 22:58:19 +00002501 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2502 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin");
2503 break;
2504 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002505 case OMPRTL__tgt_target_data_begin_nowait: {
2506 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002507 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002508 // *arg_types);
2509 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2510 CGM.Int32Ty,
2511 CGM.VoidPtrPtrTy,
2512 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002513 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002514 CGM.Int64Ty->getPointerTo()};
2515 auto *FnTy =
2516 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2517 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait");
2518 break;
2519 }
Samuel Antaodf158d52016-04-27 22:58:19 +00002520 case OMPRTL__tgt_target_data_end: {
George Rokos63bc9d62017-11-21 18:25:12 +00002521 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002522 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002523 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaodf158d52016-04-27 22:58:19 +00002524 CGM.Int32Ty,
2525 CGM.VoidPtrPtrTy,
2526 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002527 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002528 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002529 auto *FnTy =
Samuel Antaodf158d52016-04-27 22:58:19 +00002530 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2531 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end");
2532 break;
2533 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002534 case OMPRTL__tgt_target_data_end_nowait: {
2535 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002536 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002537 // *arg_types);
2538 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2539 CGM.Int32Ty,
2540 CGM.VoidPtrPtrTy,
2541 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002542 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002543 CGM.Int64Ty->getPointerTo()};
2544 auto *FnTy =
2545 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2546 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait");
2547 break;
2548 }
Samuel Antao8d2d7302016-05-26 18:30:22 +00002549 case OMPRTL__tgt_target_data_update: {
George Rokos63bc9d62017-11-21 18:25:12 +00002550 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002551 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002552 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antao8d2d7302016-05-26 18:30:22 +00002553 CGM.Int32Ty,
2554 CGM.VoidPtrPtrTy,
2555 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002556 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002557 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002558 auto *FnTy =
Samuel Antao8d2d7302016-05-26 18:30:22 +00002559 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2560 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update");
2561 break;
2562 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002563 case OMPRTL__tgt_target_data_update_nowait: {
2564 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002565 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002566 // *arg_types);
2567 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2568 CGM.Int32Ty,
2569 CGM.VoidPtrPtrTy,
2570 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002571 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002572 CGM.Int64Ty->getPointerTo()};
2573 auto *FnTy =
2574 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2575 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait");
2576 break;
2577 }
Michael Krused47b9432019-08-05 18:43:21 +00002578 case OMPRTL__tgt_mapper_num_components: {
2579 // Build int64_t __tgt_mapper_num_components(void *rt_mapper_handle);
2580 llvm::Type *TypeParams[] = {CGM.VoidPtrTy};
2581 auto *FnTy =
2582 llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false);
2583 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_mapper_num_components");
2584 break;
2585 }
2586 case OMPRTL__tgt_push_mapper_component: {
2587 // Build void __tgt_push_mapper_component(void *rt_mapper_handle, void
2588 // *base, void *begin, int64_t size, int64_t type);
2589 llvm::Type *TypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.VoidPtrTy,
2590 CGM.Int64Ty, CGM.Int64Ty};
2591 auto *FnTy =
2592 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2593 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_push_mapper_component");
2594 break;
2595 }
Alexey Bataev9959db52014-05-06 10:08:46 +00002596 }
Alexey Bataev50b3c952016-02-19 10:38:26 +00002597 assert(RTLFn && "Unable to find OpenMP runtime function");
Alexey Bataev9959db52014-05-06 10:08:46 +00002598 return RTLFn;
2599}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00002600
James Y Knight9871db02019-02-05 16:42:33 +00002601llvm::FunctionCallee
2602CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman21212e42015-03-13 10:38:23 +00002603 assert((IVSize == 32 || IVSize == 64) &&
2604 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002605 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
2606 : "__kmpc_for_static_init_4u")
2607 : (IVSigned ? "__kmpc_for_static_init_8"
2608 : "__kmpc_for_static_init_8u");
2609 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
2610 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
Alexander Musman21212e42015-03-13 10:38:23 +00002611 llvm::Type *TypeParams[] = {
2612 getIdentTyPointerTy(), // loc
2613 CGM.Int32Ty, // tid
2614 CGM.Int32Ty, // schedtype
2615 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
2616 PtrTy, // p_lower
2617 PtrTy, // p_upper
2618 PtrTy, // p_stride
2619 ITy, // incr
2620 ITy // chunk
2621 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002622 auto *FnTy =
Alexander Musman21212e42015-03-13 10:38:23 +00002623 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2624 return CGM.CreateRuntimeFunction(FnTy, Name);
2625}
2626
James Y Knight9871db02019-02-05 16:42:33 +00002627llvm::FunctionCallee
2628CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002629 assert((IVSize == 32 || IVSize == 64) &&
2630 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002631 StringRef Name =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002632 IVSize == 32
2633 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
2634 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002635 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
Alexander Musman92bdaab2015-03-12 13:37:50 +00002636 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
2637 CGM.Int32Ty, // tid
2638 CGM.Int32Ty, // schedtype
2639 ITy, // lower
2640 ITy, // upper
2641 ITy, // stride
2642 ITy // chunk
2643 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002644 auto *FnTy =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002645 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2646 return CGM.CreateRuntimeFunction(FnTy, Name);
2647}
2648
James Y Knight9871db02019-02-05 16:42:33 +00002649llvm::FunctionCallee
2650CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002651 assert((IVSize == 32 || IVSize == 64) &&
2652 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002653 StringRef Name =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002654 IVSize == 32
2655 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
2656 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
2657 llvm::Type *TypeParams[] = {
2658 getIdentTyPointerTy(), // loc
2659 CGM.Int32Ty, // tid
2660 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002661 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002662 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2663 return CGM.CreateRuntimeFunction(FnTy, Name);
2664}
2665
James Y Knight9871db02019-02-05 16:42:33 +00002666llvm::FunctionCallee
2667CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002668 assert((IVSize == 32 || IVSize == 64) &&
2669 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002670 StringRef Name =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002671 IVSize == 32
2672 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
2673 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002674 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
2675 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002676 llvm::Type *TypeParams[] = {
2677 getIdentTyPointerTy(), // loc
2678 CGM.Int32Ty, // tid
2679 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
2680 PtrTy, // p_lower
2681 PtrTy, // p_upper
2682 PtrTy // p_stride
2683 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002684 auto *FnTy =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002685 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2686 return CGM.CreateRuntimeFunction(FnTy, Name);
2687}
2688
Gheorghe-Teodor Bercea625f59d2019-08-01 21:15:58 +00002689/// Obtain information that uniquely identifies a target entry. This
2690/// consists of the file and device IDs as well as line number associated with
2691/// the relevant entry source location.
2692static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
2693 unsigned &DeviceID, unsigned &FileID,
2694 unsigned &LineNum) {
2695 SourceManager &SM = C.getSourceManager();
2696
2697 // The loc should be always valid and have a file ID (the user cannot use
2698 // #pragma directives in macros)
2699
2700 assert(Loc.isValid() && "Source location is expected to be always valid.");
2701
2702 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
2703 assert(PLoc.isValid() && "Source location is expected to be always valid.");
2704
2705 llvm::sys::fs::UniqueID ID;
2706 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
2707 SM.getDiagnostics().Report(diag::err_cannot_open_file)
2708 << PLoc.getFilename() << EC.message();
2709
2710 DeviceID = ID.getDevice();
2711 FileID = ID.getFile();
2712 LineNum = PLoc.getLine();
2713}
2714
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002715Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) {
Alexey Bataev03f270c2018-03-30 18:31:07 +00002716 if (CGM.getLangOpts().OpenMPSimd)
2717 return Address::invalid();
Alexey Bataev92327c52018-03-26 16:40:55 +00002718 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00002719 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002720 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link ||
2721 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
2722 HasRequiresUnifiedSharedMemory))) {
Alexey Bataev92327c52018-03-26 16:40:55 +00002723 SmallString<64> PtrName;
2724 {
2725 llvm::raw_svector_ostream OS(PtrName);
Gheorghe-Teodor Bercea625f59d2019-08-01 21:15:58 +00002726 OS << CGM.getMangledName(GlobalDecl(VD));
2727 if (!VD->isExternallyVisible()) {
2728 unsigned DeviceID, FileID, Line;
2729 getTargetEntryUniqueInfo(CGM.getContext(),
2730 VD->getCanonicalDecl()->getBeginLoc(),
2731 DeviceID, FileID, Line);
2732 OS << llvm::format("_%x", FileID);
2733 }
2734 OS << "_decl_tgt_ref_ptr";
Alexey Bataev92327c52018-03-26 16:40:55 +00002735 }
2736 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName);
2737 if (!Ptr) {
2738 QualType PtrTy = CGM.getContext().getPointerType(VD->getType());
2739 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy),
2740 PtrName);
Gheorghe-Teodor Bercea625f59d2019-08-01 21:15:58 +00002741
2742 auto *GV = cast<llvm::GlobalVariable>(Ptr);
2743 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
2744
2745 if (!CGM.getLangOpts().OpenMPIsDevice)
Alexey Bataev03f270c2018-03-30 18:31:07 +00002746 GV->setInitializer(CGM.GetAddrOfGlobal(VD));
Alexey Bataev03f270c2018-03-30 18:31:07 +00002747 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr));
Alexey Bataev92327c52018-03-26 16:40:55 +00002748 }
2749 return Address(Ptr, CGM.getContext().getDeclAlign(VD));
2750 }
2751 return Address::invalid();
2752}
2753
Alexey Bataev97720002014-11-11 04:05:39 +00002754llvm::Constant *
2755CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002756 assert(!CGM.getLangOpts().OpenMPUseTLS ||
2757 !CGM.getContext().getTargetInfo().isTLSSupported());
Alexey Bataev97720002014-11-11 04:05:39 +00002758 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev18fa2322018-05-02 14:20:50 +00002759 std::string Suffix = getName({"cache", ""});
2760 return getOrCreateInternalVariable(
2761 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix));
Alexey Bataev97720002014-11-11 04:05:39 +00002762}
2763
John McCall7f416cc2015-09-08 08:05:57 +00002764Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
2765 const VarDecl *VD,
2766 Address VDAddr,
2767 SourceLocation Loc) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002768 if (CGM.getLangOpts().OpenMPUseTLS &&
2769 CGM.getContext().getTargetInfo().isTLSSupported())
2770 return VDAddr;
2771
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002772 llvm::Type *VarTy = VDAddr.getElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002773 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00002774 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
2775 CGM.Int8PtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00002776 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
2777 getOrCreateThreadPrivateCache(VD)};
John McCall7f416cc2015-09-08 08:05:57 +00002778 return Address(CGF.EmitRuntimeCall(
2779 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
2780 VDAddr.getAlignment());
Alexey Bataev97720002014-11-11 04:05:39 +00002781}
2782
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002783void CGOpenMPRuntime::emitThreadPrivateVarInit(
John McCall7f416cc2015-09-08 08:05:57 +00002784 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
Alexey Bataev97720002014-11-11 04:05:39 +00002785 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
2786 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
2787 // library.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002788 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002789 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +00002790 OMPLoc);
2791 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
2792 // to register constructor/destructor for variable.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002793 llvm::Value *Args[] = {
2794 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy),
2795 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +00002796 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002797 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +00002798}
2799
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002800llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
John McCall7f416cc2015-09-08 08:05:57 +00002801 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
Alexey Bataev97720002014-11-11 04:05:39 +00002802 bool PerformInit, CodeGenFunction *CGF) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002803 if (CGM.getLangOpts().OpenMPUseTLS &&
2804 CGM.getContext().getTargetInfo().isTLSSupported())
2805 return nullptr;
2806
Alexey Bataev97720002014-11-11 04:05:39 +00002807 VD = VD->getDefinition(CGM.getContext());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00002808 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) {
Alexey Bataev97720002014-11-11 04:05:39 +00002809 QualType ASTTy = VD->getType();
2810
2811 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002812 const Expr *Init = VD->getAnyInitializer();
Alexey Bataev97720002014-11-11 04:05:39 +00002813 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
2814 // Generate function that re-emits the declaration's initializer into the
2815 // threadprivate copy of the variable VD
2816 CodeGenFunction CtorCGF(CGM);
2817 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002818 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
2819 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
Alexey Bataev56223232017-06-09 13:40:18 +00002820 ImplicitParamDecl::Other);
Alexey Bataev97720002014-11-11 04:05:39 +00002821 Args.push_back(&Dst);
2822
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002823 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
John McCallc56a8b32016-03-11 04:30:31 +00002824 CGM.getContext().VoidPtrTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002825 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002826 std::string Name = getName({"__kmpc_global_ctor_", ""});
2827 llvm::Function *Fn =
2828 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002829 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002830 Args, Loc, Loc);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002831 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002832 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00002833 CGM.getContext().VoidPtrTy, Dst.getLocation());
John McCall7f416cc2015-09-08 08:05:57 +00002834 Address Arg = Address(ArgVal, VDAddr.getAlignment());
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002835 Arg = CtorCGF.Builder.CreateElementBitCast(
2836 Arg, CtorCGF.ConvertTypeForMem(ASTTy));
Alexey Bataev97720002014-11-11 04:05:39 +00002837 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
2838 /*IsInitializer=*/true);
2839 ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002840 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00002841 CGM.getContext().VoidPtrTy, Dst.getLocation());
2842 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
2843 CtorCGF.FinishFunction();
2844 Ctor = Fn;
2845 }
2846 if (VD->getType().isDestructedType() != QualType::DK_none) {
2847 // Generate function that emits destructor call for the threadprivate copy
2848 // of the variable VD
2849 CodeGenFunction DtorCGF(CGM);
2850 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002851 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
2852 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
Alexey Bataev56223232017-06-09 13:40:18 +00002853 ImplicitParamDecl::Other);
Alexey Bataev97720002014-11-11 04:05:39 +00002854 Args.push_back(&Dst);
2855
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002856 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
John McCallc56a8b32016-03-11 04:30:31 +00002857 CGM.getContext().VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002858 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002859 std::string Name = getName({"__kmpc_global_dtor_", ""});
2860 llvm::Function *Fn =
2861 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
Adrian Prantl1858c662016-04-24 22:22:29 +00002862 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
Alexey Bataev97720002014-11-11 04:05:39 +00002863 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002864 Loc, Loc);
Adrian Prantl1858c662016-04-24 22:22:29 +00002865 // Create a scope with an artificial location for the body of this function.
2866 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002867 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar(
Alexey Bataev97720002014-11-11 04:05:39 +00002868 DtorCGF.GetAddrOfLocalVar(&Dst),
John McCall7f416cc2015-09-08 08:05:57 +00002869 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
2870 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
Alexey Bataev97720002014-11-11 04:05:39 +00002871 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
2872 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
2873 DtorCGF.FinishFunction();
2874 Dtor = Fn;
2875 }
2876 // Do not emit init function if it is not required.
2877 if (!Ctor && !Dtor)
2878 return nullptr;
2879
2880 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002881 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
2882 /*isVarArg=*/false)
2883 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002884 // Copying constructor for the threadprivate variable.
2885 // Must be NULL - reserved by runtime, but currently it requires that this
2886 // parameter is always NULL. Otherwise it fires assertion.
2887 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
2888 if (Ctor == nullptr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002889 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
2890 /*isVarArg=*/false)
2891 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002892 Ctor = llvm::Constant::getNullValue(CtorTy);
2893 }
2894 if (Dtor == nullptr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002895 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
2896 /*isVarArg=*/false)
2897 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002898 Dtor = llvm::Constant::getNullValue(DtorTy);
2899 }
2900 if (!CGF) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002901 auto *InitFunctionTy =
Alexey Bataev97720002014-11-11 04:05:39 +00002902 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002903 std::string Name = getName({"__omp_threadprivate_init_", ""});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002904 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction(
Alexey Bataev18fa2322018-05-02 14:20:50 +00002905 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction());
Alexey Bataev97720002014-11-11 04:05:39 +00002906 CodeGenFunction InitCGF(CGM);
2907 FunctionArgList ArgList;
2908 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
2909 CGM.getTypes().arrangeNullaryFunction(), ArgList,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002910 Loc, Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002911 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002912 InitCGF.FinishFunction();
2913 return InitFunction;
2914 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002915 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002916 }
2917 return nullptr;
2918}
2919
Alexey Bataev34f8a702018-03-28 14:28:54 +00002920bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD,
2921 llvm::GlobalVariable *Addr,
2922 bool PerformInit) {
Alexey Bataev36724b72019-10-03 16:46:49 +00002923 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
2924 !CGM.getLangOpts().OpenMPIsDevice)
Alexey Bataev4db9dc62019-09-23 15:53:51 +00002925 return false;
Alexey Bataev34f8a702018-03-28 14:28:54 +00002926 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00002927 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002928 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
2929 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
2930 HasRequiresUnifiedSharedMemory))
Alexey Bataevd01b7492018-08-15 19:45:12 +00002931 return CGM.getLangOpts().OpenMPIsDevice;
Alexey Bataev34f8a702018-03-28 14:28:54 +00002932 VD = VD->getDefinition(CGM.getContext());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00002933 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second)
Alexey Bataev34f8a702018-03-28 14:28:54 +00002934 return CGM.getLangOpts().OpenMPIsDevice;
2935
2936 QualType ASTTy = VD->getType();
2937
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002938 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc();
Alexey Bataev34f8a702018-03-28 14:28:54 +00002939 // Produce the unique prefix to identify the new target regions. We use
2940 // the source location of the variable declaration which we know to not
2941 // conflict with any target region.
2942 unsigned DeviceID;
2943 unsigned FileID;
2944 unsigned Line;
2945 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line);
2946 SmallString<128> Buffer, Out;
2947 {
2948 llvm::raw_svector_ostream OS(Buffer);
2949 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID)
2950 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
2951 }
2952
2953 const Expr *Init = VD->getAnyInitializer();
2954 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
2955 llvm::Constant *Ctor;
2956 llvm::Constant *ID;
2957 if (CGM.getLangOpts().OpenMPIsDevice) {
2958 // Generate function that re-emits the declaration's initializer into
2959 // the threadprivate copy of the variable VD
2960 CodeGenFunction CtorCGF(CGM);
2961
2962 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2963 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2964 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
2965 FTy, Twine(Buffer, "_ctor"), FI, Loc);
2966 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF);
2967 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
2968 FunctionArgList(), Loc, Loc);
2969 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF);
2970 CtorCGF.EmitAnyExprToMem(Init,
2971 Address(Addr, CGM.getContext().getDeclAlign(VD)),
2972 Init->getType().getQualifiers(),
2973 /*IsInitializer=*/true);
2974 CtorCGF.FinishFunction();
2975 Ctor = Fn;
2976 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
Alexey Bataeve253f2f2018-05-09 14:15:18 +00002977 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor));
Alexey Bataev34f8a702018-03-28 14:28:54 +00002978 } else {
2979 Ctor = new llvm::GlobalVariable(
2980 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
2981 llvm::GlobalValue::PrivateLinkage,
2982 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor"));
2983 ID = Ctor;
2984 }
2985
2986 // Register the information for the entry associated with the constructor.
2987 Out.clear();
2988 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
2989 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor,
Alexey Bataev03f270c2018-03-30 18:31:07 +00002990 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor);
Alexey Bataev34f8a702018-03-28 14:28:54 +00002991 }
2992 if (VD->getType().isDestructedType() != QualType::DK_none) {
2993 llvm::Constant *Dtor;
2994 llvm::Constant *ID;
2995 if (CGM.getLangOpts().OpenMPIsDevice) {
2996 // Generate function that emits destructor call for the threadprivate
2997 // copy of the variable VD
2998 CodeGenFunction DtorCGF(CGM);
2999
3000 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
3001 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
3002 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
3003 FTy, Twine(Buffer, "_dtor"), FI, Loc);
3004 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
3005 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
3006 FunctionArgList(), Loc, Loc);
3007 // Create a scope with an artificial location for the body of this
3008 // function.
3009 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
3010 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)),
3011 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()),
3012 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
3013 DtorCGF.FinishFunction();
3014 Dtor = Fn;
3015 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
Alexey Bataeve253f2f2018-05-09 14:15:18 +00003016 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor));
Alexey Bataev34f8a702018-03-28 14:28:54 +00003017 } else {
3018 Dtor = new llvm::GlobalVariable(
3019 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
3020 llvm::GlobalValue::PrivateLinkage,
3021 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor"));
3022 ID = Dtor;
3023 }
3024 // Register the information for the entry associated with the destructor.
3025 Out.clear();
3026 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
3027 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor,
Alexey Bataev03f270c2018-03-30 18:31:07 +00003028 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor);
Alexey Bataev34f8a702018-03-28 14:28:54 +00003029 }
3030 return CGM.getLangOpts().OpenMPIsDevice;
3031}
3032
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003033Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
3034 QualType VarType,
3035 StringRef Name) {
Alexey Bataev18fa2322018-05-02 14:20:50 +00003036 std::string Suffix = getName({"artificial", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003037 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType);
Alexey Bataev18fa2322018-05-02 14:20:50 +00003038 llvm::Value *GAddr =
3039 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix));
Alexey Bataev8be5a0f2019-12-31 12:41:57 -05003040 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPUseTLS &&
3041 CGM.getTarget().isTLSSupported()) {
3042 cast<llvm::GlobalVariable>(GAddr)->setThreadLocal(/*Val=*/true);
3043 return Address(GAddr, CGM.getContext().getTypeAlignInChars(VarType));
3044 }
3045 std::string CacheSuffix = getName({"cache", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003046 llvm::Value *Args[] = {
3047 emitUpdateLocation(CGF, SourceLocation()),
3048 getThreadID(CGF, SourceLocation()),
3049 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy),
3050 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00003051 /*isSigned=*/false),
Alexey Bataev18fa2322018-05-02 14:20:50 +00003052 getOrCreateInternalVariable(
3053 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))};
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003054 return Address(
3055 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3056 CGF.EmitRuntimeCall(
3057 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
3058 VarLVType->getPointerTo(/*AddrSpace=*/0)),
Alexey Bataev8be5a0f2019-12-31 12:41:57 -05003059 CGM.getContext().getTypeAlignInChars(VarType));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003060}
3061
Alexey Bataev1d943ae2019-11-19 12:12:23 -05003062void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond,
3063 const RegionCodeGenTy &ThenGen,
3064 const RegionCodeGenTy &ElseGen) {
Alexey Bataev1d677132015-04-22 13:57:31 +00003065 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
3066
3067 // If the condition constant folds and can be elided, try to avoid emitting
3068 // the condition and the dead arm of the if/else.
3069 bool CondConstant;
3070 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003071 if (CondConstant)
Alexey Bataev1d677132015-04-22 13:57:31 +00003072 ThenGen(CGF);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003073 else
Alexey Bataev1d677132015-04-22 13:57:31 +00003074 ElseGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00003075 return;
3076 }
3077
3078 // Otherwise, the condition did not fold, or we couldn't elide it. Just
3079 // emit the conditional branch.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003080 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then");
3081 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else");
3082 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end");
Alexey Bataev1d677132015-04-22 13:57:31 +00003083 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
3084
3085 // Emit the 'then' code.
3086 CGF.EmitBlock(ThenBlock);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003087 ThenGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00003088 CGF.EmitBranch(ContBlock);
3089 // Emit the 'else' code if present.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003090 // There is no need to emit line number for unconditional branch.
3091 (void)ApplyDebugLocation::CreateEmpty(CGF);
3092 CGF.EmitBlock(ElseBlock);
3093 ElseGen(CGF);
3094 // There is no need to emit line number for unconditional branch.
3095 (void)ApplyDebugLocation::CreateEmpty(CGF);
3096 CGF.EmitBranch(ContBlock);
Alexey Bataev1d677132015-04-22 13:57:31 +00003097 // Emit the continuation block for code after the if.
3098 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003099}
3100
Alexey Bataev1d677132015-04-22 13:57:31 +00003101void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00003102 llvm::Function *OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00003103 ArrayRef<llvm::Value *> CapturedVars,
Alexey Bataev1d677132015-04-22 13:57:31 +00003104 const Expr *IfCond) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003105 if (!CGF.HaveInsertPoint())
3106 return;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003107 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003108 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF,
3109 PrePostActionTy &) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00003110 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003111 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev2377fe92015-09-10 08:12:02 +00003112 llvm::Value *Args[] = {
3113 RTLoc,
3114 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003115 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())};
Alexey Bataev2377fe92015-09-10 08:12:02 +00003116 llvm::SmallVector<llvm::Value *, 16> RealArgs;
3117 RealArgs.append(std::begin(Args), std::end(Args));
3118 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
3119
James Y Knight9871db02019-02-05 16:42:33 +00003120 llvm::FunctionCallee RTLFn =
3121 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call);
Alexey Bataev2377fe92015-09-10 08:12:02 +00003122 CGF.EmitRuntimeCall(RTLFn, RealArgs);
3123 };
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003124 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF,
3125 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003126 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
3127 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc);
Alexey Bataev1d677132015-04-22 13:57:31 +00003128 // Build calls:
3129 // __kmpc_serialized_parallel(&Loc, GTid);
3130 llvm::Value *Args[] = {RTLoc, ThreadID};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003131 CGF.EmitRuntimeCall(
3132 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +00003133
Alexey Bataev3e0f4f82019-10-17 14:36:43 +00003134 // OutlinedFn(&GTid, &zero_bound, CapturedStruct);
3135 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc);
Alexey Bataevf89cf212019-10-16 16:59:01 +00003136 Address ZeroAddrBound =
3137 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty,
3138 /*Name=*/".bound.zero.addr");
3139 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0));
Alexey Bataev2377fe92015-09-10 08:12:02 +00003140 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
Alexey Bataev8521ff62018-07-25 20:03:01 +00003141 // ThreadId for serialized parallels is 0.
Alexey Bataev3e0f4f82019-10-17 14:36:43 +00003142 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer());
Alexey Bataevf89cf212019-10-16 16:59:01 +00003143 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer());
Alexey Bataev2377fe92015-09-10 08:12:02 +00003144 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
Alexey Bataev3c595a62017-08-14 15:01:03 +00003145 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +00003146
Alexey Bataev1d677132015-04-22 13:57:31 +00003147 // __kmpc_end_serialized_parallel(&Loc, GTid);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003148 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID};
Alexey Bataev1d677132015-04-22 13:57:31 +00003149 CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003150 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel),
3151 EndArgs);
Alexey Bataev1d677132015-04-22 13:57:31 +00003152 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003153 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -05003154 emitIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003155 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003156 RegionCodeGenTy ThenRCG(ThenGen);
3157 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00003158 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00003159}
3160
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00003161// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +00003162// thread-ID variable (it is passed in a first argument of the outlined function
3163// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
3164// regular serial code region, get thread ID by calling kmp_int32
3165// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
3166// return the address of that temp.
John McCall7f416cc2015-09-08 08:05:57 +00003167Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
3168 SourceLocation Loc) {
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003169 if (auto *OMPRegionInfo =
Alexey Bataevd74d0602014-10-13 06:02:40 +00003170 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003171 if (OMPRegionInfo->getThreadIDVariable())
Akira Hatanakaf139ae32019-12-03 15:17:01 -08003172 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003173
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003174 llvm::Value *ThreadID = getThreadID(CGF, Loc);
3175 QualType Int32Ty =
Alexey Bataevd74d0602014-10-13 06:02:40 +00003176 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003177 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
Alexey Bataevd74d0602014-10-13 06:02:40 +00003178 CGF.EmitStoreOfScalar(ThreadID,
John McCall7f416cc2015-09-08 08:05:57 +00003179 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
Alexey Bataevd74d0602014-10-13 06:02:40 +00003180
3181 return ThreadIDTemp;
3182}
3183
Alexey Bataev1af5bd52019-03-05 17:47:18 +00003184llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable(
3185 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003186 SmallString<256> Buffer;
3187 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00003188 Out << Name;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003189 StringRef RuntimeName = Out.str();
Alexey Bataev43a919f2018-04-13 17:48:43 +00003190 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first;
David Blaikie13156b62014-11-19 03:06:06 +00003191 if (Elem.second) {
3192 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00003193 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00003194 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00003195 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003196
David Blaikie13156b62014-11-19 03:06:06 +00003197 return Elem.second = new llvm::GlobalVariable(
3198 CGM.getModule(), Ty, /*IsConstant*/ false,
3199 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
Alexey Bataev1af5bd52019-03-05 17:47:18 +00003200 Elem.first(), /*InsertBefore=*/nullptr,
3201 llvm::GlobalValue::NotThreadLocal, AddressSpace);
Alexey Bataev97720002014-11-11 04:05:39 +00003202}
3203
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003204llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev18fa2322018-05-02 14:20:50 +00003205 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str();
3206 std::string Name = getName({Prefix, "var"});
3207 return getOrCreateInternalVariable(KmpCriticalNameTy, Name);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003208}
3209
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003210namespace {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003211/// Common pre(post)-action for different OpenMP constructs.
3212class CommonActionTy final : public PrePostActionTy {
James Y Knight9871db02019-02-05 16:42:33 +00003213 llvm::FunctionCallee EnterCallee;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003214 ArrayRef<llvm::Value *> EnterArgs;
James Y Knight9871db02019-02-05 16:42:33 +00003215 llvm::FunctionCallee ExitCallee;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003216 ArrayRef<llvm::Value *> ExitArgs;
3217 bool Conditional;
3218 llvm::BasicBlock *ContBlock = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003219
3220public:
James Y Knight9871db02019-02-05 16:42:33 +00003221 CommonActionTy(llvm::FunctionCallee EnterCallee,
3222 ArrayRef<llvm::Value *> EnterArgs,
3223 llvm::FunctionCallee ExitCallee,
3224 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003225 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
3226 ExitArgs(ExitArgs), Conditional(Conditional) {}
3227 void Enter(CodeGenFunction &CGF) override {
3228 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs);
3229 if (Conditional) {
3230 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes);
3231 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
3232 ContBlock = CGF.createBasicBlock("omp_if.end");
3233 // Generate the branch (If-stmt)
3234 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
3235 CGF.EmitBlock(ThenBlock);
3236 }
Alexey Bataeva744ff52015-05-05 09:24:37 +00003237 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003238 void Done(CodeGenFunction &CGF) {
3239 // Emit the rest of blocks/branches
3240 CGF.EmitBranch(ContBlock);
3241 CGF.EmitBlock(ContBlock, true);
3242 }
3243 void Exit(CodeGenFunction &CGF) override {
3244 CGF.EmitRuntimeCall(ExitCallee, ExitArgs);
Alexey Bataev3e6124b2015-04-10 07:48:12 +00003245 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003246};
Hans Wennborg7eb54642015-09-10 17:07:54 +00003247} // anonymous namespace
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003248
3249void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
3250 StringRef CriticalName,
3251 const RegionCodeGenTy &CriticalOpGen,
Alexey Bataevfc57d162015-12-15 10:55:09 +00003252 SourceLocation Loc, const Expr *Hint) {
3253 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
Alexey Bataev75ddfab2014-12-01 11:32:38 +00003254 // CriticalOpGen();
3255 // __kmpc_end_critical(ident_t *, gtid, Lock);
3256 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev8ef31412015-12-18 07:58:25 +00003257 if (!CGF.HaveInsertPoint())
3258 return;
Alexey Bataevfc57d162015-12-15 10:55:09 +00003259 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3260 getCriticalRegionLock(CriticalName)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003261 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args),
3262 std::end(Args));
Alexey Bataevfc57d162015-12-15 10:55:09 +00003263 if (Hint) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003264 EnterArgs.push_back(CGF.Builder.CreateIntCast(
3265 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false));
3266 }
3267 CommonActionTy Action(
3268 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint
3269 : OMPRTL__kmpc_critical),
3270 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args);
3271 CriticalOpGen.setAction(Action);
Alexey Bataevfc57d162015-12-15 10:55:09 +00003272 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003273}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003274
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003275void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003276 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003277 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003278 if (!CGF.HaveInsertPoint())
3279 return;
Alexey Bataev8d690652014-12-04 07:23:53 +00003280 // if(__kmpc_master(ident_t *, gtid)) {
3281 // MasterOpGen();
3282 // __kmpc_end_master(ident_t *, gtid);
3283 // }
3284 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00003285 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003286 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args,
3287 createRuntimeFunction(OMPRTL__kmpc_end_master), Args,
3288 /*Conditional=*/true);
3289 MasterOpGen.setAction(Action);
3290 emitInlinedDirective(CGF, OMPD_master, MasterOpGen);
3291 Action.Done(CGF);
Alexey Bataev8d690652014-12-04 07:23:53 +00003292}
3293
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003294void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
3295 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003296 if (!CGF.HaveInsertPoint())
3297 return;
Alexey Bataev9f797f32015-02-05 05:57:51 +00003298 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
3299 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003300 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00003301 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003302 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00003303 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
3304 Region->emitUntiedSwitch(CGF);
Alexey Bataev9f797f32015-02-05 05:57:51 +00003305}
3306
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003307void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
3308 const RegionCodeGenTy &TaskgroupOpGen,
3309 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003310 if (!CGF.HaveInsertPoint())
3311 return;
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003312 // __kmpc_taskgroup(ident_t *, gtid);
3313 // TaskgroupOpGen();
3314 // __kmpc_end_taskgroup(ident_t *, gtid);
3315 // Prepare arguments and build a call to __kmpc_taskgroup
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003316 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
3317 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args,
3318 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
3319 Args);
3320 TaskgroupOpGen.setAction(Action);
3321 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003322}
3323
John McCall7f416cc2015-09-08 08:05:57 +00003324/// Given an array of pointers to variables, project the address of a
3325/// given variable.
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003326static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
3327 unsigned Index, const VarDecl *Var) {
John McCall7f416cc2015-09-08 08:05:57 +00003328 // Pull out the pointer to the variable.
James Y Knight751fe282019-02-09 22:22:28 +00003329 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index);
John McCall7f416cc2015-09-08 08:05:57 +00003330 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
3331
3332 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003333 Addr = CGF.Builder.CreateElementBitCast(
3334 Addr, CGF.ConvertTypeForMem(Var->getType()));
John McCall7f416cc2015-09-08 08:05:57 +00003335 return Addr;
3336}
3337
Alexey Bataeva63048e2015-03-23 06:18:07 +00003338static llvm::Value *emitCopyprivateCopyFunction(
Alexey Bataev420d45b2015-04-14 05:11:24 +00003339 CodeGenModule &CGM, llvm::Type *ArgsType,
3340 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003341 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps,
3342 SourceLocation Loc) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003343 ASTContext &C = CGM.getContext();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003344 // void copy_func(void *LHSArg, void *RHSArg);
3345 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003346 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3347 ImplicitParamDecl::Other);
3348 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3349 ImplicitParamDecl::Other);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003350 Args.push_back(&LHSArg);
3351 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003352 const auto &CGFI =
3353 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00003354 std::string Name =
3355 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"});
3356 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
3357 llvm::GlobalValue::InternalLinkage, Name,
3358 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00003359 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00003360 Fn->setDoesNotRecurse();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003361 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003362 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev420d45b2015-04-14 05:11:24 +00003363 // Dest = (void*[n])(LHSArg);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003364 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00003365 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3366 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
3367 ArgsType), CGF.getPointerAlign());
3368 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3369 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
3370 ArgsType), CGF.getPointerAlign());
Alexey Bataeva63048e2015-03-23 06:18:07 +00003371 // *(Type0*)Dst[0] = *(Type0*)Src[0];
3372 // *(Type1*)Dst[1] = *(Type1*)Src[1];
3373 // ...
3374 // *(Typen*)Dst[n] = *(Typen*)Src[n];
Alexey Bataeva63048e2015-03-23 06:18:07 +00003375 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003376 const auto *DestVar =
3377 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +00003378 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
3379
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003380 const auto *SrcVar =
3381 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +00003382 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
3383
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003384 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003385 QualType Type = VD->getType();
John McCall7f416cc2015-09-08 08:05:57 +00003386 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003387 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00003388 CGF.FinishFunction();
3389 return Fn;
3390}
3391
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003392void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003393 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00003394 SourceLocation Loc,
3395 ArrayRef<const Expr *> CopyprivateVars,
3396 ArrayRef<const Expr *> SrcExprs,
3397 ArrayRef<const Expr *> DstExprs,
3398 ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003399 if (!CGF.HaveInsertPoint())
3400 return;
Alexey Bataeva63048e2015-03-23 06:18:07 +00003401 assert(CopyprivateVars.size() == SrcExprs.size() &&
3402 CopyprivateVars.size() == DstExprs.size() &&
3403 CopyprivateVars.size() == AssignmentOps.size());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003404 ASTContext &C = CGM.getContext();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003405 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003406 // if(__kmpc_single(ident_t *, gtid)) {
3407 // SingleOpGen();
3408 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003409 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003410 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00003411 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3412 // <copy_func>, did_it);
3413
John McCall7f416cc2015-09-08 08:05:57 +00003414 Address DidIt = Address::invalid();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003415 if (!CopyprivateVars.empty()) {
3416 // int32 did_it = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003417 QualType KmpInt32Ty =
3418 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003419 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
John McCall7f416cc2015-09-08 08:05:57 +00003420 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003421 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003422 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00003423 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003424 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args,
3425 createRuntimeFunction(OMPRTL__kmpc_end_single), Args,
3426 /*Conditional=*/true);
3427 SingleOpGen.setAction(Action);
3428 emitInlinedDirective(CGF, OMPD_single, SingleOpGen);
3429 if (DidIt.isValid()) {
3430 // did_it = 1;
3431 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
3432 }
3433 Action.Done(CGF);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003434 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3435 // <copy_func>, did_it);
John McCall7f416cc2015-09-08 08:05:57 +00003436 if (DidIt.isValid()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00003437 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
Richard Smith772e2662019-10-04 01:25:59 +00003438 QualType CopyprivateArrayTy = C.getConstantArrayType(
3439 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
3440 /*IndexTypeQuals=*/0);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003441 // Create a list of all private variables for copyprivate.
John McCall7f416cc2015-09-08 08:05:57 +00003442 Address CopyprivateList =
Alexey Bataeva63048e2015-03-23 06:18:07 +00003443 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
3444 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +00003445 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I);
John McCall7f416cc2015-09-08 08:05:57 +00003446 CGF.Builder.CreateStore(
Alexey Bataeva63048e2015-03-23 06:18:07 +00003447 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08003448 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF),
3449 CGF.VoidPtrTy),
John McCall7f416cc2015-09-08 08:05:57 +00003450 Elem);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003451 }
3452 // Build function that copies private values from single region to all other
3453 // threads in the corresponding parallel region.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003454 llvm::Value *CpyFn = emitCopyprivateCopyFunction(
Alexey Bataeva63048e2015-03-23 06:18:07 +00003455 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003456 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003457 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00003458 Address CL =
3459 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
3460 CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003461 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003462 llvm::Value *Args[] = {
3463 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
3464 getThreadID(CGF, Loc), // i32 <gtid>
Alexey Bataev66beaa92015-04-30 03:47:32 +00003465 BufSize, // size_t <buf_size>
John McCall7f416cc2015-09-08 08:05:57 +00003466 CL.getPointer(), // void *<copyprivate list>
Alexey Bataeva63048e2015-03-23 06:18:07 +00003467 CpyFn, // void (*) (void *, void *) <copy_func>
3468 DidItVal // i32 did_it
3469 };
3470 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
3471 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003472}
3473
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003474void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
3475 const RegionCodeGenTy &OrderedOpGen,
Alexey Bataev5f600d62015-09-29 03:48:57 +00003476 SourceLocation Loc, bool IsThreads) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003477 if (!CGF.HaveInsertPoint())
3478 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003479 // __kmpc_ordered(ident_t *, gtid);
3480 // OrderedOpGen();
3481 // __kmpc_end_ordered(ident_t *, gtid);
3482 // Prepare arguments and build a call to __kmpc_ordered
Alexey Bataev5f600d62015-09-29 03:48:57 +00003483 if (IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003484 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003485 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args,
3486 createRuntimeFunction(OMPRTL__kmpc_end_ordered),
3487 Args);
3488 OrderedOpGen.setAction(Action);
3489 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
3490 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003491 }
Alexey Bataev5f600d62015-09-29 03:48:57 +00003492 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003493}
3494
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003495unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) {
Alexey Bataev50b3c952016-02-19 10:38:26 +00003496 unsigned Flags;
3497 if (Kind == OMPD_for)
3498 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
3499 else if (Kind == OMPD_sections)
3500 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
3501 else if (Kind == OMPD_single)
3502 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
3503 else if (Kind == OMPD_barrier)
3504 Flags = OMP_IDENT_BARRIER_EXPL;
3505 else
3506 Flags = OMP_IDENT_BARRIER_IMPL;
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003507 return Flags;
3508}
3509
Alexey Bataevf6a53d62019-03-18 18:40:00 +00003510void CGOpenMPRuntime::getDefaultScheduleAndChunk(
3511 CodeGenFunction &CGF, const OMPLoopDirective &S,
3512 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const {
3513 // Check if the loop directive is actually a doacross loop directive. In this
3514 // case choose static, 1 schedule.
3515 if (llvm::any_of(
3516 S.getClausesOfKind<OMPOrderedClause>(),
3517 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) {
3518 ScheduleKind = OMPC_SCHEDULE_static;
3519 // Chunk size is 1 in this case.
3520 llvm::APInt ChunkSize(32, 1);
3521 ChunkExpr = IntegerLiteral::Create(
3522 CGF.getContext(), ChunkSize,
3523 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
3524 SourceLocation());
3525 }
3526}
3527
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003528void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
3529 OpenMPDirectiveKind Kind, bool EmitChecks,
3530 bool ForceSimpleCall) {
Johannes Doerfertb3c06db2019-11-04 23:00:36 -06003531 // Check if we should use the OMPBuilder
3532 auto *OMPRegionInfo =
3533 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo);
3534 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder();
3535 if (OMPBuilder) {
Johannes Doerfertf9c3c5da2019-12-25 10:33:56 -06003536 CGF.Builder.restoreIP(OMPBuilder->CreateBarrier(
3537 CGF.Builder, Kind, ForceSimpleCall, EmitChecks));
Johannes Doerfertb3c06db2019-11-04 23:00:36 -06003538 return;
3539 }
3540
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003541 if (!CGF.HaveInsertPoint())
3542 return;
3543 // Build call __kmpc_cancel_barrier(loc, thread_id);
3544 // Build call __kmpc_barrier(loc, thread_id);
3545 unsigned Flags = getDefaultFlagsForBarriers(Kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003546 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
3547 // thread_id);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003548 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
3549 getThreadID(CGF, Loc)};
Johannes Doerfertb3c06db2019-11-04 23:00:36 -06003550 if (OMPRegionInfo) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00003551 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003552 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003553 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev25e5b442015-09-15 12:52:43 +00003554 if (EmitChecks) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003555 // if (__kmpc_cancel_barrier()) {
3556 // exit from construct;
3557 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003558 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
3559 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
3560 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003561 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
3562 CGF.EmitBlock(ExitBB);
3563 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003564 CodeGenFunction::JumpDest CancelDestination =
Alexey Bataev25e5b442015-09-15 12:52:43 +00003565 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003566 CGF.EmitBranchThroughCleanup(CancelDestination);
3567 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
3568 }
3569 return;
3570 }
3571 }
3572 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003573}
3574
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003575/// Map the OpenMP loop schedule to the runtime enumeration.
Alexander Musmanc6388682014-12-15 07:07:06 +00003576static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003577 bool Chunked, bool Ordered) {
Alexander Musmanc6388682014-12-15 07:07:06 +00003578 switch (ScheduleKind) {
3579 case OMPC_SCHEDULE_static:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003580 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
3581 : (Ordered ? OMP_ord_static : OMP_sch_static);
Alexander Musmanc6388682014-12-15 07:07:06 +00003582 case OMPC_SCHEDULE_dynamic:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003583 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00003584 case OMPC_SCHEDULE_guided:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003585 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00003586 case OMPC_SCHEDULE_runtime:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003587 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
3588 case OMPC_SCHEDULE_auto:
3589 return Ordered ? OMP_ord_auto : OMP_sch_auto;
Alexander Musmanc6388682014-12-15 07:07:06 +00003590 case OMPC_SCHEDULE_unknown:
3591 assert(!Chunked && "chunk was specified but schedule kind not known");
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003592 return Ordered ? OMP_ord_static : OMP_sch_static;
Alexander Musmanc6388682014-12-15 07:07:06 +00003593 }
3594 llvm_unreachable("Unexpected runtime schedule");
3595}
3596
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003597/// Map the OpenMP distribute schedule to the runtime enumeration.
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003598static OpenMPSchedType
3599getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
3600 // only static is allowed for dist_schedule
3601 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
3602}
3603
Alexander Musmanc6388682014-12-15 07:07:06 +00003604bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
3605 bool Chunked) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003606 OpenMPSchedType Schedule =
3607 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
Alexander Musmanc6388682014-12-15 07:07:06 +00003608 return Schedule == OMP_sch_static;
3609}
3610
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003611bool CGOpenMPRuntime::isStaticNonchunked(
3612 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003613 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003614 return Schedule == OMP_dist_sch_static;
3615}
3616
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00003617bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind,
3618 bool Chunked) const {
3619 OpenMPSchedType Schedule =
3620 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
3621 return Schedule == OMP_sch_static_chunked;
3622}
3623
3624bool CGOpenMPRuntime::isStaticChunked(
3625 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
3626 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
3627 return Schedule == OMP_dist_sch_static_chunked;
3628}
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003629
Alexander Musmandf7a8e22015-01-22 08:49:35 +00003630bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003631 OpenMPSchedType Schedule =
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003632 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00003633 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
3634 return Schedule != OMP_sch_static;
3635}
3636
Alexey Bataev07a3b592019-08-23 19:52:05 +00003637static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003638 OpenMPScheduleClauseModifier M1,
3639 OpenMPScheduleClauseModifier M2) {
Alexey Bataev6cff6242016-05-30 13:05:14 +00003640 int Modifier = 0;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003641 switch (M1) {
3642 case OMPC_SCHEDULE_MODIFIER_monotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003643 Modifier = OMP_sch_modifier_monotonic;
3644 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003645 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003646 Modifier = OMP_sch_modifier_nonmonotonic;
3647 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003648 case OMPC_SCHEDULE_MODIFIER_simd:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003649 if (Schedule == OMP_sch_static_chunked)
3650 Schedule = OMP_sch_static_balanced_chunked;
3651 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003652 case OMPC_SCHEDULE_MODIFIER_last:
3653 case OMPC_SCHEDULE_MODIFIER_unknown:
3654 break;
3655 }
3656 switch (M2) {
3657 case OMPC_SCHEDULE_MODIFIER_monotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003658 Modifier = OMP_sch_modifier_monotonic;
3659 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003660 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003661 Modifier = OMP_sch_modifier_nonmonotonic;
3662 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003663 case OMPC_SCHEDULE_MODIFIER_simd:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003664 if (Schedule == OMP_sch_static_chunked)
3665 Schedule = OMP_sch_static_balanced_chunked;
3666 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003667 case OMPC_SCHEDULE_MODIFIER_last:
3668 case OMPC_SCHEDULE_MODIFIER_unknown:
3669 break;
3670 }
Alexey Bataev07a3b592019-08-23 19:52:05 +00003671 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription.
3672 // If the static schedule kind is specified or if the ordered clause is
3673 // specified, and if the nonmonotonic modifier is not specified, the effect is
3674 // as if the monotonic modifier is specified. Otherwise, unless the monotonic
3675 // modifier is specified, the effect is as if the nonmonotonic modifier is
3676 // specified.
3677 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) {
3678 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
3679 Schedule == OMP_sch_static_balanced_chunked ||
Alexey Bataevc3eded02019-11-18 11:13:08 -05003680 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static ||
3681 Schedule == OMP_dist_sch_static_chunked ||
3682 Schedule == OMP_dist_sch_static))
Alexey Bataev07a3b592019-08-23 19:52:05 +00003683 Modifier = OMP_sch_modifier_nonmonotonic;
3684 }
Alexey Bataev6cff6242016-05-30 13:05:14 +00003685 return Schedule | Modifier;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003686}
3687
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003688void CGOpenMPRuntime::emitForDispatchInit(
3689 CodeGenFunction &CGF, SourceLocation Loc,
3690 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
3691 bool Ordered, const DispatchRTInput &DispatchValues) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003692 if (!CGF.HaveInsertPoint())
3693 return;
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003694 OpenMPSchedType Schedule = getRuntimeSchedule(
3695 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered);
John McCall7f416cc2015-09-08 08:05:57 +00003696 assert(Ordered ||
3697 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
Alexey Bataev6cff6242016-05-30 13:05:14 +00003698 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
3699 Schedule != OMP_sch_static_balanced_chunked));
John McCall7f416cc2015-09-08 08:05:57 +00003700 // Call __kmpc_dispatch_init(
3701 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
3702 // kmp_int[32|64] lower, kmp_int[32|64] upper,
3703 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00003704
John McCall7f416cc2015-09-08 08:05:57 +00003705 // If the Chunk was not specified in the clause - use default value 1.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003706 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk
3707 : CGF.Builder.getIntN(IVSize, 1);
John McCall7f416cc2015-09-08 08:05:57 +00003708 llvm::Value *Args[] = {
Alexey Bataev07a3b592019-08-23 19:52:05 +00003709 emitUpdateLocation(CGF, Loc),
3710 getThreadID(CGF, Loc),
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003711 CGF.Builder.getInt32(addMonoNonMonoModifier(
Alexey Bataev07a3b592019-08-23 19:52:05 +00003712 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type
3713 DispatchValues.LB, // Lower
3714 DispatchValues.UB, // Upper
3715 CGF.Builder.getIntN(IVSize, 1), // Stride
3716 Chunk // Chunk
John McCall7f416cc2015-09-08 08:05:57 +00003717 };
3718 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
3719}
3720
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003721static void emitForStaticInitCall(
3722 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
James Y Knight9871db02019-02-05 16:42:33 +00003723 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003724 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003725 const CGOpenMPRuntime::StaticRTInput &Values) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003726 if (!CGF.HaveInsertPoint())
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003727 return;
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003728
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003729 assert(!Values.Ordered);
3730 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
3731 Schedule == OMP_sch_static_balanced_chunked ||
3732 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
3733 Schedule == OMP_dist_sch_static ||
3734 Schedule == OMP_dist_sch_static_chunked);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003735
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003736 // Call __kmpc_for_static_init(
3737 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
3738 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
3739 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
3740 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
3741 llvm::Value *Chunk = Values.Chunk;
3742 if (Chunk == nullptr) {
3743 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
3744 Schedule == OMP_dist_sch_static) &&
3745 "expected static non-chunked schedule");
3746 // If the Chunk was not specified in the clause - use default value 1.
3747 Chunk = CGF.Builder.getIntN(Values.IVSize, 1);
3748 } else {
3749 assert((Schedule == OMP_sch_static_chunked ||
3750 Schedule == OMP_sch_static_balanced_chunked ||
3751 Schedule == OMP_ord_static_chunked ||
3752 Schedule == OMP_dist_sch_static_chunked) &&
3753 "expected static chunked schedule");
3754 }
3755 llvm::Value *Args[] = {
3756 UpdateLocation,
3757 ThreadId,
Alexey Bataev07a3b592019-08-23 19:52:05 +00003758 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003759 M2)), // Schedule type
3760 Values.IL.getPointer(), // &isLastIter
3761 Values.LB.getPointer(), // &LB
3762 Values.UB.getPointer(), // &UB
3763 Values.ST.getPointer(), // &Stride
3764 CGF.Builder.getIntN(Values.IVSize, 1), // Incr
3765 Chunk // Chunk
3766 };
3767 CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003768}
3769
John McCall7f416cc2015-09-08 08:05:57 +00003770void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
3771 SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003772 OpenMPDirectiveKind DKind,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003773 const OpenMPScheduleTy &ScheduleKind,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003774 const StaticRTInput &Values) {
3775 OpenMPSchedType ScheduleNum = getRuntimeSchedule(
3776 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered);
3777 assert(isOpenMPWorksharingDirective(DKind) &&
3778 "Expected loop-based or sections-based directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003779 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003780 isOpenMPLoopDirective(DKind)
3781 ? OMP_IDENT_WORK_LOOP
3782 : OMP_IDENT_WORK_SECTIONS);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003783 llvm::Value *ThreadId = getThreadID(CGF, Loc);
James Y Knight9871db02019-02-05 16:42:33 +00003784 llvm::FunctionCallee StaticInitFunction =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003785 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
Alexey Bataevc33ba8c2020-01-17 14:05:40 -05003786 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003787 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003788 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003789}
John McCall7f416cc2015-09-08 08:05:57 +00003790
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003791void CGOpenMPRuntime::emitDistributeStaticInit(
3792 CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003793 OpenMPDistScheduleClauseKind SchedKind,
3794 const CGOpenMPRuntime::StaticRTInput &Values) {
3795 OpenMPSchedType ScheduleNum =
3796 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003797 llvm::Value *UpdatedLocation =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003798 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003799 llvm::Value *ThreadId = getThreadID(CGF, Loc);
James Y Knight9871db02019-02-05 16:42:33 +00003800 llvm::FunctionCallee StaticInitFunction =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003801 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003802 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
3803 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003804 OMPC_SCHEDULE_MODIFIER_unknown, Values);
Alexander Musmanc6388682014-12-15 07:07:06 +00003805}
3806
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003807void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
Alexey Bataevf43f7142017-09-06 16:17:35 +00003808 SourceLocation Loc,
3809 OpenMPDirectiveKind DKind) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003810 if (!CGF.HaveInsertPoint())
3811 return;
Alexander Musmanc6388682014-12-15 07:07:06 +00003812 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataevf43f7142017-09-06 16:17:35 +00003813 llvm::Value *Args[] = {
3814 emitUpdateLocation(CGF, Loc,
3815 isOpenMPDistributeDirective(DKind)
3816 ? OMP_IDENT_WORK_DISTRIBUTE
3817 : isOpenMPLoopDirective(DKind)
3818 ? OMP_IDENT_WORK_LOOP
3819 : OMP_IDENT_WORK_SECTIONS),
3820 getThreadID(CGF, Loc)};
Alexey Bataevc33ba8c2020-01-17 14:05:40 -05003821 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003822 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
3823 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00003824}
3825
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003826void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
3827 SourceLocation Loc,
3828 unsigned IVSize,
3829 bool IVSigned) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003830 if (!CGF.HaveInsertPoint())
3831 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003832 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00003833 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003834 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
3835}
3836
Alexander Musman92bdaab2015-03-12 13:37:50 +00003837llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
3838 SourceLocation Loc, unsigned IVSize,
John McCall7f416cc2015-09-08 08:05:57 +00003839 bool IVSigned, Address IL,
3840 Address LB, Address UB,
3841 Address ST) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00003842 // Call __kmpc_dispatch_next(
3843 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
3844 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
3845 // kmp_int[32|64] *p_stride);
3846 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00003847 emitUpdateLocation(CGF, Loc),
3848 getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00003849 IL.getPointer(), // &isLastIter
3850 LB.getPointer(), // &Lower
3851 UB.getPointer(), // &Upper
3852 ST.getPointer() // &Stride
Alexander Musman92bdaab2015-03-12 13:37:50 +00003853 };
3854 llvm::Value *Call =
3855 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
3856 return CGF.EmitScalarConversion(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003857 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00003858 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00003859}
3860
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003861void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
3862 llvm::Value *NumThreads,
3863 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003864 if (!CGF.HaveInsertPoint())
3865 return;
Alexey Bataevb2059782014-10-13 08:23:51 +00003866 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
3867 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003868 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00003869 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003870 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
3871 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00003872}
3873
Alexey Bataev7f210c62015-06-18 13:40:03 +00003874void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
Johannes Doerfert6c5d1f402019-12-25 18:15:36 -06003875 ProcBindKind ProcBind,
Alexey Bataev7f210c62015-06-18 13:40:03 +00003876 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003877 if (!CGF.HaveInsertPoint())
3878 return;
Johannes Doerfert6c5d1f402019-12-25 18:15:36 -06003879 assert(ProcBind != OMP_PROC_BIND_unknown && "Unsupported proc_bind value.");
Alexey Bataev7f210c62015-06-18 13:40:03 +00003880 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
3881 llvm::Value *Args[] = {
3882 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Johannes Doerfert6c5d1f402019-12-25 18:15:36 -06003883 llvm::ConstantInt::get(CGM.IntTy, unsigned(ProcBind), /*isSigned=*/true)};
Alexey Bataev7f210c62015-06-18 13:40:03 +00003884 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
3885}
3886
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003887void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
Alexey Bataeve8e05de2020-02-07 12:22:23 -05003888 SourceLocation Loc, llvm::AtomicOrdering AO) {
Kiran Chandramohana969e052020-02-04 21:43:40 +00003889 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder();
3890 if (OMPBuilder) {
3891 OMPBuilder->CreateFlush(CGF.Builder);
3892 } else {
3893 if (!CGF.HaveInsertPoint())
3894 return;
3895 // Build call void __kmpc_flush(ident_t *loc)
3896 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
3897 emitUpdateLocation(CGF, Loc));
3898 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +00003899}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003900
Alexey Bataev62b63b12015-03-10 07:28:44 +00003901namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003902/// Indexes of fields for type kmp_task_t.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003903enum KmpTaskTFields {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003904 /// List of shared variables.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003905 KmpTaskTShareds,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003906 /// Task routine.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003907 KmpTaskTRoutine,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003908 /// Partition id for the untied tasks.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003909 KmpTaskTPartId,
Alexey Bataevad537bb2016-05-30 09:06:50 +00003910 /// Function with call of destructors for private variables.
3911 Data1,
3912 /// Task priority.
3913 Data2,
Alexey Bataev7292c292016-04-25 12:22:29 +00003914 /// (Taskloops only) Lower bound.
3915 KmpTaskTLowerBound,
3916 /// (Taskloops only) Upper bound.
3917 KmpTaskTUpperBound,
3918 /// (Taskloops only) Stride.
3919 KmpTaskTStride,
3920 /// (Taskloops only) Is last iteration flag.
3921 KmpTaskTLastIter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003922 /// (Taskloops only) Reduction data.
3923 KmpTaskTReductions,
Alexey Bataev62b63b12015-03-10 07:28:44 +00003924};
Hans Wennborg7eb54642015-09-10 17:07:54 +00003925} // anonymous namespace
Alexey Bataev62b63b12015-03-10 07:28:44 +00003926
Samuel Antaoee8fb302016-01-06 13:42:12 +00003927bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003928 return OffloadEntriesTargetRegion.empty() &&
3929 OffloadEntriesDeviceGlobalVar.empty();
Samuel Antaoee8fb302016-01-06 13:42:12 +00003930}
3931
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003932/// Initialize target region entry.
Samuel Antaoee8fb302016-01-06 13:42:12 +00003933void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3934 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3935 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00003936 unsigned Order) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003937 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
3938 "only required for the device "
3939 "code generation.");
Samuel Antao2de62b02016-02-13 23:35:10 +00003940 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
Samuel Antaof83efdb2017-01-05 16:02:49 +00003941 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003942 OMPTargetRegionEntryTargetRegion);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003943 ++OffloadingEntriesNum;
3944}
3945
3946void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3947 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3948 StringRef ParentName, unsigned LineNum,
Samuel Antaof83efdb2017-01-05 16:02:49 +00003949 llvm::Constant *Addr, llvm::Constant *ID,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003950 OMPTargetRegionEntryKind Flags) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003951 // If we are emitting code for a target, the entry is already initialized,
3952 // only has to be registered.
3953 if (CGM.getLangOpts().OpenMPIsDevice) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00003954 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) {
3955 unsigned DiagID = CGM.getDiags().getCustomDiagID(
3956 DiagnosticsEngine::Error,
3957 "Unable to find target region on line '%0' in the device code.");
3958 CGM.getDiags().Report(DiagID) << LineNum;
3959 return;
3960 }
Samuel Antao2de62b02016-02-13 23:35:10 +00003961 auto &Entry =
3962 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
Samuel Antaoee8fb302016-01-06 13:42:12 +00003963 assert(Entry.isValid() && "Entry not initialized!");
3964 Entry.setAddress(Addr);
3965 Entry.setID(ID);
Samuel Antaof83efdb2017-01-05 16:02:49 +00003966 Entry.setFlags(Flags);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003967 } else {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003968 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags);
Samuel Antao2de62b02016-02-13 23:35:10 +00003969 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00003970 ++OffloadingEntriesNum;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003971 }
3972}
3973
3974bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00003975 unsigned DeviceID, unsigned FileID, StringRef ParentName,
3976 unsigned LineNum) const {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003977 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
3978 if (PerDevice == OffloadEntriesTargetRegion.end())
3979 return false;
3980 auto PerFile = PerDevice->second.find(FileID);
3981 if (PerFile == PerDevice->second.end())
3982 return false;
3983 auto PerParentName = PerFile->second.find(ParentName);
3984 if (PerParentName == PerFile->second.end())
3985 return false;
3986 auto PerLine = PerParentName->second.find(LineNum);
3987 if (PerLine == PerParentName->second.end())
3988 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003989 // Fail if this entry is already registered.
Samuel Antao2de62b02016-02-13 23:35:10 +00003990 if (PerLine->second.getAddress() || PerLine->second.getID())
Samuel Antaoee8fb302016-01-06 13:42:12 +00003991 return false;
3992 return true;
3993}
3994
3995void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
3996 const OffloadTargetRegionEntryInfoActTy &Action) {
3997 // Scan all target region entries and perform the provided action.
Alexey Bataev03f270c2018-03-30 18:31:07 +00003998 for (const auto &D : OffloadEntriesTargetRegion)
3999 for (const auto &F : D.second)
4000 for (const auto &P : F.second)
4001 for (const auto &L : P.second)
Samuel Antao2de62b02016-02-13 23:35:10 +00004002 Action(D.first, F.first, P.first(), L.first, L.second);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004003}
4004
Alexey Bataev03f270c2018-03-30 18:31:07 +00004005void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
4006 initializeDeviceGlobalVarEntryInfo(StringRef Name,
4007 OMPTargetGlobalVarEntryKind Flags,
4008 unsigned Order) {
4009 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
4010 "only required for the device "
4011 "code generation.");
4012 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
4013 ++OffloadingEntriesNum;
4014}
Samuel Antaoee8fb302016-01-06 13:42:12 +00004015
Alexey Bataev03f270c2018-03-30 18:31:07 +00004016void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
4017 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr,
4018 CharUnits VarSize,
4019 OMPTargetGlobalVarEntryKind Flags,
4020 llvm::GlobalValue::LinkageTypes Linkage) {
4021 if (CGM.getLangOpts().OpenMPIsDevice) {
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.");
Alexey Bataev8259cc32019-03-12 20:05:17 +00004027 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) {
4028 if (Entry.getVarSize().isZero()) {
4029 Entry.setVarSize(VarSize);
4030 Entry.setLinkage(Linkage);
4031 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004032 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00004033 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004034 Entry.setVarSize(VarSize);
4035 Entry.setLinkage(Linkage);
Alexey Bataev8259cc32019-03-12 20:05:17 +00004036 Entry.setAddress(Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00004037 } else {
Alexey Bataev8259cc32019-03-12 20:05:17 +00004038 if (hasDeviceGlobalVarEntryInfo(VarName)) {
4039 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
4040 assert(Entry.isValid() && Entry.getFlags() == Flags &&
4041 "Entry not initialized!");
4042 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
4043 "Resetting with the new address.");
4044 if (Entry.getVarSize().isZero()) {
4045 Entry.setVarSize(VarSize);
4046 Entry.setLinkage(Linkage);
4047 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004048 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00004049 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004050 OffloadEntriesDeviceGlobalVar.try_emplace(
4051 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage);
4052 ++OffloadingEntriesNum;
4053 }
4054}
4055
4056void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
4057 actOnDeviceGlobalVarEntriesInfo(
4058 const OffloadDeviceGlobalVarEntryInfoActTy &Action) {
4059 // Scan all target region entries and perform the provided action.
4060 for (const auto &E : OffloadEntriesDeviceGlobalVar)
4061 Action(E.getKey(), E.getValue());
Samuel Antaoee8fb302016-01-06 13:42:12 +00004062}
4063
Alexey Bataev03f270c2018-03-30 18:31:07 +00004064void CGOpenMPRuntime::createOffloadEntry(
4065 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags,
4066 llvm::GlobalValue::LinkageTypes Linkage) {
Samuel Antao2de62b02016-02-13 23:35:10 +00004067 StringRef Name = Addr->getName();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004068 llvm::Module &M = CGM.getModule();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004069 llvm::LLVMContext &C = M.getContext();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004070
4071 // Create constant string with the name.
4072 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
4073
Alexey Bataev18fa2322018-05-02 14:20:50 +00004074 std::string StringName = getName({"omp_offloading", "entry_name"});
4075 auto *Str = new llvm::GlobalVariable(
4076 M, StrPtrInit->getType(), /*isConstant=*/true,
4077 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00004078 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004079
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004080 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy),
4081 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy),
4082 llvm::ConstantInt::get(CGM.SizeTy, Size),
4083 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
4084 llvm::ConstantInt::get(CGM.Int32Ty, 0)};
Alexey Bataev18fa2322018-05-02 14:20:50 +00004085 std::string EntryName = getName({"omp_offloading", "entry", ""});
Mike Ricee1ca7b62018-08-29 15:45:11 +00004086 llvm::GlobalVariable *Entry = createGlobalStruct(
4087 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data,
4088 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004089
4090 // The entry has to be created in the section the linker expects it to be.
Sergey Dmitriev4b343fd2019-09-27 20:00:51 +00004091 Entry->setSection("omp_offloading_entries");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004092}
4093
4094void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
4095 // Emit the offloading entries and metadata so that the device codegen side
Samuel Antao4c8035b2016-12-12 18:00:20 +00004096 // can easily figure out what to emit. The produced metadata looks like
4097 // this:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004098 //
4099 // !omp_offload.info = !{!1, ...}
4100 //
4101 // Right now we only generate metadata for function that contain target
4102 // regions.
4103
Sergey Dmitriev5836c352019-10-15 18:42:47 +00004104 // If we are in simd mode or there are no entries, we don't need to do
4105 // anything.
4106 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty())
Samuel Antaoee8fb302016-01-06 13:42:12 +00004107 return;
4108
4109 llvm::Module &M = CGM.getModule();
4110 llvm::LLVMContext &C = M.getContext();
Alexey Bataevba643691d2019-10-03 16:20:34 +00004111 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *,
4112 SourceLocation, StringRef>,
4113 16>
Samuel Antaoee8fb302016-01-06 13:42:12 +00004114 OrderedEntries(OffloadEntriesInfoManager.size());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004115 llvm::SmallVector<StringRef, 16> ParentFunctions(
4116 OffloadEntriesInfoManager.size());
Samuel Antaoee8fb302016-01-06 13:42:12 +00004117
Simon Pilgrim2c518802017-03-30 14:13:19 +00004118 // Auxiliary methods to create metadata values and strings.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004119 auto &&GetMDInt = [this](unsigned V) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004120 return llvm::ConstantAsMetadata::get(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004121 llvm::ConstantInt::get(CGM.Int32Ty, V));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004122 };
4123
Alexey Bataev03f270c2018-03-30 18:31:07 +00004124 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); };
4125
4126 // Create the offloading info metadata node.
4127 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004128
4129 // Create function that emits metadata for each target region entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00004130 auto &&TargetRegionMetadataEmitter =
Alexey Bataevba643691d2019-10-03 16:20:34 +00004131 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt,
4132 &GetMDString](
Alexey Bataev03f270c2018-03-30 18:31:07 +00004133 unsigned DeviceID, unsigned FileID, StringRef ParentName,
4134 unsigned Line,
4135 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
4136 // Generate metadata for target regions. Each entry of this metadata
4137 // contains:
4138 // - Entry 0 -> Kind of this type of metadata (0).
4139 // - Entry 1 -> Device ID of the file where the entry was identified.
4140 // - Entry 2 -> File ID of the file where the entry was identified.
4141 // - Entry 3 -> Mangled name of the function where the entry was
4142 // identified.
4143 // - Entry 4 -> Line in the file where the entry was identified.
4144 // - Entry 5 -> Order the entry was created.
4145 // The first element of the metadata node is the kind.
4146 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID),
4147 GetMDInt(FileID), GetMDString(ParentName),
4148 GetMDInt(Line), GetMDInt(E.getOrder())};
Samuel Antaoee8fb302016-01-06 13:42:12 +00004149
Alexey Bataevba643691d2019-10-03 16:20:34 +00004150 SourceLocation Loc;
4151 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(),
4152 E = CGM.getContext().getSourceManager().fileinfo_end();
4153 I != E; ++I) {
4154 if (I->getFirst()->getUniqueID().getDevice() == DeviceID &&
4155 I->getFirst()->getUniqueID().getFile() == FileID) {
4156 Loc = CGM.getContext().getSourceManager().translateFileLineCol(
4157 I->getFirst(), Line, 1);
4158 break;
4159 }
4160 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004161 // Save this entry in the right position of the ordered entries array.
Alexey Bataevba643691d2019-10-03 16:20:34 +00004162 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName);
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004163 ParentFunctions[E.getOrder()] = ParentName;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004164
Alexey Bataev03f270c2018-03-30 18:31:07 +00004165 // Add metadata to the named metadata node.
4166 MD->addOperand(llvm::MDNode::get(C, Ops));
4167 };
Samuel Antaoee8fb302016-01-06 13:42:12 +00004168
4169 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
4170 TargetRegionMetadataEmitter);
4171
Alexey Bataev03f270c2018-03-30 18:31:07 +00004172 // Create function that emits metadata for each device global variable entry;
4173 auto &&DeviceGlobalVarMetadataEmitter =
4174 [&C, &OrderedEntries, &GetMDInt, &GetMDString,
4175 MD](StringRef MangledName,
4176 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar
4177 &E) {
4178 // Generate metadata for global variables. Each entry of this metadata
4179 // contains:
4180 // - Entry 0 -> Kind of this type of metadata (1).
4181 // - Entry 1 -> Mangled name of the variable.
4182 // - Entry 2 -> Declare target kind.
4183 // - Entry 3 -> Order the entry was created.
4184 // The first element of the metadata node is the kind.
4185 llvm::Metadata *Ops[] = {
4186 GetMDInt(E.getKind()), GetMDString(MangledName),
4187 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
4188
4189 // Save this entry in the right position of the ordered entries array.
Alexey Bataevba643691d2019-10-03 16:20:34 +00004190 OrderedEntries[E.getOrder()] =
4191 std::make_tuple(&E, SourceLocation(), MangledName);
Alexey Bataev03f270c2018-03-30 18:31:07 +00004192
4193 // Add metadata to the named metadata node.
4194 MD->addOperand(llvm::MDNode::get(C, Ops));
4195 };
4196
4197 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo(
4198 DeviceGlobalVarMetadataEmitter);
4199
Alexey Bataevba643691d2019-10-03 16:20:34 +00004200 for (const auto &E : OrderedEntries) {
4201 assert(std::get<0>(E) && "All ordered entries must exist!");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004202 if (const auto *CE =
Samuel Antaoee8fb302016-01-06 13:42:12 +00004203 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
Alexey Bataevba643691d2019-10-03 16:20:34 +00004204 std::get<0>(E))) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004205 if (!CE->getID() || !CE->getAddress()) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004206 // Do not blame the entry if the parent funtion is not emitted.
4207 StringRef FnName = ParentFunctions[CE->getOrder()];
4208 if (!CGM.GetGlobalValue(FnName))
4209 continue;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004210 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4211 DiagnosticsEngine::Error,
Alexey Bataevba643691d2019-10-03 16:20:34 +00004212 "Offloading entry for target region in %0 is incorrect: either the "
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004213 "address or the ID is invalid.");
Alexey Bataevba643691d2019-10-03 16:20:34 +00004214 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004215 continue;
4216 }
Alexey Bataev34f8a702018-03-28 14:28:54 +00004217 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004218 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage);
Alexey Bataevba643691d2019-10-03 16:20:34 +00004219 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy::
4220 OffloadEntryInfoDeviceGlobalVar>(
4221 std::get<0>(E))) {
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004222 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags =
4223 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4224 CE->getFlags());
4225 switch (Flags) {
4226 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00004227 if (CGM.getLangOpts().OpenMPIsDevice &&
4228 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())
4229 continue;
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004230 if (!CE->getAddress()) {
4231 unsigned DiagID = CGM.getDiags().getCustomDiagID(
Alexey Bataevba643691d2019-10-03 16:20:34 +00004232 DiagnosticsEngine::Error, "Offloading entry for declare target "
4233 "variable %0 is incorrect: the "
4234 "address is invalid.");
4235 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E);
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004236 continue;
4237 }
Alexey Bataevb4dd6d22018-08-29 20:41:37 +00004238 // The vaiable has no definition - no need to add the entry.
4239 if (CE->getVarSize().isZero())
4240 continue;
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004241 break;
4242 }
4243 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink:
4244 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) ||
4245 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) &&
4246 "Declaret target link address is set.");
4247 if (CGM.getLangOpts().OpenMPIsDevice)
4248 continue;
4249 if (!CE->getAddress()) {
4250 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4251 DiagnosticsEngine::Error,
4252 "Offloading entry for declare target variable is incorrect: the "
4253 "address is invalid.");
4254 CGM.getDiags().Report(DiagID);
4255 continue;
4256 }
4257 break;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004258 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004259 createOffloadEntry(CE->getAddress(), CE->getAddress(),
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004260 CE->getVarSize().getQuantity(), Flags,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004261 CE->getLinkage());
4262 } else {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004263 llvm_unreachable("Unsupported entry kind.");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004264 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004265 }
4266}
4267
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004268/// Loads all the offload entries information from the host IR
Samuel Antaoee8fb302016-01-06 13:42:12 +00004269/// metadata.
4270void CGOpenMPRuntime::loadOffloadInfoMetadata() {
4271 // If we are in target mode, load the metadata from the host IR. This code has
4272 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
4273
4274 if (!CGM.getLangOpts().OpenMPIsDevice)
4275 return;
4276
4277 if (CGM.getLangOpts().OMPHostIRFile.empty())
4278 return;
4279
4280 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004281 if (auto EC = Buf.getError()) {
4282 CGM.getDiags().Report(diag::err_cannot_open_file)
4283 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004284 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004285 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004286
4287 llvm::LLVMContext C;
Peter Collingbourned9445c42016-11-13 07:00:17 +00004288 auto ME = expectedToErrorOrAndEmitErrors(
4289 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004290
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004291 if (auto EC = ME.getError()) {
4292 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4293 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'");
4294 CGM.getDiags().Report(DiagID)
4295 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004296 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004297 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004298
4299 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
4300 if (!MD)
4301 return;
4302
George Burgess IV00f70bd2018-03-01 05:43:23 +00004303 for (llvm::MDNode *MN : MD->operands()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004304 auto &&GetMDInt = [MN](unsigned Idx) {
4305 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004306 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
4307 };
4308
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004309 auto &&GetMDString = [MN](unsigned Idx) {
4310 auto *V = cast<llvm::MDString>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004311 return V->getString();
4312 };
4313
Alexey Bataev03f270c2018-03-30 18:31:07 +00004314 switch (GetMDInt(0)) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004315 default:
4316 llvm_unreachable("Unexpected metadata!");
4317 break;
4318 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
Alexey Bataev34f8a702018-03-28 14:28:54 +00004319 OffloadingEntryInfoTargetRegion:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004320 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
Alexey Bataev03f270c2018-03-30 18:31:07 +00004321 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2),
4322 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4),
4323 /*Order=*/GetMDInt(5));
4324 break;
4325 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
4326 OffloadingEntryInfoDeviceGlobalVar:
4327 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo(
4328 /*MangledName=*/GetMDString(1),
4329 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4330 /*Flags=*/GetMDInt(2)),
4331 /*Order=*/GetMDInt(3));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004332 break;
4333 }
4334 }
4335}
4336
Alexey Bataev62b63b12015-03-10 07:28:44 +00004337void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
4338 if (!KmpRoutineEntryPtrTy) {
4339 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004340 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004341 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
4342 FunctionProtoType::ExtProtoInfo EPI;
4343 KmpRoutineEntryPtrQTy = C.getPointerType(
4344 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
4345 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
4346 }
4347}
4348
Samuel Antaoee8fb302016-01-06 13:42:12 +00004349QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004350 // Make sure the type of the entry is already created. This is the type we
4351 // have to create:
4352 // struct __tgt_offload_entry{
4353 // void *addr; // Pointer to the offload entry info.
4354 // // (function or global)
4355 // char *name; // Name of the function or global.
4356 // size_t size; // Size of the entry info (0 if it a function).
Samuel Antaof83efdb2017-01-05 16:02:49 +00004357 // int32_t flags; // Flags associated with the entry, e.g. 'link'.
4358 // int32_t reserved; // Reserved, to use by the runtime library.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004359 // };
4360 if (TgtOffloadEntryQTy.isNull()) {
4361 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004362 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004363 RD->startDefinition();
4364 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4365 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
4366 addFieldToRecordDecl(C, RD, C.getSizeType());
Samuel Antaof83efdb2017-01-05 16:02:49 +00004367 addFieldToRecordDecl(
4368 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4369 addFieldToRecordDecl(
4370 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004371 RD->completeDefinition();
Jonas Hahnfeld5e4df282018-01-18 15:38:03 +00004372 RD->addAttr(PackedAttr::CreateImplicit(C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004373 TgtOffloadEntryQTy = C.getRecordType(RD);
4374 }
4375 return TgtOffloadEntryQTy;
4376}
4377
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004378namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00004379struct PrivateHelpersTy {
4380 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
4381 const VarDecl *PrivateElemInit)
4382 : Original(Original), PrivateCopy(PrivateCopy),
4383 PrivateElemInit(PrivateElemInit) {}
4384 const VarDecl *Original;
4385 const VarDecl *PrivateCopy;
4386 const VarDecl *PrivateElemInit;
4387};
4388typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Hans Wennborg7eb54642015-09-10 17:07:54 +00004389} // anonymous namespace
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004390
Alexey Bataev9e034042015-05-05 04:05:12 +00004391static RecordDecl *
Craig Topper8674c5c2015-09-29 04:30:07 +00004392createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004393 if (!Privates.empty()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004394 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004395 // Build struct .kmp_privates_t. {
4396 // /* private vars */
4397 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004398 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t");
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004399 RD->startDefinition();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004400 for (const auto &Pair : Privates) {
4401 const VarDecl *VD = Pair.second.Original;
4402 QualType Type = VD->getType().getNonReferenceType();
4403 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type);
Alexey Bataevc71a4092015-09-11 10:29:41 +00004404 if (VD->hasAttrs()) {
4405 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
4406 E(VD->getAttrs().end());
4407 I != E; ++I)
4408 FD->addAttr(*I);
4409 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004410 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004411 RD->completeDefinition();
4412 return RD;
4413 }
4414 return nullptr;
4415}
4416
Alexey Bataev9e034042015-05-05 04:05:12 +00004417static RecordDecl *
Alexey Bataev7292c292016-04-25 12:22:29 +00004418createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind,
4419 QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004420 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004421 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004422 // Build struct kmp_task_t {
4423 // void * shareds;
4424 // kmp_routine_entry_t routine;
4425 // kmp_int32 part_id;
Alexey Bataevad537bb2016-05-30 09:06:50 +00004426 // kmp_cmplrdata_t data1;
4427 // kmp_cmplrdata_t data2;
Alexey Bataev7292c292016-04-25 12:22:29 +00004428 // For taskloops additional fields:
4429 // kmp_uint64 lb;
4430 // kmp_uint64 ub;
4431 // kmp_int64 st;
4432 // kmp_int32 liter;
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004433 // void * reductions;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004434 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004435 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004436 UD->startDefinition();
4437 addFieldToRecordDecl(C, UD, KmpInt32Ty);
4438 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy);
4439 UD->completeDefinition();
4440 QualType KmpCmplrdataTy = C.getRecordType(UD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004441 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t");
Alexey Bataev62b63b12015-03-10 07:28:44 +00004442 RD->startDefinition();
4443 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4444 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
4445 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004446 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
4447 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004448 if (isOpenMPTaskLoopDirective(Kind)) {
4449 QualType KmpUInt64Ty =
4450 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
4451 QualType KmpInt64Ty =
4452 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
4453 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4454 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4455 addFieldToRecordDecl(C, RD, KmpInt64Ty);
4456 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004457 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004458 }
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004459 RD->completeDefinition();
4460 return RD;
4461}
4462
4463static RecordDecl *
4464createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004465 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004466 ASTContext &C = CGM.getContext();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004467 // Build struct kmp_task_t_with_privates {
4468 // kmp_task_t task_data;
4469 // .kmp_privates_t. privates;
4470 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004471 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004472 RD->startDefinition();
4473 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004474 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates))
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004475 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004476 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004477 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004478}
4479
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004480/// Emit a proxy function which accepts kmp_task_t as the second
Alexey Bataev62b63b12015-03-10 07:28:44 +00004481/// argument.
4482/// \code
4483/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00004484/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt,
Alexey Bataev7292c292016-04-25 12:22:29 +00004485/// For taskloops:
4486/// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004487/// tt->reductions, tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004488/// return 0;
4489/// }
4490/// \endcode
James Y Knight9871db02019-02-05 16:42:33 +00004491static llvm::Function *
Alexey Bataev62b63b12015-03-10 07:28:44 +00004492emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev7292c292016-04-25 12:22:29 +00004493 OpenMPDirectiveKind Kind, QualType KmpInt32Ty,
4494 QualType KmpTaskTWithPrivatesPtrQTy,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004495 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
James Y Knight9871db02019-02-05 16:42:33 +00004496 QualType SharedsPtrTy, llvm::Function *TaskFunction,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004497 llvm::Value *TaskPrivatesMap) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004498 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004499 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004500 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4501 ImplicitParamDecl::Other);
4502 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4503 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4504 ImplicitParamDecl::Other);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004505 Args.push_back(&GtidArg);
4506 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004507 const auto &TaskEntryFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004508 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004509 llvm::FunctionType *TaskEntryTy =
4510 CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004511 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""});
4512 auto *TaskEntry = llvm::Function::Create(
4513 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004514 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004515 TaskEntry->setDoesNotRecurse();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004516 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004517 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args,
4518 Loc, Loc);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004519
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004520 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
Alexey Bataev7292c292016-04-25 12:22:29 +00004521 // tt,
4522 // For taskloops:
4523 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
4524 // tt->task_data.shareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004525 llvm::Value *GtidParam = CGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00004526 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
Alexey Bataev31300ed2016-02-04 11:27:03 +00004527 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4528 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4529 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004530 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004531 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004532 LValue Base =
4533 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004534 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004535 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004536 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004537 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004538
4539 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004540 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
4541 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev1e491372018-01-23 18:44:14 +00004542 CGF.EmitLoadOfScalar(SharedsLVal, Loc),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004543 CGF.ConvertTypeForMem(SharedsPtrTy));
4544
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004545 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4546 llvm::Value *PrivatesParam;
4547 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004548 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004549 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004550 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004551 } else {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004552 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004553 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004554
Alexey Bataev7292c292016-04-25 12:22:29 +00004555 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam,
4556 TaskPrivatesMap,
4557 CGF.Builder
4558 .CreatePointerBitCastOrAddrSpaceCast(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004559 TDBase.getAddress(CGF), CGF.VoidPtrTy)
Alexey Bataev7292c292016-04-25 12:22:29 +00004560 .getPointer()};
4561 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs),
4562 std::end(CommonArgs));
4563 if (isOpenMPTaskLoopDirective(Kind)) {
4564 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004565 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI);
4566 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004567 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004568 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI);
4569 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004570 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004571 LValue StLVal = CGF.EmitLValueForField(Base, *StFI);
4572 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004573 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004574 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4575 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004576 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004577 LValue RLVal = CGF.EmitLValueForField(Base, *RFI);
4578 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004579 CallArgs.push_back(LBParam);
4580 CallArgs.push_back(UBParam);
4581 CallArgs.push_back(StParam);
4582 CallArgs.push_back(LIParam);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004583 CallArgs.push_back(RParam);
Alexey Bataev7292c292016-04-25 12:22:29 +00004584 }
4585 CallArgs.push_back(SharedsParam);
4586
Alexey Bataev3c595a62017-08-14 15:01:03 +00004587 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction,
4588 CallArgs);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004589 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)),
4590 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004591 CGF.FinishFunction();
4592 return TaskEntry;
4593}
4594
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004595static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
4596 SourceLocation Loc,
4597 QualType KmpInt32Ty,
4598 QualType KmpTaskTWithPrivatesPtrQTy,
4599 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004600 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004601 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004602 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4603 ImplicitParamDecl::Other);
4604 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4605 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4606 ImplicitParamDecl::Other);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004607 Args.push_back(&GtidArg);
4608 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004609 const auto &DestructorFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004610 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004611 llvm::FunctionType *DestructorFnTy =
4612 CGM.getTypes().GetFunctionType(DestructorFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004613 std::string Name =
4614 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""});
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004615 auto *DestructorFn =
4616 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00004617 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004618 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004619 DestructorFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004620 DestructorFn->setDoesNotRecurse();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004621 CodeGenFunction CGF(CGM);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004622 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004623 Args, Loc, Loc);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004624
Alexey Bataev31300ed2016-02-04 11:27:03 +00004625 LValue Base = CGF.EmitLoadOfPointerLValue(
4626 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4627 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004628 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004629 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
4630 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004631 Base = CGF.EmitLValueForField(Base, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004632 for (const auto *Field :
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004633 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004634 if (QualType::DestructionKind DtorKind =
4635 Field->getType().isDestructedType()) {
4636 LValue FieldLValue = CGF.EmitLValueForField(Base, Field);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004637 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004638 }
4639 }
4640 CGF.FinishFunction();
4641 return DestructorFn;
4642}
4643
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004644/// Emit a privates mapping function for correct handling of private and
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004645/// firstprivate variables.
4646/// \code
4647/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
4648/// **noalias priv1,..., <tyn> **noalias privn) {
4649/// *priv1 = &.privates.priv1;
4650/// ...;
4651/// *privn = &.privates.privn;
4652/// }
4653/// \endcode
4654static llvm::Value *
4655emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Craig Topper8674c5c2015-09-29 04:30:07 +00004656 ArrayRef<const Expr *> PrivateVars,
4657 ArrayRef<const Expr *> FirstprivateVars,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004658 ArrayRef<const Expr *> LastprivateVars,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004659 QualType PrivatesQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004660 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004661 ASTContext &C = CGM.getContext();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004662 FunctionArgList Args;
4663 ImplicitParamDecl TaskPrivatesArg(
4664 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
Alexey Bataev56223232017-06-09 13:40:18 +00004665 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
4666 ImplicitParamDecl::Other);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004667 Args.push_back(&TaskPrivatesArg);
4668 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
4669 unsigned Counter = 1;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004670 for (const Expr *E : PrivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004671 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004672 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4673 C.getPointerType(C.getPointerType(E->getType()))
4674 .withConst()
4675 .withRestrict(),
4676 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004677 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004678 PrivateVarsPos[VD] = Counter;
4679 ++Counter;
4680 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004681 for (const Expr *E : FirstprivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004682 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004683 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4684 C.getPointerType(C.getPointerType(E->getType()))
4685 .withConst()
4686 .withRestrict(),
4687 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004688 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004689 PrivateVarsPos[VD] = Counter;
4690 ++Counter;
4691 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004692 for (const Expr *E : LastprivateVars) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004693 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004694 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4695 C.getPointerType(C.getPointerType(E->getType()))
4696 .withConst()
4697 .withRestrict(),
4698 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004699 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataevf93095a2016-05-05 08:46:22 +00004700 PrivateVarsPos[VD] = Counter;
4701 ++Counter;
4702 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004703 const auto &TaskPrivatesMapFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004704 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004705 llvm::FunctionType *TaskPrivatesMapTy =
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004706 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004707 std::string Name =
4708 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""});
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004709 auto *TaskPrivatesMap = llvm::Function::Create(
Alexey Bataev18fa2322018-05-02 14:20:50 +00004710 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
4711 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004712 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004713 TaskPrivatesMapFnInfo);
Alexey Bataev8c5555c2019-05-21 15:11:58 +00004714 if (CGM.getLangOpts().Optimize) {
4715 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
4716 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
4717 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
4718 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004719 CodeGenFunction CGF(CGM);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004720 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004721 TaskPrivatesMapFnInfo, Args, Loc, Loc);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004722
4723 // *privi = &.privates.privi;
Alexey Bataev31300ed2016-02-04 11:27:03 +00004724 LValue Base = CGF.EmitLoadOfPointerLValue(
4725 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
4726 TaskPrivatesArg.getType()->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004727 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004728 Counter = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004729 for (const FieldDecl *Field : PrivatesQTyRD->fields()) {
4730 LValue FieldLVal = CGF.EmitLValueForField(Base, Field);
4731 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
4732 LValue RefLVal =
4733 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
4734 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004735 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>());
4736 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004737 ++Counter;
4738 }
4739 CGF.FinishFunction();
4740 return TaskPrivatesMap;
4741}
4742
Alexey Bataevf93095a2016-05-05 08:46:22 +00004743/// Emit initialization for private variables in task-based directives.
Alexey Bataev8a831592016-05-10 10:36:51 +00004744static void emitPrivatesInit(CodeGenFunction &CGF,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004745 const OMPExecutableDirective &D,
4746 Address KmpTaskSharedsPtr, LValue TDBase,
4747 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4748 QualType SharedsTy, QualType SharedsPtrTy,
4749 const OMPTaskDataTy &Data,
4750 ArrayRef<PrivateDataTy> Privates, bool ForDup) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004751 ASTContext &C = CGF.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004752 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
4753 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004754 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind())
4755 ? OMPD_taskloop
4756 : OMPD_task;
4757 const CapturedStmt &CS = *D.getCapturedStmt(Kind);
4758 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004759 LValue SrcBase;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004760 bool IsTargetTask =
4761 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) ||
4762 isOpenMPTargetExecutionDirective(D.getDirectiveKind());
4763 // For target-based directives skip 3 firstprivate arrays BasePointersArray,
4764 // PointersArray and SizesArray. The original variables for these arrays are
4765 // not captured and we get their addresses explicitly.
4766 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) ||
Alexey Bataev8451efa2018-01-15 19:06:12 +00004767 (IsTargetTask && KmpTaskSharedsPtr.isValid())) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004768 SrcBase = CGF.MakeAddrLValue(
4769 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4770 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
4771 SharedsTy);
4772 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004773 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004774 for (const PrivateDataTy &Pair : Privates) {
4775 const VarDecl *VD = Pair.second.PrivateCopy;
4776 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004777 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) &&
4778 !CGF.isTrivialInitializer(Init)))) {
Alexey Bataev8a831592016-05-10 10:36:51 +00004779 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004780 if (const VarDecl *Elem = Pair.second.PrivateElemInit) {
4781 const VarDecl *OriginalVD = Pair.second.Original;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004782 // Check if the variable is the target-based BasePointersArray,
4783 // PointersArray or SizesArray.
4784 LValue SharedRefLValue;
Alexey Bataevab41ea62019-03-13 20:46:28 +00004785 QualType Type = PrivateLValue.getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004786 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004787 if (IsTargetTask && !SharedField) {
4788 assert(isa<ImplicitParamDecl>(OriginalVD) &&
4789 isa<CapturedDecl>(OriginalVD->getDeclContext()) &&
4790 cast<CapturedDecl>(OriginalVD->getDeclContext())
4791 ->getNumParams() == 0 &&
4792 isa<TranslationUnitDecl>(
4793 cast<CapturedDecl>(OriginalVD->getDeclContext())
4794 ->getDeclContext()) &&
4795 "Expected artificial target data variable.");
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004796 SharedRefLValue =
4797 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type);
4798 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004799 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField);
4800 SharedRefLValue = CGF.MakeAddrLValue(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004801 Address(SharedRefLValue.getPointer(CGF),
4802 C.getDeclAlign(OriginalVD)),
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004803 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl),
4804 SharedRefLValue.getTBAAInfo());
4805 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004806 if (Type->isArrayType()) {
4807 // Initialize firstprivate array.
4808 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) {
4809 // Perform simple memcpy.
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00004810 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004811 } else {
4812 // Initialize firstprivate array using element-by-element
Simon Pilgrim2c518802017-03-30 14:13:19 +00004813 // initialization.
Alexey Bataevf93095a2016-05-05 08:46:22 +00004814 CGF.EmitOMPAggregateAssign(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004815 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF),
4816 Type,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004817 [&CGF, Elem, Init, &CapturesInfo](Address DestElement,
4818 Address SrcElement) {
4819 // Clean up any temporaries needed by the initialization.
4820 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4821 InitScope.addPrivate(
4822 Elem, [SrcElement]() -> Address { return SrcElement; });
4823 (void)InitScope.Privatize();
4824 // Emit initialization for single element.
4825 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
4826 CGF, &CapturesInfo);
4827 CGF.EmitAnyExprToMem(Init, DestElement,
4828 Init->getType().getQualifiers(),
4829 /*IsInitializer=*/false);
4830 });
4831 }
4832 } else {
4833 CodeGenFunction::OMPPrivateScope InitScope(CGF);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004834 InitScope.addPrivate(Elem, [SharedRefLValue, &CGF]() -> Address {
4835 return SharedRefLValue.getAddress(CGF);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004836 });
4837 (void)InitScope.Privatize();
4838 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
4839 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
4840 /*capturedByInit=*/false);
4841 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004842 } else {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004843 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004844 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004845 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004846 ++FI;
4847 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004848}
4849
4850/// Check if duplication function is required for taskloops.
4851static bool checkInitIsRequired(CodeGenFunction &CGF,
4852 ArrayRef<PrivateDataTy> Privates) {
4853 bool InitRequired = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004854 for (const PrivateDataTy &Pair : Privates) {
4855 const VarDecl *VD = Pair.second.PrivateCopy;
4856 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004857 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) &&
4858 !CGF.isTrivialInitializer(Init));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004859 if (InitRequired)
4860 break;
Alexey Bataevf93095a2016-05-05 08:46:22 +00004861 }
4862 return InitRequired;
4863}
4864
4865
4866/// Emit task_dup function (for initialization of
4867/// private/firstprivate/lastprivate vars and last_iter flag)
4868/// \code
4869/// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int
4870/// lastpriv) {
4871/// // setup lastprivate flag
4872/// task_dst->last = lastpriv;
4873/// // could be constructor calls here...
4874/// }
4875/// \endcode
4876static llvm::Value *
4877emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
4878 const OMPExecutableDirective &D,
4879 QualType KmpTaskTWithPrivatesPtrQTy,
4880 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4881 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy,
4882 QualType SharedsPtrTy, const OMPTaskDataTy &Data,
4883 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004884 ASTContext &C = CGM.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004885 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004886 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4887 KmpTaskTWithPrivatesPtrQTy,
4888 ImplicitParamDecl::Other);
4889 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4890 KmpTaskTWithPrivatesPtrQTy,
4891 ImplicitParamDecl::Other);
4892 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy,
4893 ImplicitParamDecl::Other);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004894 Args.push_back(&DstArg);
4895 Args.push_back(&SrcArg);
4896 Args.push_back(&LastprivArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004897 const auto &TaskDupFnInfo =
Alexey Bataevf93095a2016-05-05 08:46:22 +00004898 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004899 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004900 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""});
4901 auto *TaskDup = llvm::Function::Create(
4902 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004903 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004904 TaskDup->setDoesNotRecurse();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004905 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004906 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc,
4907 Loc);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004908
4909 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4910 CGF.GetAddrOfLocalVar(&DstArg),
4911 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4912 // task_dst->liter = lastpriv;
4913 if (WithLastIter) {
4914 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
4915 LValue Base = CGF.EmitLValueForField(
4916 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4917 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4918 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar(
4919 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc);
4920 CGF.EmitStoreOfScalar(Lastpriv, LILVal);
4921 }
4922
4923 // Emit initial values for private copies (if any).
4924 assert(!Privates.empty());
4925 Address KmpTaskSharedsPtr = Address::invalid();
4926 if (!Data.FirstprivateVars.empty()) {
4927 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4928 CGF.GetAddrOfLocalVar(&SrcArg),
4929 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4930 LValue Base = CGF.EmitLValueForField(
4931 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4932 KmpTaskSharedsPtr = Address(
4933 CGF.EmitLoadOfScalar(CGF.EmitLValueForField(
4934 Base, *std::next(KmpTaskTQTyRD->field_begin(),
4935 KmpTaskTShareds)),
4936 Loc),
4937 CGF.getNaturalTypeAlignment(SharedsTy));
4938 }
Alexey Bataev8a831592016-05-10 10:36:51 +00004939 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
4940 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004941 CGF.FinishFunction();
4942 return TaskDup;
4943}
4944
Alexey Bataev8a831592016-05-10 10:36:51 +00004945/// Checks if destructor function is required to be generated.
4946/// \return true if cleanups are required, false otherwise.
4947static bool
4948checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) {
4949 bool NeedsCleanup = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004950 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4951 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl());
4952 for (const FieldDecl *FD : PrivateRD->fields()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00004953 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType();
4954 if (NeedsCleanup)
4955 break;
4956 }
4957 return NeedsCleanup;
4958}
4959
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004960CGOpenMPRuntime::TaskResultTy
4961CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
4962 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00004963 llvm::Function *TaskFunction, QualType SharedsTy,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004964 Address Shareds, const OMPTaskDataTy &Data) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004965 ASTContext &C = CGM.getContext();
Alexey Bataev7292c292016-04-25 12:22:29 +00004966 llvm::SmallVector<PrivateDataTy, 4> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004967 // Aggregate privates and sort them by the alignment.
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004968 auto I = Data.PrivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004969 for (const Expr *E : Data.PrivateVars) {
4970 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00004971 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00004972 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00004973 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00004974 /*PrivateElemInit=*/nullptr));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004975 ++I;
4976 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004977 I = Data.FirstprivateCopies.begin();
4978 auto IElemInitRef = Data.FirstprivateInits.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004979 for (const Expr *E : Data.FirstprivateVars) {
4980 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00004981 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00004982 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00004983 PrivateHelpersTy(
4984 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00004985 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())));
Richard Trieucc3949d2016-02-18 22:34:54 +00004986 ++I;
4987 ++IElemInitRef;
Alexey Bataev9e034042015-05-05 04:05:12 +00004988 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004989 I = Data.LastprivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004990 for (const Expr *E : Data.LastprivateVars) {
4991 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00004992 Privates.emplace_back(
Alexey Bataevf93095a2016-05-05 08:46:22 +00004993 C.getDeclAlign(VD),
4994 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00004995 /*PrivateElemInit=*/nullptr));
Alexey Bataevf93095a2016-05-05 08:46:22 +00004996 ++I;
4997 }
Fangrui Song899d1392019-04-24 14:43:05 +00004998 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) {
4999 return L.first > R.first;
5000 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005001 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005002 // Build type kmp_routine_entry_t (if not built yet).
5003 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005004 // Build type kmp_task_t (if not built yet).
Alexey Bataeve213f3e2017-10-11 15:29:40 +00005005 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) {
5006 if (SavedKmpTaskloopTQTy.isNull()) {
5007 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5008 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5009 }
5010 KmpTaskTQTy = SavedKmpTaskloopTQTy;
Alexey Bataev3a03a7f2017-10-11 15:56:38 +00005011 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00005012 assert((D.getDirectiveKind() == OMPD_task ||
5013 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) ||
5014 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) &&
5015 "Expected taskloop, task or target directive");
Alexey Bataeve213f3e2017-10-11 15:29:40 +00005016 if (SavedKmpTaskTQTy.isNull()) {
5017 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5018 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5019 }
5020 KmpTaskTQTy = SavedKmpTaskTQTy;
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005021 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005022 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005023 // Build particular struct kmp_task_t for the given task.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005024 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005025 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005026 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005027 QualType KmpTaskTWithPrivatesPtrQTy =
5028 C.getPointerType(KmpTaskTWithPrivatesQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005029 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
5030 llvm::Type *KmpTaskTWithPrivatesPtrTy =
5031 KmpTaskTWithPrivatesTy->getPointerTo();
5032 llvm::Value *KmpTaskTWithPrivatesTySize =
5033 CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005034 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
5035
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005036 // Emit initial values for private copies (if any).
5037 llvm::Value *TaskPrivatesMap = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005038 llvm::Type *TaskPrivatesMapTy =
James Y Knight9871db02019-02-05 16:42:33 +00005039 std::next(TaskFunction->arg_begin(), 3)->getType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005040 if (!Privates.empty()) {
5041 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataevf93095a2016-05-05 08:46:22 +00005042 TaskPrivatesMap = emitTaskPrivateMappingFunction(
5043 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars,
5044 FI->getType(), Privates);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005045 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5046 TaskPrivatesMap, TaskPrivatesMapTy);
5047 } else {
5048 TaskPrivatesMap = llvm::ConstantPointerNull::get(
5049 cast<llvm::PointerType>(TaskPrivatesMapTy));
5050 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005051 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
5052 // kmp_task_t *tt);
James Y Knight9871db02019-02-05 16:42:33 +00005053 llvm::Function *TaskEntry = emitProxyTaskFunction(
Alexey Bataev7292c292016-04-25 12:22:29 +00005054 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5055 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction,
5056 TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005057
5058 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
5059 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
5060 // kmp_routine_entry_t *task_entry);
5061 // Task flags. Format is taken from
James Y Knight5d71fc52019-01-29 16:37:27 +00005062 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h,
Alexey Bataev62b63b12015-03-10 07:28:44 +00005063 // description of kmp_tasking_flags struct.
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005064 enum {
5065 TiedFlag = 0x1,
5066 FinalFlag = 0x2,
5067 DestructorsFlag = 0x8,
5068 PriorityFlag = 0x20
5069 };
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005070 unsigned Flags = Data.Tied ? TiedFlag : 0;
Alexey Bataev8a831592016-05-10 10:36:51 +00005071 bool NeedsCleanup = false;
5072 if (!Privates.empty()) {
5073 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD);
5074 if (NeedsCleanup)
5075 Flags = Flags | DestructorsFlag;
5076 }
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005077 if (Data.Priority.getInt())
5078 Flags = Flags | PriorityFlag;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005079 llvm::Value *TaskFlags =
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005080 Data.Final.getPointer()
5081 ? CGF.Builder.CreateSelect(Data.Final.getPointer(),
Alexey Bataev62b63b12015-03-10 07:28:44 +00005082 CGF.Builder.getInt32(FinalFlag),
5083 CGF.Builder.getInt32(/*C=*/0))
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005084 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005085 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005086 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00005087 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc),
5088 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
5089 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5090 TaskEntry, KmpRoutineEntryPtrTy)};
5091 llvm::Value *NewTask;
5092 if (D.hasClausesOfKind<OMPNowaitClause>()) {
5093 // Check if we have any device clause associated with the directive.
5094 const Expr *Device = nullptr;
5095 if (auto *C = D.getSingleClause<OMPDeviceClause>())
5096 Device = C->getDevice();
5097 // Emit device ID if any otherwise use default value.
5098 llvm::Value *DeviceID;
5099 if (Device)
5100 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
5101 CGF.Int64Ty, /*isSigned=*/true);
5102 else
5103 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
5104 AllocArgs.push_back(DeviceID);
5105 NewTask = CGF.EmitRuntimeCall(
5106 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs);
5107 } else {
5108 NewTask = CGF.EmitRuntimeCall(
Alexey Bataev62b63b12015-03-10 07:28:44 +00005109 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00005110 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005111 llvm::Value *NewTaskNewTaskTTy =
5112 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5113 NewTask, KmpTaskTWithPrivatesPtrTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005114 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
5115 KmpTaskTWithPrivatesQTy);
5116 LValue TDBase =
5117 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005118 // Fill the data in the resulting kmp_task_t record.
5119 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00005120 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005121 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00005122 KmpTaskSharedsPtr =
5123 Address(CGF.EmitLoadOfScalar(
5124 CGF.EmitLValueForField(
5125 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
5126 KmpTaskTShareds)),
5127 Loc),
5128 CGF.getNaturalTypeAlignment(SharedsTy));
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00005129 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy);
5130 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy);
Richard Smithe78fac52018-04-05 20:52:58 +00005131 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005132 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005133 // Emit initial values for private copies (if any).
Alexey Bataevf93095a2016-05-05 08:46:22 +00005134 TaskResultTy Result;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005135 if (!Privates.empty()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00005136 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD,
5137 SharedsTy, SharedsPtrTy, Data, Privates,
5138 /*ForDup=*/false);
Alexey Bataevf93095a2016-05-05 08:46:22 +00005139 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
5140 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) {
5141 Result.TaskDupFn = emitTaskDupFunction(
5142 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
5143 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates,
5144 /*WithLastIter=*/!Data.LastprivateVars.empty());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005145 }
5146 }
Alexey Bataevad537bb2016-05-30 09:06:50 +00005147 // Fields of union "kmp_cmplrdata_t" for destructors and priority.
5148 enum { Priority = 0, Destructors = 1 };
Alexey Bataev62b63b12015-03-10 07:28:44 +00005149 // Provide pointer to function with destructors for privates.
Alexey Bataevad537bb2016-05-30 09:06:50 +00005150 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005151 const RecordDecl *KmpCmplrdataUD =
5152 (*FI)->getType()->getAsUnionType()->getDecl();
Alexey Bataevad537bb2016-05-30 09:06:50 +00005153 if (NeedsCleanup) {
5154 llvm::Value *DestructorFn = emitDestructorsFunction(
5155 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5156 KmpTaskTWithPrivatesQTy);
5157 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI);
5158 LValue DestructorsLV = CGF.EmitLValueForField(
5159 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
5160 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5161 DestructorFn, KmpRoutineEntryPtrTy),
5162 DestructorsLV);
5163 }
5164 // Set priority.
5165 if (Data.Priority.getInt()) {
5166 LValue Data2LV = CGF.EmitLValueForField(
5167 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
5168 LValue PriorityLV = CGF.EmitLValueForField(
5169 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
5170 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV);
5171 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005172 Result.NewTask = NewTask;
5173 Result.TaskEntry = TaskEntry;
5174 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
5175 Result.TDBase = TDBase;
5176 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
5177 return Result;
Alexey Bataev7292c292016-04-25 12:22:29 +00005178}
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005179
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005180void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
5181 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005182 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005183 QualType SharedsTy, Address Shareds,
5184 const Expr *IfCond,
5185 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005186 if (!CGF.HaveInsertPoint())
5187 return;
5188
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005189 TaskResultTy Result =
5190 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
5191 llvm::Value *NewTask = Result.NewTask;
James Y Knight9871db02019-02-05 16:42:33 +00005192 llvm::Function *TaskEntry = Result.TaskEntry;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005193 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy;
5194 LValue TDBase = Result.TDBase;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005195 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD;
5196 ASTContext &C = CGM.getContext();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005197 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00005198 Address DependenciesArray = Address::invalid();
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005199 unsigned NumDependencies = Data.Dependences.size();
John McCall7f416cc2015-09-08 08:05:57 +00005200 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005201 // Dependence kind for RTL.
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005202 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 };
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005203 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
5204 RecordDecl *KmpDependInfoRD;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005205 QualType FlagsTy =
5206 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005207 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
5208 if (KmpDependInfoTy.isNull()) {
5209 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
5210 KmpDependInfoRD->startDefinition();
5211 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
5212 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
5213 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
5214 KmpDependInfoRD->completeDefinition();
5215 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005216 } else {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005217 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005218 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005219 // Define type kmp_depend_info[<Dependences.size()>];
5220 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00005221 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Richard Smith772e2662019-10-04 01:25:59 +00005222 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005223 // kmp_depend_info[<Dependences.size()>] deps;
Alexey Bataev48591dd2016-04-20 04:01:36 +00005224 DependenciesArray =
5225 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005226 for (unsigned I = 0; I < NumDependencies; ++I) {
5227 const Expr *E = Data.Dependences[I].second;
5228 LValue Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005229 llvm::Value *Size;
5230 QualType Ty = E->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005231 if (const auto *ASE =
5232 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005233 LValue UpAddrLVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005234 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005235 llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32(
5236 UpAddrLVal.getPointer(CGF), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005237 llvm::Value *LowIntPtr =
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005238 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005239 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
5240 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005241 } else {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005242 Size = CGF.getTypeSize(Ty);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005243 }
5244 LValue Base = CGF.MakeAddrLValue(
James Y Knight751fe282019-02-09 22:22:28 +00005245 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005246 KmpDependInfoTy);
5247 // deps[i].base_addr = &<Dependences[i].second>;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005248 LValue BaseAddrLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005249 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00005250 CGF.EmitStoreOfScalar(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005251 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGF.IntPtrTy),
John McCall7f416cc2015-09-08 08:05:57 +00005252 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005253 // deps[i].len = sizeof(<Dependences[i].second>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005254 LValue LenLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005255 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
5256 CGF.EmitStoreOfScalar(Size, LenLVal);
5257 // deps[i].flags = <Dependences[i].first>;
5258 RTLDependenceKindTy DepKind;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005259 switch (Data.Dependences[I].first) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005260 case OMPC_DEPEND_in:
5261 DepKind = DepIn;
5262 break;
Alexey Bataev92e82f92015-11-23 13:33:42 +00005263 // Out and InOut dependencies must use the same code.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005264 case OMPC_DEPEND_out:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005265 case OMPC_DEPEND_inout:
5266 DepKind = DepInOut;
5267 break;
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005268 case OMPC_DEPEND_mutexinoutset:
5269 DepKind = DepMutexInOutSet;
5270 break;
Alexey Bataeveb482352015-12-18 05:05:56 +00005271 case OMPC_DEPEND_source:
Alexey Bataeva636c7f2015-12-23 10:27:45 +00005272 case OMPC_DEPEND_sink:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005273 case OMPC_DEPEND_unknown:
5274 llvm_unreachable("Unknown task dependence type");
5275 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005276 LValue FlagsLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005277 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
5278 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
5279 FlagsLVal);
5280 }
John McCall7f416cc2015-09-08 08:05:57 +00005281 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knightf5f1b0e2019-02-08 15:34:12 +00005282 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005283 }
5284
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005285 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev62b63b12015-03-10 07:28:44 +00005286 // libcall.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005287 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
5288 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
5289 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
5290 // list is not empty
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005291 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5292 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00005293 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
5294 llvm::Value *DepTaskArgs[7];
5295 if (NumDependencies) {
5296 DepTaskArgs[0] = UpLoc;
5297 DepTaskArgs[1] = ThreadID;
5298 DepTaskArgs[2] = NewTask;
5299 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
5300 DepTaskArgs[4] = DependenciesArray.getPointer();
5301 DepTaskArgs[5] = CGF.Builder.getInt32(0);
5302 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5303 }
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005304 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies,
5305 &TaskArgs,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005306 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005307 if (!Data.Tied) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005308 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005309 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
Alexey Bataev48591dd2016-04-20 04:01:36 +00005310 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
5311 }
John McCall7f416cc2015-09-08 08:05:57 +00005312 if (NumDependencies) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005313 CGF.EmitRuntimeCall(
Alexey Bataev48591dd2016-04-20 04:01:36 +00005314 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs);
John McCall7f416cc2015-09-08 08:05:57 +00005315 } else {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005316 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
John McCall7f416cc2015-09-08 08:05:57 +00005317 TaskArgs);
5318 }
Alexey Bataev48591dd2016-04-20 04:01:36 +00005319 // Check if parent region is untied and build return for untied task;
5320 if (auto *Region =
5321 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
5322 Region->emitUntiedSwitch(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00005323 };
John McCall7f416cc2015-09-08 08:05:57 +00005324
5325 llvm::Value *DepWaitTaskArgs[6];
5326 if (NumDependencies) {
5327 DepWaitTaskArgs[0] = UpLoc;
5328 DepWaitTaskArgs[1] = ThreadID;
5329 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
5330 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
5331 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
5332 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5333 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005334 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
Alexey Bataev3c595a62017-08-14 15:01:03 +00005335 NumDependencies, &DepWaitTaskArgs,
5336 Loc](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005337 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005338 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
5339 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
5340 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
5341 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
5342 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00005343 if (NumDependencies)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005344 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005345 DepWaitTaskArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005346 // Call proxy_task_entry(gtid, new_task);
Alexey Bataev3c595a62017-08-14 15:01:03 +00005347 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
5348 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005349 Action.Enter(CGF);
5350 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
Alexey Bataev3c595a62017-08-14 15:01:03 +00005351 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
Alexey Bataev2c7eee52017-08-04 19:10:54 +00005352 OutlinedFnArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005353 };
5354
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005355 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
5356 // kmp_task_t *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005357 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
5358 // kmp_task_t *new_task);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005359 RegionCodeGenTy RCG(CodeGen);
5360 CommonActionTy Action(
5361 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs,
5362 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs);
5363 RCG.setAction(Action);
5364 RCG(CGF);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005365 };
John McCall7f416cc2015-09-08 08:05:57 +00005366
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005367 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -05005368 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005369 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005370 RegionCodeGenTy ThenRCG(ThenCodeGen);
5371 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00005372 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005373}
5374
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005375void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
5376 const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005377 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005378 QualType SharedsTy, Address Shareds,
5379 const Expr *IfCond,
5380 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005381 if (!CGF.HaveInsertPoint())
5382 return;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005383 TaskResultTy Result =
5384 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005385 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev7292c292016-04-25 12:22:29 +00005386 // libcall.
5387 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
5388 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
5389 // sched, kmp_uint64 grainsize, void *task_dup);
5390 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5391 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
5392 llvm::Value *IfVal;
5393 if (IfCond) {
5394 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy,
5395 /*isSigned=*/true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005396 } else {
Alexey Bataev7292c292016-04-25 12:22:29 +00005397 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005398 }
Alexey Bataev7292c292016-04-25 12:22:29 +00005399
5400 LValue LBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005401 Result.TDBase,
5402 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005403 const auto *LBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005404 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005405 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF),
5406 LBLVal.getQuals(),
Alexey Bataev7292c292016-04-25 12:22:29 +00005407 /*IsInitializer=*/true);
5408 LValue UBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005409 Result.TDBase,
5410 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005411 const auto *UBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005412 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005413 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF),
5414 UBLVal.getQuals(),
Alexey Bataev7292c292016-04-25 12:22:29 +00005415 /*IsInitializer=*/true);
5416 LValue StLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005417 Result.TDBase,
5418 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005419 const auto *StVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005420 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005421 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF),
5422 StLVal.getQuals(),
Alexey Bataev7292c292016-04-25 12:22:29 +00005423 /*IsInitializer=*/true);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005424 // Store reductions address.
5425 LValue RedLVal = CGF.EmitLValueForField(
5426 Result.TDBase,
5427 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005428 if (Data.Reductions) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005429 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005430 } else {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005431 CGF.EmitNullInitialization(RedLVal.getAddress(CGF),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005432 CGF.getContext().VoidPtrTy);
5433 }
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005434 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
Alexey Bataev7292c292016-04-25 12:22:29 +00005435 llvm::Value *TaskArgs[] = {
Alexey Bataev33446032017-07-12 18:09:32 +00005436 UpLoc,
5437 ThreadID,
5438 Result.NewTask,
5439 IfVal,
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005440 LBLVal.getPointer(CGF),
5441 UBLVal.getPointer(CGF),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00005442 CGF.EmitLoadOfScalar(StLVal, Loc),
Alexey Bataevac6e4de2018-10-24 19:06:37 +00005443 llvm::ConstantInt::getSigned(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005444 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005445 llvm::ConstantInt::getSigned(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005446 CGF.IntTy, Data.Schedule.getPointer()
5447 ? Data.Schedule.getInt() ? NumTasks : Grainsize
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005448 : NoSchedule),
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005449 Data.Schedule.getPointer()
5450 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty,
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005451 /*isSigned=*/false)
5452 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0),
Alexey Bataev33446032017-07-12 18:09:32 +00005453 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5454 Result.TaskDupFn, CGF.VoidPtrTy)
5455 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)};
Alexey Bataev7292c292016-04-25 12:22:29 +00005456 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs);
5457}
5458
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005459/// Emit reduction operation for each element of array (required for
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005460/// array sections) LHS op = RHS.
5461/// \param Type Type of array.
5462/// \param LHSVar Variable on the left side of the reduction operation
5463/// (references element of array in original variable).
5464/// \param RHSVar Variable on the right side of the reduction operation
5465/// (references element of array in original variable).
5466/// \param RedOpGen Generator of reduction operation with use of LHSVar and
5467/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00005468static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005469 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
5470 const VarDecl *RHSVar,
5471 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
5472 const Expr *, const Expr *)> &RedOpGen,
5473 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
5474 const Expr *UpExpr = nullptr) {
5475 // Perform element-by-element initialization.
5476 QualType ElementTy;
5477 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
5478 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
5479
5480 // Drill down to the base element type on both arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005481 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
5482 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005483
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005484 llvm::Value *RHSBegin = RHSAddr.getPointer();
5485 llvm::Value *LHSBegin = LHSAddr.getPointer();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005486 // Cast from pointer to array type to pointer to single element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005487 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005488 // The basic structure here is a while-do loop.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005489 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
5490 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
5491 llvm::Value *IsEmpty =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005492 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
5493 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
5494
5495 // Enter the loop body, making that address the current address.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005496 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005497 CGF.EmitBlock(BodyBB);
5498
5499 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
5500
5501 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
5502 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
5503 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
5504 Address RHSElementCurrent =
5505 Address(RHSElementPHI,
5506 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5507
5508 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
5509 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
5510 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
5511 Address LHSElementCurrent =
5512 Address(LHSElementPHI,
5513 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5514
5515 // Emit copy.
5516 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005517 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; });
5518 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005519 Scope.Privatize();
5520 RedOpGen(CGF, XExpr, EExpr, UpExpr);
5521 Scope.ForceCleanup();
5522
5523 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005524 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005525 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005526 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005527 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
5528 // Check whether we've reached the end.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005529 llvm::Value *Done =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005530 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
5531 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
5532 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
5533 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
5534
5535 // Done.
5536 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
5537}
5538
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005539/// Emit reduction combiner. If the combiner is a simple expression emit it as
5540/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
5541/// UDR combiner function.
5542static void emitReductionCombiner(CodeGenFunction &CGF,
5543 const Expr *ReductionOp) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005544 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
5545 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
5546 if (const auto *DRE =
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005547 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005548 if (const auto *DRD =
5549 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005550 std::pair<llvm::Function *, llvm::Function *> Reduction =
5551 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
5552 RValue Func = RValue::get(Reduction.first);
5553 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
5554 CGF.EmitIgnoredExpr(ReductionOp);
5555 return;
5556 }
5557 CGF.EmitIgnoredExpr(ReductionOp);
5558}
5559
James Y Knight9871db02019-02-05 16:42:33 +00005560llvm::Function *CGOpenMPRuntime::emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005561 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates,
5562 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
5563 ArrayRef<const Expr *> ReductionOps) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005564 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005565
5566 // void reduction_func(void *LHSArg, void *RHSArg);
5567 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005568 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5569 ImplicitParamDecl::Other);
5570 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5571 ImplicitParamDecl::Other);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005572 Args.push_back(&LHSArg);
5573 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005574 const auto &CGFI =
5575 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00005576 std::string Name = getName({"omp", "reduction", "reduction_func"});
5577 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
5578 llvm::GlobalValue::InternalLinkage, Name,
5579 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00005580 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00005581 Fn->setDoesNotRecurse();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005582 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005583 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005584
5585 // Dst = (void*[n])(LHSArg);
5586 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00005587 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5588 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
5589 ArgsType), CGF.getPointerAlign());
5590 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5591 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
5592 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005593
5594 // ...
5595 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
5596 // ...
5597 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005598 auto IPriv = Privates.begin();
5599 unsigned Idx = 0;
5600 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005601 const auto *RHSVar =
5602 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
5603 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005604 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005605 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005606 const auto *LHSVar =
5607 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
5608 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005609 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005610 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005611 QualType PrivTy = (*IPriv)->getType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00005612 if (PrivTy->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005613 // Get array size and emit VLA type.
5614 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005615 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005616 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005617 const VariableArrayType *VLA =
5618 CGF.getContext().getAsVariableArrayType(PrivTy);
5619 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005620 CodeGenFunction::OpaqueValueMapping OpaqueMap(
Alexey Bataev1189bd02016-01-26 12:20:39 +00005621 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005622 CGF.EmitVariablyModifiedType(PrivTy);
5623 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005624 }
5625 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005626 IPriv = Privates.begin();
5627 auto ILHS = LHSExprs.begin();
5628 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005629 for (const Expr *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005630 if ((*IPriv)->getType()->isArrayType()) {
5631 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005632 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5633 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005634 EmitOMPAggregateReduction(
5635 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5636 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5637 emitReductionCombiner(CGF, E);
5638 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005639 } else {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005640 // Emit reduction for array subscript or single variable.
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005641 emitReductionCombiner(CGF, E);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005642 }
Richard Trieucc3949d2016-02-18 22:34:54 +00005643 ++IPriv;
5644 ++ILHS;
5645 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005646 }
5647 Scope.ForceCleanup();
5648 CGF.FinishFunction();
5649 return Fn;
5650}
5651
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005652void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF,
5653 const Expr *ReductionOp,
5654 const Expr *PrivateRef,
5655 const DeclRefExpr *LHS,
5656 const DeclRefExpr *RHS) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005657 if (PrivateRef->getType()->isArrayType()) {
5658 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005659 const auto *LHSVar = cast<VarDecl>(LHS->getDecl());
5660 const auto *RHSVar = cast<VarDecl>(RHS->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005661 EmitOMPAggregateReduction(
5662 CGF, PrivateRef->getType(), LHSVar, RHSVar,
5663 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5664 emitReductionCombiner(CGF, ReductionOp);
5665 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005666 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005667 // Emit reduction for array subscript or single variable.
5668 emitReductionCombiner(CGF, ReductionOp);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005669 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005670}
5671
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005672void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005673 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005674 ArrayRef<const Expr *> LHSExprs,
5675 ArrayRef<const Expr *> RHSExprs,
5676 ArrayRef<const Expr *> ReductionOps,
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005677 ReductionOptionsTy Options) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00005678 if (!CGF.HaveInsertPoint())
5679 return;
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005680
5681 bool WithNowait = Options.WithNowait;
5682 bool SimpleReduction = Options.SimpleReduction;
5683
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005684 // Next code should be emitted for reduction:
5685 //
5686 // static kmp_critical_name lock = { 0 };
5687 //
5688 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
5689 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
5690 // ...
5691 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
5692 // *(Type<n>-1*)rhs[<n>-1]);
5693 // }
5694 //
5695 // ...
5696 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
5697 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5698 // RedList, reduce_func, &<lock>)) {
5699 // case 1:
5700 // ...
5701 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5702 // ...
5703 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5704 // break;
5705 // case 2:
5706 // ...
5707 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5708 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00005709 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005710 // break;
5711 // default:;
5712 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005713 //
5714 // if SimpleReduction is true, only the next code is generated:
5715 // ...
5716 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5717 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005718
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005719 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005720
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005721 if (SimpleReduction) {
5722 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005723 auto IPriv = Privates.begin();
5724 auto ILHS = LHSExprs.begin();
5725 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005726 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005727 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5728 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005729 ++IPriv;
5730 ++ILHS;
5731 ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005732 }
5733 return;
5734 }
5735
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005736 // 1. Build a list of reduction variables.
5737 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005738 auto Size = RHSExprs.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005739 for (const Expr *E : Privates) {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005740 if (E->getType()->isVariablyModifiedType())
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005741 // Reserve place for array size.
5742 ++Size;
5743 }
5744 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005745 QualType ReductionArrayTy =
Richard Smith772e2662019-10-04 01:25:59 +00005746 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005747 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00005748 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005749 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005750 auto IPriv = Privates.begin();
5751 unsigned Idx = 0;
5752 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
James Y Knight751fe282019-02-09 22:22:28 +00005753 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
John McCall7f416cc2015-09-08 08:05:57 +00005754 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005755 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005756 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy),
John McCall7f416cc2015-09-08 08:05:57 +00005757 Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005758 if ((*IPriv)->getType()->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005759 // Store array size.
5760 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005761 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005762 llvm::Value *Size = CGF.Builder.CreateIntCast(
5763 CGF.getVLASize(
5764 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
Sander de Smalen891af03a2018-02-03 13:55:59 +00005765 .NumElts,
Alexey Bataev1189bd02016-01-26 12:20:39 +00005766 CGF.SizeTy, /*isSigned=*/false);
5767 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
5768 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005769 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005770 }
5771
5772 // 2. Emit reduce_func().
James Y Knight9871db02019-02-05 16:42:33 +00005773 llvm::Function *ReductionFn = emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005774 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
5775 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005776
5777 // 3. Create static kmp_critical_name lock = { 0 };
Alexey Bataev18fa2322018-05-02 14:20:50 +00005778 std::string Name = getName({"reduction"});
5779 llvm::Value *Lock = getCriticalRegionLock(Name);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005780
5781 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5782 // RedList, reduce_func, &<lock>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005783 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
5784 llvm::Value *ThreadId = getThreadID(CGF, Loc);
5785 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
5786 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Samuel Antao4c8035b2016-12-12 18:00:20 +00005787 ReductionList.getPointer(), CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005788 llvm::Value *Args[] = {
5789 IdentTLoc, // ident_t *<loc>
5790 ThreadId, // i32 <gtid>
5791 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
5792 ReductionArrayTySize, // size_type sizeof(RedList)
5793 RL, // void *RedList
5794 ReductionFn, // void (*) (void *, void *) <reduce_func>
5795 Lock // kmp_critical_name *&<lock>
5796 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005797 llvm::Value *Res = CGF.EmitRuntimeCall(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005798 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
5799 : OMPRTL__kmpc_reduce),
5800 Args);
5801
5802 // 5. Build switch(res)
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005803 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
5804 llvm::SwitchInst *SwInst =
5805 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005806
5807 // 6. Build case 1:
5808 // ...
5809 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5810 // ...
5811 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5812 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005813 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005814 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
5815 CGF.EmitBlock(Case1BB);
5816
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005817 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5818 llvm::Value *EndArgs[] = {
5819 IdentTLoc, // ident_t *<loc>
5820 ThreadId, // i32 <gtid>
5821 Lock // kmp_critical_name *&<lock>
5822 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005823 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5824 CodeGenFunction &CGF, PrePostActionTy &Action) {
5825 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005826 auto IPriv = Privates.begin();
5827 auto ILHS = LHSExprs.begin();
5828 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005829 for (const Expr *E : ReductionOps) {
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005830 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5831 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005832 ++IPriv;
5833 ++ILHS;
5834 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005835 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005836 };
5837 RegionCodeGenTy RCG(CodeGen);
5838 CommonActionTy Action(
5839 nullptr, llvm::None,
5840 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
5841 : OMPRTL__kmpc_end_reduce),
5842 EndArgs);
5843 RCG.setAction(Action);
5844 RCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005845
5846 CGF.EmitBranch(DefaultBB);
5847
5848 // 7. Build case 2:
5849 // ...
5850 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5851 // ...
5852 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005853 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005854 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
5855 CGF.EmitBlock(Case2BB);
5856
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005857 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
5858 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005859 auto ILHS = LHSExprs.begin();
5860 auto IRHS = RHSExprs.begin();
5861 auto IPriv = Privates.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005862 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005863 const Expr *XExpr = nullptr;
5864 const Expr *EExpr = nullptr;
5865 const Expr *UpExpr = nullptr;
5866 BinaryOperatorKind BO = BO_Comma;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005867 if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005868 if (BO->getOpcode() == BO_Assign) {
5869 XExpr = BO->getLHS();
5870 UpExpr = BO->getRHS();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005871 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005872 }
5873 // Try to emit update expression as a simple atomic.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005874 const Expr *RHSExpr = UpExpr;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005875 if (RHSExpr) {
5876 // Analyze RHS part of the whole expression.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005877 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005878 RHSExpr->IgnoreParenImpCasts())) {
5879 // If this is a conditional operator, analyze its condition for
5880 // min/max reduction operator.
5881 RHSExpr = ACO->getCond();
Alexey Bataev69a47792015-05-07 03:54:03 +00005882 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005883 if (const auto *BORHS =
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005884 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
5885 EExpr = BORHS->getRHS();
5886 BO = BORHS->getOpcode();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005887 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005888 }
5889 if (XExpr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005890 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005891 auto &&AtomicRedGen = [BO, VD,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005892 Loc](CodeGenFunction &CGF, const Expr *XExpr,
5893 const Expr *EExpr, const Expr *UpExpr) {
5894 LValue X = CGF.EmitLValue(XExpr);
5895 RValue E;
5896 if (EExpr)
5897 E = CGF.EmitAnyExpr(EExpr);
5898 CGF.EmitOMPAtomicSimpleUpdateExpr(
JF Bastien92f4ef12016-04-06 17:26:42 +00005899 X, E, BO, /*IsXLHSInRHSPart=*/true,
5900 llvm::AtomicOrdering::Monotonic, Loc,
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005901 [&CGF, UpExpr, VD, Loc](RValue XRValue) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005902 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5903 PrivateScope.addPrivate(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005904 VD, [&CGF, VD, XRValue, Loc]() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005905 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5906 CGF.emitOMPSimpleStore(
5907 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
5908 VD->getType().getNonReferenceType(), Loc);
5909 return LHSTemp;
5910 });
5911 (void)PrivateScope.Privatize();
5912 return CGF.EmitAnyExpr(UpExpr);
5913 });
5914 };
5915 if ((*IPriv)->getType()->isArrayType()) {
5916 // Emit atomic reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005917 const auto *RHSVar =
5918 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005919 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
5920 AtomicRedGen, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005921 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005922 // Emit atomic reduction for array subscript or single variable.
5923 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005924 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005925 } else {
5926 // Emit as a critical region.
5927 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
Alexey Bataev18fa2322018-05-02 14:20:50 +00005928 const Expr *, const Expr *) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005929 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev18fa2322018-05-02 14:20:50 +00005930 std::string Name = RT.getName({"atomic_reduction"});
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005931 RT.emitCriticalRegion(
Alexey Bataev18fa2322018-05-02 14:20:50 +00005932 CGF, Name,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005933 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
5934 Action.Enter(CGF);
5935 emitReductionCombiner(CGF, E);
5936 },
5937 Loc);
5938 };
5939 if ((*IPriv)->getType()->isArrayType()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005940 const auto *LHSVar =
5941 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5942 const auto *RHSVar =
5943 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005944 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5945 CritRedGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005946 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005947 CritRedGen(CGF, nullptr, nullptr, nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005948 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005949 }
Richard Trieucc3949d2016-02-18 22:34:54 +00005950 ++ILHS;
5951 ++IRHS;
5952 ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005953 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005954 };
5955 RegionCodeGenTy AtomicRCG(AtomicCodeGen);
5956 if (!WithNowait) {
5957 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
5958 llvm::Value *EndArgs[] = {
5959 IdentTLoc, // ident_t *<loc>
5960 ThreadId, // i32 <gtid>
5961 Lock // kmp_critical_name *&<lock>
5962 };
5963 CommonActionTy Action(nullptr, llvm::None,
5964 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
5965 EndArgs);
5966 AtomicRCG.setAction(Action);
5967 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005968 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005969 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005970 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005971
5972 CGF.EmitBranch(DefaultBB);
5973 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
5974}
5975
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005976/// Generates unique name for artificial threadprivate variables.
Alexey Bataev1c44e152018-03-06 18:59:43 +00005977/// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>"
5978static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix,
5979 const Expr *Ref) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005980 SmallString<256> Buffer;
5981 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev1c44e152018-03-06 18:59:43 +00005982 const clang::DeclRefExpr *DE;
5983 const VarDecl *D = ::getBaseDecl(Ref, DE);
5984 if (!D)
5985 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl());
5986 D = D->getCanonicalDecl();
Alexey Bataev18fa2322018-05-02 14:20:50 +00005987 std::string Name = CGM.getOpenMPRuntime().getName(
5988 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)});
5989 Out << Prefix << Name << "_"
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005990 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding();
Benjamin Krameradcd0262020-01-28 20:23:46 +01005991 return std::string(Out.str());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005992}
5993
5994/// Emits reduction initializer function:
5995/// \code
5996/// void @.red_init(void* %arg) {
5997/// %0 = bitcast void* %arg to <type>*
5998/// store <type> <init>, <type>* %0
5999/// ret void
6000/// }
6001/// \endcode
6002static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM,
6003 SourceLocation Loc,
6004 ReductionCodeGen &RCG, unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006005 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006006 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006007 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6008 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006009 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006010 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006011 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006012 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006013 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006014 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006015 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006016 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006017 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006018 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006019 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006020 Address PrivateAddr = CGF.EmitLoadOfPointer(
6021 CGF.GetAddrOfLocalVar(&Param),
6022 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6023 llvm::Value *Size = nullptr;
6024 // If the size of the reduction item is non-constant, load it from global
6025 // threadprivate variable.
6026 if (RCG.getSizes(N).second) {
6027 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6028 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006029 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006030 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6031 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006032 }
6033 RCG.emitAggregateType(CGF, N, Size);
6034 LValue SharedLVal;
6035 // If initializer uses initializer from declare reduction construct, emit a
6036 // pointer to the address of the original reduction item (reuired by reduction
6037 // initializer)
6038 if (RCG.usesReductionInitializer(N)) {
6039 Address SharedAddr =
6040 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6041 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006042 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataev21dab122018-03-09 15:20:30 +00006043 SharedAddr = CGF.EmitLoadOfPointer(
6044 SharedAddr,
6045 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006046 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy);
6047 } else {
6048 SharedLVal = CGF.MakeNaturalAlignAddrLValue(
6049 llvm::ConstantPointerNull::get(CGM.VoidPtrTy),
6050 CGM.getContext().VoidPtrTy);
6051 }
6052 // Emit the initializer:
6053 // %0 = bitcast void* %arg to <type>*
6054 // store <type> <init>, <type>* %0
6055 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal,
6056 [](CodeGenFunction &) { return false; });
6057 CGF.FinishFunction();
6058 return Fn;
6059}
6060
6061/// Emits reduction combiner function:
6062/// \code
6063/// void @.red_comb(void* %arg0, void* %arg1) {
6064/// %lhs = bitcast void* %arg0 to <type>*
6065/// %rhs = bitcast void* %arg1 to <type>*
6066/// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs)
6067/// store <type> %2, <type>* %lhs
6068/// ret void
6069/// }
6070/// \endcode
6071static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM,
6072 SourceLocation Loc,
6073 ReductionCodeGen &RCG, unsigned N,
6074 const Expr *ReductionOp,
6075 const Expr *LHS, const Expr *RHS,
6076 const Expr *PrivateRef) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006077 ASTContext &C = CGM.getContext();
6078 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl());
6079 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006080 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006081 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
6082 C.VoidPtrTy, ImplicitParamDecl::Other);
6083 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6084 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006085 Args.emplace_back(&ParamInOut);
6086 Args.emplace_back(&ParamIn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006087 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006088 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006089 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006090 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006091 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006092 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006093 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006094 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006095 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006096 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006097 llvm::Value *Size = nullptr;
6098 // If the size of the reduction item is non-constant, load it from global
6099 // threadprivate variable.
6100 if (RCG.getSizes(N).second) {
6101 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6102 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006103 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006104 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6105 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006106 }
6107 RCG.emitAggregateType(CGF, N, Size);
6108 // Remap lhs and rhs variables to the addresses of the function arguments.
6109 // %lhs = bitcast void* %arg0 to <type>*
6110 // %rhs = bitcast void* %arg1 to <type>*
6111 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006112 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006113 // Pull out the pointer to the variable.
6114 Address PtrAddr = CGF.EmitLoadOfPointer(
6115 CGF.GetAddrOfLocalVar(&ParamInOut),
6116 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6117 return CGF.Builder.CreateElementBitCast(
6118 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType()));
6119 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006120 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006121 // Pull out the pointer to the variable.
6122 Address PtrAddr = CGF.EmitLoadOfPointer(
6123 CGF.GetAddrOfLocalVar(&ParamIn),
6124 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6125 return CGF.Builder.CreateElementBitCast(
6126 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType()));
6127 });
6128 PrivateScope.Privatize();
6129 // Emit the combiner body:
6130 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs)
6131 // store <type> %2, <type>* %lhs
6132 CGM.getOpenMPRuntime().emitSingleReductionCombiner(
6133 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS),
6134 cast<DeclRefExpr>(RHS));
6135 CGF.FinishFunction();
6136 return Fn;
6137}
6138
6139/// Emits reduction finalizer function:
6140/// \code
6141/// void @.red_fini(void* %arg) {
6142/// %0 = bitcast void* %arg to <type>*
6143/// <destroy>(<type>* %0)
6144/// ret void
6145/// }
6146/// \endcode
6147static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM,
6148 SourceLocation Loc,
6149 ReductionCodeGen &RCG, unsigned N) {
6150 if (!RCG.needCleanups(N))
6151 return nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006152 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006153 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006154 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6155 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006156 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006157 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006158 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006159 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006160 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006161 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006162 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006163 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006164 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006165 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006166 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006167 Address PrivateAddr = CGF.EmitLoadOfPointer(
6168 CGF.GetAddrOfLocalVar(&Param),
6169 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6170 llvm::Value *Size = nullptr;
6171 // If the size of the reduction item is non-constant, load it from global
6172 // threadprivate variable.
6173 if (RCG.getSizes(N).second) {
6174 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6175 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006176 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006177 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6178 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006179 }
6180 RCG.emitAggregateType(CGF, N, Size);
6181 // Emit the finalizer body:
6182 // <destroy>(<type>* %0)
6183 RCG.emitCleanups(CGF, N, PrivateAddr);
Adrian Prantlce7d3592019-12-05 12:26:16 -08006184 CGF.FinishFunction(Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006185 return Fn;
6186}
6187
6188llvm::Value *CGOpenMPRuntime::emitTaskReductionInit(
6189 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
6190 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
6191 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty())
6192 return nullptr;
6193
6194 // Build typedef struct:
6195 // kmp_task_red_input {
6196 // void *reduce_shar; // shared reduction item
6197 // size_t reduce_size; // size of data item
6198 // void *reduce_init; // data initialization routine
6199 // void *reduce_fini; // data finalization routine
6200 // void *reduce_comb; // data combiner routine
6201 // kmp_task_red_flags_t flags; // flags for additional info from compiler
6202 // } kmp_task_red_input_t;
6203 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006204 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t");
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006205 RD->startDefinition();
6206 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6207 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType());
6208 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6209 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6210 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6211 const FieldDecl *FlagsFD = addFieldToRecordDecl(
6212 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false));
6213 RD->completeDefinition();
6214 QualType RDType = C.getRecordType(RD);
6215 unsigned Size = Data.ReductionVars.size();
6216 llvm::APInt ArraySize(/*numBits=*/64, Size);
6217 QualType ArrayRDType = C.getConstantArrayType(
Richard Smith772e2662019-10-04 01:25:59 +00006218 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006219 // kmp_task_red_input_t .rd_input.[Size];
6220 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input.");
6221 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies,
6222 Data.ReductionOps);
6223 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) {
6224 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt];
6225 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0),
6226 llvm::ConstantInt::get(CGM.SizeTy, Cnt)};
6227 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP(
6228 TaskRedInput.getPointer(), Idxs,
6229 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc,
6230 ".rd_input.gep.");
6231 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType);
6232 // ElemLVal.reduce_shar = &Shareds[Cnt];
6233 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD);
6234 RCG.emitSharedLValue(CGF, Cnt);
6235 llvm::Value *CastedShared =
Akira Hatanakaf139ae32019-12-03 15:17:01 -08006236 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006237 CGF.EmitStoreOfScalar(CastedShared, SharedLVal);
6238 RCG.emitAggregateType(CGF, Cnt);
6239 llvm::Value *SizeValInChars;
6240 llvm::Value *SizeVal;
6241 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt);
6242 // We use delayed creation/initialization for VLAs, array sections and
6243 // custom reduction initializations. It is required because runtime does not
6244 // provide the way to pass the sizes of VLAs/array sections to
6245 // initializer/combiner/finalizer functions and does not pass the pointer to
6246 // original reduction item to the initializer. Instead threadprivate global
6247 // variables are used to store these values and use them in the functions.
6248 bool DelayedCreation = !!SizeVal;
6249 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy,
6250 /*isSigned=*/false);
6251 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD);
6252 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal);
6253 // ElemLVal.reduce_init = init;
6254 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD);
6255 llvm::Value *InitAddr =
6256 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt));
6257 CGF.EmitStoreOfScalar(InitAddr, InitLVal);
6258 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt);
6259 // ElemLVal.reduce_fini = fini;
6260 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD);
6261 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt);
6262 llvm::Value *FiniAddr = Fini
6263 ? CGF.EmitCastToVoidPtr(Fini)
6264 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy);
6265 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal);
6266 // ElemLVal.reduce_comb = comb;
6267 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD);
6268 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction(
6269 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt],
6270 RHSExprs[Cnt], Data.ReductionCopies[Cnt]));
6271 CGF.EmitStoreOfScalar(CombAddr, CombLVal);
6272 // ElemLVal.flags = 0;
6273 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD);
6274 if (DelayedCreation) {
6275 CGF.EmitStoreOfScalar(
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006276 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006277 FlagsLVal);
6278 } else
Akira Hatanakaf139ae32019-12-03 15:17:01 -08006279 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF),
6280 FlagsLVal.getType());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006281 }
6282 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void
6283 // *data);
6284 llvm::Value *Args[] = {
6285 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6286 /*isSigned=*/true),
6287 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true),
6288 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(),
6289 CGM.VoidPtrTy)};
6290 return CGF.EmitRuntimeCall(
6291 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args);
6292}
6293
6294void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
6295 SourceLocation Loc,
6296 ReductionCodeGen &RCG,
6297 unsigned N) {
6298 auto Sizes = RCG.getSizes(N);
6299 // Emit threadprivate global variable if the type is non-constant
6300 // (Sizes.second = nullptr).
6301 if (Sizes.second) {
6302 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy,
6303 /*isSigned=*/false);
6304 Address SizeAddr = getAddrOfArtificialThreadPrivate(
6305 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006306 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006307 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false);
6308 }
6309 // Store address of the original reduction item if custom initializer is used.
6310 if (RCG.usesReductionInitializer(N)) {
6311 Address SharedAddr = getAddrOfArtificialThreadPrivate(
6312 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006313 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006314 CGF.Builder.CreateStore(
6315 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08006316 RCG.getSharedLValue(N).getPointer(CGF), CGM.VoidPtrTy),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006317 SharedAddr, /*IsVolatile=*/false);
6318 }
6319}
6320
6321Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF,
6322 SourceLocation Loc,
6323 llvm::Value *ReductionsPtr,
6324 LValue SharedLVal) {
6325 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
6326 // *d);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08006327 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc),
6328 CGM.IntTy,
6329 /*isSigned=*/true),
6330 ReductionsPtr,
6331 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6332 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)};
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006333 return Address(
6334 CGF.EmitRuntimeCall(
6335 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args),
6336 SharedLVal.getAlignment());
6337}
6338
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006339void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
6340 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006341 if (!CGF.HaveInsertPoint())
6342 return;
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006343 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
6344 // global_tid);
6345 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
6346 // Ignore return result until untied tasks are supported.
6347 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00006348 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
6349 Region->emitUntiedSwitch(CGF);
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006350}
6351
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006352void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006353 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00006354 const RegionCodeGenTy &CodeGen,
6355 bool HasCancel) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006356 if (!CGF.HaveInsertPoint())
6357 return;
Alexey Bataev25e5b442015-09-15 12:52:43 +00006358 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006359 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00006360}
6361
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006362namespace {
6363enum RTCancelKind {
6364 CancelNoreq = 0,
6365 CancelParallel = 1,
6366 CancelLoop = 2,
6367 CancelSections = 3,
6368 CancelTaskgroup = 4
6369};
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00006370} // anonymous namespace
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006371
6372static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
6373 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00006374 if (CancelRegion == OMPD_parallel)
6375 CancelKind = CancelParallel;
6376 else if (CancelRegion == OMPD_for)
6377 CancelKind = CancelLoop;
6378 else if (CancelRegion == OMPD_sections)
6379 CancelKind = CancelSections;
6380 else {
6381 assert(CancelRegion == OMPD_taskgroup);
6382 CancelKind = CancelTaskgroup;
6383 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006384 return CancelKind;
6385}
6386
6387void CGOpenMPRuntime::emitCancellationPointCall(
6388 CodeGenFunction &CGF, SourceLocation Loc,
6389 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006390 if (!CGF.HaveInsertPoint())
6391 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006392 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
6393 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006394 if (auto *OMPRegionInfo =
6395 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Jonas Hahnfeldb07931f2017-02-17 18:32:58 +00006396 // For 'cancellation point taskgroup', the task region info may not have a
6397 // cancel. This may instead happen in another adjacent task.
6398 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006399 llvm::Value *Args[] = {
6400 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
6401 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006402 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006403 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006404 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
6405 // if (__kmpc_cancellationpoint()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006406 // exit from construct;
6407 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006408 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6409 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6410 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006411 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6412 CGF.EmitBlock(ExitBB);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006413 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006414 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev25e5b442015-09-15 12:52:43 +00006415 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006416 CGF.EmitBranchThroughCleanup(CancelDest);
6417 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6418 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006419 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006420}
6421
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006422void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00006423 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006424 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006425 if (!CGF.HaveInsertPoint())
6426 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006427 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
6428 // kmp_int32 cncl_kind);
6429 if (auto *OMPRegionInfo =
6430 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006431 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF,
6432 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006433 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev87933c72015-09-18 08:07:34 +00006434 llvm::Value *Args[] = {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006435 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
Alexey Bataev87933c72015-09-18 08:07:34 +00006436 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
6437 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006438 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006439 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
Alexey Bataev87933c72015-09-18 08:07:34 +00006440 // if (__kmpc_cancel()) {
Alexey Bataev87933c72015-09-18 08:07:34 +00006441 // exit from construct;
6442 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006443 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6444 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6445 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev87933c72015-09-18 08:07:34 +00006446 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6447 CGF.EmitBlock(ExitBB);
Alexey Bataev87933c72015-09-18 08:07:34 +00006448 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006449 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev87933c72015-09-18 08:07:34 +00006450 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6451 CGF.EmitBranchThroughCleanup(CancelDest);
6452 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6453 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006454 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -05006455 emitIfClause(CGF, IfCond, ThenGen,
6456 [](CodeGenFunction &, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006457 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006458 RegionCodeGenTy ThenRCG(ThenGen);
6459 ThenRCG(CGF);
6460 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006461 }
6462}
Samuel Antaobed3c462015-10-02 16:14:20 +00006463
Samuel Antaoee8fb302016-01-06 13:42:12 +00006464void CGOpenMPRuntime::emitTargetOutlinedFunction(
6465 const OMPExecutableDirective &D, StringRef ParentName,
6466 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006467 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00006468 assert(!ParentName.empty() && "Invalid target region parent name!");
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00006469 HasEmittedTargetRegion = true;
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006470 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
6471 IsOffloadEntry, CodeGen);
6472}
6473
6474void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
6475 const OMPExecutableDirective &D, StringRef ParentName,
6476 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6477 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antao2de62b02016-02-13 23:35:10 +00006478 // Create a unique name for the entry function using the source location
6479 // information of the current target region. The name will be something like:
Samuel Antaoee8fb302016-01-06 13:42:12 +00006480 //
Samuel Antao2de62b02016-02-13 23:35:10 +00006481 // __omp_offloading_DD_FFFF_PP_lBB
Samuel Antaoee8fb302016-01-06 13:42:12 +00006482 //
6483 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
Samuel Antao2de62b02016-02-13 23:35:10 +00006484 // mangled name of the function that encloses the target region and BB is the
6485 // line number of the target region.
Samuel Antaoee8fb302016-01-06 13:42:12 +00006486
6487 unsigned DeviceID;
6488 unsigned FileID;
6489 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00006490 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00006491 Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006492 SmallString<64> EntryFnName;
6493 {
6494 llvm::raw_svector_ostream OS(EntryFnName);
Samuel Antao2de62b02016-02-13 23:35:10 +00006495 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
6496 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00006497 }
6498
Alexey Bataev475a7442018-01-12 19:39:11 +00006499 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006500
Samuel Antaobed3c462015-10-02 16:14:20 +00006501 CodeGenFunction CGF(CGM, true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006502 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
Samuel Antaobed3c462015-10-02 16:14:20 +00006503 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006504
Alexey Bataevc33ba8c2020-01-17 14:05:40 -05006505 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS, D.getBeginLoc());
Samuel Antaoee8fb302016-01-06 13:42:12 +00006506
6507 // If this target outline function is not an offload entry, we don't need to
6508 // register it.
6509 if (!IsOffloadEntry)
6510 return;
6511
6512 // The target region ID is used by the runtime library to identify the current
6513 // target region, so it only has to be unique and not necessarily point to
6514 // anything. It could be the pointer to the outlined function that implements
6515 // the target region, but we aren't using that so that the compiler doesn't
6516 // need to keep that, and could therefore inline the host function if proven
6517 // worthwhile during optimization. In the other hand, if emitting code for the
6518 // device, the ID has to be the function address so that it can retrieved from
6519 // the offloading entry and launched by the runtime library. We also mark the
6520 // outlined function to have external linkage in case we are emitting code for
6521 // the device, because these functions will be entry points to the device.
6522
6523 if (CGM.getLangOpts().OpenMPIsDevice) {
6524 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
Alexey Bataev9a700172018-05-08 14:16:57 +00006525 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Rafael Espindolacbca4872018-01-11 22:15:12 +00006526 OutlinedFn->setDSOLocal(false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006527 } else {
Alexey Bataevc15ea702018-05-09 18:02:37 +00006528 std::string Name = getName({EntryFnName, "region_id"});
Samuel Antaoee8fb302016-01-06 13:42:12 +00006529 OutlinedFnID = new llvm::GlobalVariable(
6530 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
Alexey Bataev9a700172018-05-08 14:16:57 +00006531 llvm::GlobalValue::WeakAnyLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006532 llvm::Constant::getNullValue(CGM.Int8Ty), Name);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006533 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00006534
6535 // Register the information for the entry associated with this target region.
6536 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
Samuel Antaof83efdb2017-01-05 16:02:49 +00006537 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID,
Alexey Bataev03f270c2018-03-30 18:31:07 +00006538 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion);
Samuel Antaobed3c462015-10-02 16:14:20 +00006539}
6540
Alexey Bataev5c427362019-04-10 19:11:33 +00006541/// Checks if the expression is constant or does not have non-trivial function
6542/// calls.
6543static bool isTrivial(ASTContext &Ctx, const Expr * E) {
6544 // We can skip constant expressions.
6545 // We can skip expressions with trivial calls or simple expressions.
6546 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) ||
6547 !E->hasNonTrivialCall(Ctx)) &&
6548 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true);
6549}
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006550
Alexey Bataev5c427362019-04-10 19:11:33 +00006551const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx,
6552 const Stmt *Body) {
6553 const Stmt *Child = Body->IgnoreContainers();
6554 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) {
6555 Child = nullptr;
6556 for (const Stmt *S : C->body()) {
6557 if (const auto *E = dyn_cast<Expr>(S)) {
6558 if (isTrivial(Ctx, E))
6559 continue;
6560 }
6561 // Some of the statements can be ignored.
6562 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) ||
6563 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S))
6564 continue;
6565 // Analyze declarations.
6566 if (const auto *DS = dyn_cast<DeclStmt>(S)) {
6567 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) {
6568 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6569 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6570 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6571 isa<UsingDirectiveDecl>(D) ||
6572 isa<OMPDeclareReductionDecl>(D) ||
6573 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6574 return true;
6575 const auto *VD = dyn_cast<VarDecl>(D);
6576 if (!VD)
6577 return false;
6578 return VD->isConstexpr() ||
6579 ((VD->getType().isTrivialType(Ctx) ||
6580 VD->getType()->isReferenceType()) &&
6581 (!VD->hasInit() || isTrivial(Ctx, VD->getInit())));
6582 }))
6583 continue;
6584 }
6585 // Found multiple children - cannot get the one child only.
6586 if (Child)
6587 return nullptr;
6588 Child = S;
6589 }
6590 if (Child)
6591 Child = Child->IgnoreContainers();
6592 }
6593 return Child;
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006594}
6595
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006596/// Emit the number of teams for a target directive. Inspect the num_teams
6597/// clause associated with a teams construct combined or closely nested
6598/// with the target directive.
6599///
6600/// Emit a team of size one for directives such as 'target parallel' that
6601/// have no associated teams construct.
6602///
6603/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006604static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006605emitNumTeamsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006606 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006607 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6608 "Clauses associated with the teams directive expected to be emitted "
6609 "only for the host!");
6610 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6611 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6612 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006613 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006614 switch (DirectiveKind) {
6615 case OMPD_target: {
6616 const auto *CS = D.getInnermostCapturedStmt();
6617 const auto *Body =
6618 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
6619 const Stmt *ChildStmt =
6620 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body);
6621 if (const auto *NestedDir =
6622 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6623 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) {
6624 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) {
6625 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6626 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6627 const Expr *NumTeams =
6628 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6629 llvm::Value *NumTeamsVal =
6630 CGF.EmitScalarExpr(NumTeams,
6631 /*IgnoreResultAssign*/ true);
6632 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006633 /*isSigned=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00006634 }
6635 return Bld.getInt32(0);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006636 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006637 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) ||
6638 isOpenMPSimdDirective(NestedDir->getDirectiveKind()))
6639 return Bld.getInt32(1);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006640 return Bld.getInt32(0);
6641 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006642 return nullptr;
Samuel Antaob68e2db2016-03-03 16:20:23 +00006643 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006644 case OMPD_target_teams:
6645 case OMPD_target_teams_distribute:
6646 case OMPD_target_teams_distribute_simd:
6647 case OMPD_target_teams_distribute_parallel_for:
6648 case OMPD_target_teams_distribute_parallel_for_simd: {
6649 if (D.hasClausesOfKind<OMPNumTeamsClause>()) {
6650 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF);
6651 const Expr *NumTeams =
6652 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6653 llvm::Value *NumTeamsVal =
6654 CGF.EmitScalarExpr(NumTeams,
6655 /*IgnoreResultAssign*/ true);
6656 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006657 /*isSigned=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00006658 }
6659 return Bld.getInt32(0);
6660 }
6661 case OMPD_target_parallel:
6662 case OMPD_target_parallel_for:
6663 case OMPD_target_parallel_for_simd:
6664 case OMPD_target_simd:
6665 return Bld.getInt32(1);
6666 case OMPD_parallel:
6667 case OMPD_for:
6668 case OMPD_parallel_for:
cchen47d60942019-12-05 13:43:48 -05006669 case OMPD_parallel_master:
Alexey Bataev5c427362019-04-10 19:11:33 +00006670 case OMPD_parallel_sections:
6671 case OMPD_for_simd:
6672 case OMPD_parallel_for_simd:
6673 case OMPD_cancel:
6674 case OMPD_cancellation_point:
6675 case OMPD_ordered:
6676 case OMPD_threadprivate:
6677 case OMPD_allocate:
6678 case OMPD_task:
6679 case OMPD_simd:
6680 case OMPD_sections:
6681 case OMPD_section:
6682 case OMPD_single:
6683 case OMPD_master:
6684 case OMPD_critical:
6685 case OMPD_taskyield:
6686 case OMPD_barrier:
6687 case OMPD_taskwait:
6688 case OMPD_taskgroup:
6689 case OMPD_atomic:
6690 case OMPD_flush:
6691 case OMPD_teams:
6692 case OMPD_target_data:
6693 case OMPD_target_exit_data:
6694 case OMPD_target_enter_data:
6695 case OMPD_distribute:
6696 case OMPD_distribute_simd:
6697 case OMPD_distribute_parallel_for:
6698 case OMPD_distribute_parallel_for_simd:
6699 case OMPD_teams_distribute:
6700 case OMPD_teams_distribute_simd:
6701 case OMPD_teams_distribute_parallel_for:
6702 case OMPD_teams_distribute_parallel_for_simd:
6703 case OMPD_target_update:
6704 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00006705 case OMPD_declare_variant:
Alexey Bataev5c427362019-04-10 19:11:33 +00006706 case OMPD_declare_target:
6707 case OMPD_end_declare_target:
6708 case OMPD_declare_reduction:
6709 case OMPD_declare_mapper:
6710 case OMPD_taskloop:
6711 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00006712 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00006713 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00006714 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04006715 case OMPD_parallel_master_taskloop_simd:
Alexey Bataev5c427362019-04-10 19:11:33 +00006716 case OMPD_requires:
6717 case OMPD_unknown:
6718 break;
6719 }
6720 llvm_unreachable("Unexpected directive kind.");
6721}
Samuel Antaob68e2db2016-03-03 16:20:23 +00006722
Alexey Bataev5c427362019-04-10 19:11:33 +00006723static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS,
6724 llvm::Value *DefaultThreadLimitVal) {
6725 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6726 CGF.getContext(), CS->getCapturedStmt());
6727 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6728 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) {
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006729 llvm::Value *NumThreads = nullptr;
6730 llvm::Value *CondVal = nullptr;
6731 // Handle if clause. If if clause present, the number of threads is
6732 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6733 if (Dir->hasClausesOfKind<OMPIfClause>()) {
6734 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6735 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6736 const OMPIfClause *IfClause = nullptr;
6737 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) {
6738 if (C->getNameModifier() == OMPD_unknown ||
6739 C->getNameModifier() == OMPD_parallel) {
6740 IfClause = C;
6741 break;
6742 }
6743 }
6744 if (IfClause) {
6745 const Expr *Cond = IfClause->getCondition();
6746 bool Result;
6747 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6748 if (!Result)
6749 return CGF.Builder.getInt32(1);
6750 } else {
6751 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange());
6752 if (const auto *PreInit =
6753 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) {
6754 for (const auto *I : PreInit->decls()) {
6755 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6756 CGF.EmitVarDecl(cast<VarDecl>(*I));
6757 } else {
6758 CodeGenFunction::AutoVarEmission Emission =
6759 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6760 CGF.EmitAutoVarCleanups(Emission);
6761 }
6762 }
6763 }
6764 CondVal = CGF.EvaluateExprAsBool(Cond);
6765 }
6766 }
6767 }
6768 // Check the value of num_threads clause iff if clause was not specified
6769 // or is not evaluated to false.
Alexey Bataev5c427362019-04-10 19:11:33 +00006770 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) {
6771 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6772 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6773 const auto *NumThreadsClause =
6774 Dir->getSingleClause<OMPNumThreadsClause>();
6775 CodeGenFunction::LexicalScope Scope(
6776 CGF, NumThreadsClause->getNumThreads()->getSourceRange());
6777 if (const auto *PreInit =
6778 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6779 for (const auto *I : PreInit->decls()) {
6780 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6781 CGF.EmitVarDecl(cast<VarDecl>(*I));
6782 } else {
6783 CodeGenFunction::AutoVarEmission Emission =
6784 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6785 CGF.EmitAutoVarCleanups(Emission);
6786 }
6787 }
6788 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006789 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads());
Alexey Bataev5c427362019-04-10 19:11:33 +00006790 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006791 /*isSigned=*/false);
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006792 if (DefaultThreadLimitVal)
6793 NumThreads = CGF.Builder.CreateSelect(
6794 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads),
6795 DefaultThreadLimitVal, NumThreads);
6796 } else {
6797 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal
6798 : CGF.Builder.getInt32(0);
Alexey Bataev5c427362019-04-10 19:11:33 +00006799 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006800 // Process condition of the if clause.
6801 if (CondVal) {
6802 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads,
6803 CGF.Builder.getInt32(1));
6804 }
6805 return NumThreads;
Alexey Bataev5c427362019-04-10 19:11:33 +00006806 }
6807 if (isOpenMPSimdDirective(Dir->getDirectiveKind()))
6808 return CGF.Builder.getInt32(1);
6809 return DefaultThreadLimitVal;
6810 }
6811 return DefaultThreadLimitVal ? DefaultThreadLimitVal
6812 : CGF.Builder.getInt32(0);
Samuel Antaob68e2db2016-03-03 16:20:23 +00006813}
6814
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006815/// Emit the number of threads for a target directive. Inspect the
6816/// thread_limit clause associated with a teams construct combined or closely
6817/// nested with the target directive.
6818///
6819/// Emit the num_threads clause for directives such as 'target parallel' that
6820/// have no associated teams construct.
6821///
6822/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006823static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006824emitNumThreadsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006825 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006826 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6827 "Clauses associated with the teams directive expected to be emitted "
6828 "only for the host!");
6829 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6830 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6831 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006832 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006833 llvm::Value *ThreadLimitVal = nullptr;
6834 llvm::Value *NumThreadsVal = nullptr;
6835 switch (DirectiveKind) {
6836 case OMPD_target: {
6837 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6838 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6839 return NumThreads;
6840 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6841 CGF.getContext(), CS->getCapturedStmt());
6842 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6843 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) {
6844 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6845 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6846 const auto *ThreadLimitClause =
6847 Dir->getSingleClause<OMPThreadLimitClause>();
6848 CodeGenFunction::LexicalScope Scope(
6849 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange());
6850 if (const auto *PreInit =
6851 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6852 for (const auto *I : PreInit->decls()) {
6853 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6854 CGF.EmitVarDecl(cast<VarDecl>(*I));
6855 } else {
6856 CodeGenFunction::AutoVarEmission Emission =
6857 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6858 CGF.EmitAutoVarCleanups(Emission);
6859 }
6860 }
6861 }
6862 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6863 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6864 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006865 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006866 }
6867 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) &&
6868 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) {
6869 CS = Dir->getInnermostCapturedStmt();
6870 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6871 CGF.getContext(), CS->getCapturedStmt());
6872 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6873 }
6874 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) &&
6875 !isOpenMPSimdDirective(Dir->getDirectiveKind())) {
6876 CS = Dir->getInnermostCapturedStmt();
6877 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6878 return NumThreads;
6879 }
6880 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind()))
6881 return Bld.getInt32(1);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006882 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006883 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6884 }
6885 case OMPD_target_teams: {
6886 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6887 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6888 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6889 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6890 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6891 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006892 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006893 }
6894 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6895 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6896 return NumThreads;
6897 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6898 CGF.getContext(), CS->getCapturedStmt());
6899 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6900 if (Dir->getDirectiveKind() == OMPD_distribute) {
6901 CS = Dir->getInnermostCapturedStmt();
6902 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6903 return NumThreads;
6904 }
6905 }
6906 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6907 }
6908 case OMPD_target_teams_distribute:
6909 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6910 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6911 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6912 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6913 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6914 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006915 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006916 }
6917 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal);
6918 case OMPD_target_parallel:
6919 case OMPD_target_parallel_for:
6920 case OMPD_target_parallel_for_simd:
6921 case OMPD_target_teams_distribute_parallel_for:
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006922 case OMPD_target_teams_distribute_parallel_for_simd: {
6923 llvm::Value *CondVal = nullptr;
6924 // Handle if clause. If if clause present, the number of threads is
6925 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6926 if (D.hasClausesOfKind<OMPIfClause>()) {
6927 const OMPIfClause *IfClause = nullptr;
6928 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) {
6929 if (C->getNameModifier() == OMPD_unknown ||
6930 C->getNameModifier() == OMPD_parallel) {
6931 IfClause = C;
6932 break;
6933 }
6934 }
6935 if (IfClause) {
6936 const Expr *Cond = IfClause->getCondition();
6937 bool Result;
6938 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6939 if (!Result)
6940 return Bld.getInt32(1);
6941 } else {
6942 CodeGenFunction::RunCleanupsScope Scope(CGF);
6943 CondVal = CGF.EvaluateExprAsBool(Cond);
6944 }
6945 }
6946 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006947 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6948 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6949 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6950 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6951 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6952 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006953 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006954 }
6955 if (D.hasClausesOfKind<OMPNumThreadsClause>()) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006956 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
Alexey Bataev5c427362019-04-10 19:11:33 +00006957 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>();
6958 llvm::Value *NumThreads = CGF.EmitScalarExpr(
6959 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true);
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006960 NumThreadsVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006961 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006962 ThreadLimitVal = ThreadLimitVal
Alexey Bataev5c427362019-04-10 19:11:33 +00006963 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal,
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006964 ThreadLimitVal),
6965 NumThreadsVal, ThreadLimitVal)
6966 : NumThreadsVal;
Alexey Bataev50a1c782017-12-01 21:31:08 +00006967 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006968 if (!ThreadLimitVal)
6969 ThreadLimitVal = Bld.getInt32(0);
6970 if (CondVal)
6971 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1));
6972 return ThreadLimitVal;
6973 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006974 case OMPD_target_teams_distribute_simd:
6975 case OMPD_target_simd:
6976 return Bld.getInt32(1);
6977 case OMPD_parallel:
6978 case OMPD_for:
6979 case OMPD_parallel_for:
cchen47d60942019-12-05 13:43:48 -05006980 case OMPD_parallel_master:
Alexey Bataev5c427362019-04-10 19:11:33 +00006981 case OMPD_parallel_sections:
6982 case OMPD_for_simd:
6983 case OMPD_parallel_for_simd:
6984 case OMPD_cancel:
6985 case OMPD_cancellation_point:
6986 case OMPD_ordered:
6987 case OMPD_threadprivate:
6988 case OMPD_allocate:
6989 case OMPD_task:
6990 case OMPD_simd:
6991 case OMPD_sections:
6992 case OMPD_section:
6993 case OMPD_single:
6994 case OMPD_master:
6995 case OMPD_critical:
6996 case OMPD_taskyield:
6997 case OMPD_barrier:
6998 case OMPD_taskwait:
6999 case OMPD_taskgroup:
7000 case OMPD_atomic:
7001 case OMPD_flush:
7002 case OMPD_teams:
7003 case OMPD_target_data:
7004 case OMPD_target_exit_data:
7005 case OMPD_target_enter_data:
7006 case OMPD_distribute:
7007 case OMPD_distribute_simd:
7008 case OMPD_distribute_parallel_for:
7009 case OMPD_distribute_parallel_for_simd:
7010 case OMPD_teams_distribute:
7011 case OMPD_teams_distribute_simd:
7012 case OMPD_teams_distribute_parallel_for:
7013 case OMPD_teams_distribute_parallel_for_simd:
7014 case OMPD_target_update:
7015 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00007016 case OMPD_declare_variant:
Alexey Bataev5c427362019-04-10 19:11:33 +00007017 case OMPD_declare_target:
7018 case OMPD_end_declare_target:
7019 case OMPD_declare_reduction:
7020 case OMPD_declare_mapper:
7021 case OMPD_taskloop:
7022 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00007023 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00007024 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00007025 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04007026 case OMPD_parallel_master_taskloop_simd:
Alexey Bataev5c427362019-04-10 19:11:33 +00007027 case OMPD_requires:
7028 case OMPD_unknown:
7029 break;
Samuel Antaob68e2db2016-03-03 16:20:23 +00007030 }
Alexey Bataev5c427362019-04-10 19:11:33 +00007031 llvm_unreachable("Unsupported directive kind.");
Samuel Antaob68e2db2016-03-03 16:20:23 +00007032}
7033
Samuel Antao86ace552016-04-27 22:40:57 +00007034namespace {
Alexey Bataevb3638132018-07-19 16:34:13 +00007035LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
7036
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007037// Utility to handle information from clauses associated with a given
Samuel Antao86ace552016-04-27 22:40:57 +00007038// construct that use mappable expressions (e.g. 'map' clause, 'to' clause).
7039// It provides a convenient interface to obtain the information and generate
7040// code for that information.
7041class MappableExprsHandler {
7042public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007043 /// Values for bit flags used to specify the mapping type for
Samuel Antao86ace552016-04-27 22:40:57 +00007044 /// offloading.
Alexey Bataevb3638132018-07-19 16:34:13 +00007045 enum OpenMPOffloadMappingFlags : uint64_t {
7046 /// No flags
7047 OMP_MAP_NONE = 0x0,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007048 /// Allocate memory on the device and move data from host to device.
Samuel Antao86ace552016-04-27 22:40:57 +00007049 OMP_MAP_TO = 0x01,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007050 /// Allocate memory on the device and move data from device to host.
Samuel Antao86ace552016-04-27 22:40:57 +00007051 OMP_MAP_FROM = 0x02,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007052 /// Always perform the requested mapping action on the element, even
Samuel Antao86ace552016-04-27 22:40:57 +00007053 /// if it was already mapped before.
7054 OMP_MAP_ALWAYS = 0x04,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007055 /// Delete the element from the device environment, ignoring the
Samuel Antao86ace552016-04-27 22:40:57 +00007056 /// current reference count associated with the element.
Samuel Antao6782e942016-05-26 16:48:10 +00007057 OMP_MAP_DELETE = 0x08,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007058 /// The element being mapped is a pointer-pointee pair; both the
George Rokos065755d2017-11-07 18:27:04 +00007059 /// pointer and the pointee should be mapped.
7060 OMP_MAP_PTR_AND_OBJ = 0x10,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007061 /// This flags signals that the base address of an entry should be
George Rokos065755d2017-11-07 18:27:04 +00007062 /// passed to the target kernel as an argument.
7063 OMP_MAP_TARGET_PARAM = 0x20,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007064 /// Signal that the runtime library has to return the device pointer
George Rokos065755d2017-11-07 18:27:04 +00007065 /// in the current position for the data being mapped. Used when we have the
7066 /// use_device_ptr clause.
7067 OMP_MAP_RETURN_PARAM = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007068 /// This flag signals that the reference being passed is a pointer to
Samuel Antaod486f842016-05-26 16:53:38 +00007069 /// private data.
George Rokos065755d2017-11-07 18:27:04 +00007070 OMP_MAP_PRIVATE = 0x80,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007071 /// Pass the element to the device by value.
George Rokos065755d2017-11-07 18:27:04 +00007072 OMP_MAP_LITERAL = 0x100,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007073 /// Implicit map
7074 OMP_MAP_IMPLICIT = 0x200,
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007075 /// Close is a hint to the runtime to allocate memory close to
7076 /// the target device.
7077 OMP_MAP_CLOSE = 0x400,
Alexey Bataevb3638132018-07-19 16:34:13 +00007078 /// The 16 MSBs of the flags indicate whether the entry is member of some
7079 /// struct/class.
7080 OMP_MAP_MEMBER_OF = 0xffff000000000000,
7081 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF),
Samuel Antao86ace552016-04-27 22:40:57 +00007082 };
7083
Michael Krused47b9432019-08-05 18:43:21 +00007084 /// Get the offset of the OMP_MAP_MEMBER_OF field.
7085 static unsigned getFlagMemberOffset() {
7086 unsigned Offset = 0;
7087 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1);
7088 Remain = Remain >> 1)
7089 Offset++;
7090 return Offset;
7091 }
7092
Samuel Antaocc10b852016-07-28 14:23:26 +00007093 /// Class that associates information with a base pointer to be passed to the
7094 /// runtime library.
7095 class BasePointerInfo {
7096 /// The base pointer.
7097 llvm::Value *Ptr = nullptr;
7098 /// The base declaration that refers to this device pointer, or null if
7099 /// there is none.
7100 const ValueDecl *DevPtrDecl = nullptr;
7101
7102 public:
7103 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr)
7104 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {}
7105 llvm::Value *operator*() const { return Ptr; }
7106 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; }
7107 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; }
7108 };
7109
Alexey Bataevb3638132018-07-19 16:34:13 +00007110 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>;
7111 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>;
7112 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>;
7113
7114 /// Map between a struct and the its lowest & highest elements which have been
7115 /// mapped.
7116 /// [ValueDecl *] --> {LE(FieldIndex, Pointer),
7117 /// HE(FieldIndex, Pointer)}
7118 struct StructRangeInfoTy {
7119 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = {
7120 0, Address::invalid()};
7121 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = {
7122 0, Address::invalid()};
7123 Address Base = Address::invalid();
7124 };
Samuel Antao86ace552016-04-27 22:40:57 +00007125
7126private:
Alexey Bataevb3638132018-07-19 16:34:13 +00007127 /// Kind that defines how a device pointer has to be returned.
7128 struct MapInfo {
7129 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
7130 OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
Kelvin Lief579432018-12-18 22:18:41 +00007131 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataevb3638132018-07-19 16:34:13 +00007132 bool ReturnDevicePointer = false;
7133 bool IsImplicit = false;
7134
7135 MapInfo() = default;
7136 MapInfo(
7137 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Kelvin Lief579432018-12-18 22:18:41 +00007138 OpenMPMapClauseKind MapType,
7139 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007140 bool ReturnDevicePointer, bool IsImplicit)
Kelvin Lief579432018-12-18 22:18:41 +00007141 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
Alexey Bataevb3638132018-07-19 16:34:13 +00007142 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {}
7143 };
7144
7145 /// If use_device_ptr is used on a pointer which is a struct member and there
7146 /// is no map information about it, then emission of that entry is deferred
7147 /// until the whole struct has been processed.
7148 struct DeferredDevicePtrEntryTy {
7149 const Expr *IE = nullptr;
7150 const ValueDecl *VD = nullptr;
7151
7152 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD)
7153 : IE(IE), VD(VD) {}
7154 };
7155
Michael Krused47b9432019-08-05 18:43:21 +00007156 /// The target directive from where the mappable clauses were extracted. It
7157 /// is either a executable directive or a user-defined mapper directive.
7158 llvm::PointerUnion<const OMPExecutableDirective *,
7159 const OMPDeclareMapperDecl *>
7160 CurDir;
Samuel Antao86ace552016-04-27 22:40:57 +00007161
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007162 /// Function the directive is being generated for.
Samuel Antao86ace552016-04-27 22:40:57 +00007163 CodeGenFunction &CGF;
7164
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007165 /// Set of all first private variables in the current directive.
Alexey Bataevf288cf92019-06-27 18:53:07 +00007166 /// bool data is set to true if the variable is implicitly marked as
7167 /// firstprivate, false otherwise.
7168 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls;
Samuel Antaod486f842016-05-26 16:53:38 +00007169
Samuel Antao6890b092016-07-28 14:25:09 +00007170 /// Map between device pointer declarations and their expression components.
7171 /// The key value for declarations in 'this' is null.
7172 llvm::DenseMap<
7173 const ValueDecl *,
7174 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7175 DevPointersMap;
7176
Samuel Antao86ace552016-04-27 22:40:57 +00007177 llvm::Value *getExprTypeSize(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007178 QualType ExprTy = E->getType().getCanonicalType();
Samuel Antao86ace552016-04-27 22:40:57 +00007179
7180 // Reference types are ignored for mapping purposes.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007181 if (const auto *RefTy = ExprTy->getAs<ReferenceType>())
Samuel Antao86ace552016-04-27 22:40:57 +00007182 ExprTy = RefTy->getPointeeType().getCanonicalType();
7183
7184 // Given that an array section is considered a built-in type, we need to
7185 // do the calculation based on the length of the section instead of relying
7186 // on CGF.getTypeSize(E->getType()).
7187 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) {
7188 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType(
7189 OAE->getBase()->IgnoreParenImpCasts())
7190 .getCanonicalType();
7191
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007192 // If there is no length associated with the expression and lower bound is
7193 // not specified too, that means we are using the whole length of the
7194 // base.
7195 if (!OAE->getLength() && OAE->getColonLoc().isValid() &&
7196 !OAE->getLowerBound())
Samuel Antao86ace552016-04-27 22:40:57 +00007197 return CGF.getTypeSize(BaseTy);
7198
7199 llvm::Value *ElemSize;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007200 if (const auto *PTy = BaseTy->getAs<PointerType>()) {
Samuel Antao86ace552016-04-27 22:40:57 +00007201 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007202 } else {
7203 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr());
Samuel Antao86ace552016-04-27 22:40:57 +00007204 assert(ATy && "Expecting array type if not a pointer type.");
7205 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType());
7206 }
7207
7208 // If we don't have a length at this point, that is because we have an
7209 // array section with a single element.
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007210 if (!OAE->getLength() && OAE->getColonLoc().isInvalid())
Samuel Antao86ace552016-04-27 22:40:57 +00007211 return ElemSize;
7212
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007213 if (const Expr *LenExpr = OAE->getLength()) {
Michael Liaod838cf72019-10-02 00:22:45 +00007214 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr);
7215 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(),
7216 CGF.getContext().getSizeType(),
7217 LenExpr->getExprLoc());
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007218 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize);
7219 }
7220 assert(!OAE->getLength() && OAE->getColonLoc().isValid() &&
7221 OAE->getLowerBound() && "expected array_section[lb:].");
7222 // Size = sizetype - lb * elemtype;
7223 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy);
7224 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound());
7225 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(),
7226 CGF.getContext().getSizeType(),
7227 OAE->getLowerBound()->getExprLoc());
7228 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize);
7229 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal);
7230 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal);
7231 LengthVal = CGF.Builder.CreateSelect(
7232 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0));
7233 return LengthVal;
Samuel Antao86ace552016-04-27 22:40:57 +00007234 }
7235 return CGF.getTypeSize(ExprTy);
7236 }
7237
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007238 /// Return the corresponding bits for a given map clause modifier. Add
Samuel Antao86ace552016-04-27 22:40:57 +00007239 /// a flag marking the map as a pointer if requested. Add a flag marking the
Samuel Antao6782e942016-05-26 16:48:10 +00007240 /// map as the first one of a series of maps that relate to the same map
7241 /// expression.
Kelvin Lief579432018-12-18 22:18:41 +00007242 OpenMPOffloadMappingFlags getMapTypeBits(
7243 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
7244 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const {
Alexey Bataevb3638132018-07-19 16:34:13 +00007245 OpenMPOffloadMappingFlags Bits =
7246 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE;
Samuel Antao86ace552016-04-27 22:40:57 +00007247 switch (MapType) {
7248 case OMPC_MAP_alloc:
Samuel Antao6782e942016-05-26 16:48:10 +00007249 case OMPC_MAP_release:
7250 // alloc and release is the default behavior in the runtime library, i.e.
7251 // if we don't pass any bits alloc/release that is what the runtime is
7252 // going to do. Therefore, we don't need to signal anything for these two
7253 // type modifiers.
Samuel Antao86ace552016-04-27 22:40:57 +00007254 break;
7255 case OMPC_MAP_to:
Alexey Bataevb3638132018-07-19 16:34:13 +00007256 Bits |= OMP_MAP_TO;
Samuel Antao86ace552016-04-27 22:40:57 +00007257 break;
7258 case OMPC_MAP_from:
Alexey Bataevb3638132018-07-19 16:34:13 +00007259 Bits |= OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007260 break;
7261 case OMPC_MAP_tofrom:
Alexey Bataevb3638132018-07-19 16:34:13 +00007262 Bits |= OMP_MAP_TO | OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007263 break;
7264 case OMPC_MAP_delete:
Alexey Bataevb3638132018-07-19 16:34:13 +00007265 Bits |= OMP_MAP_DELETE;
Samuel Antao86ace552016-04-27 22:40:57 +00007266 break;
Alexey Bataevb3638132018-07-19 16:34:13 +00007267 case OMPC_MAP_unknown:
Samuel Antao86ace552016-04-27 22:40:57 +00007268 llvm_unreachable("Unexpected map type!");
Samuel Antao86ace552016-04-27 22:40:57 +00007269 }
7270 if (AddPtrFlag)
George Rokos065755d2017-11-07 18:27:04 +00007271 Bits |= OMP_MAP_PTR_AND_OBJ;
7272 if (AddIsTargetParamFlag)
7273 Bits |= OMP_MAP_TARGET_PARAM;
Kelvin Lief579432018-12-18 22:18:41 +00007274 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always)
7275 != MapModifiers.end())
Samuel Antao86ace552016-04-27 22:40:57 +00007276 Bits |= OMP_MAP_ALWAYS;
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007277 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close)
7278 != MapModifiers.end())
7279 Bits |= OMP_MAP_CLOSE;
Samuel Antao86ace552016-04-27 22:40:57 +00007280 return Bits;
7281 }
7282
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007283 /// Return true if the provided expression is a final array section. A
Samuel Antao86ace552016-04-27 22:40:57 +00007284 /// final array section, is one whose length can't be proved to be one.
7285 bool isFinalArraySectionExpression(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007286 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
Samuel Antao86ace552016-04-27 22:40:57 +00007287
7288 // It is not an array section and therefore not a unity-size one.
7289 if (!OASE)
7290 return false;
7291
7292 // An array section with no colon always refer to a single element.
7293 if (OASE->getColonLoc().isInvalid())
7294 return false;
7295
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007296 const Expr *Length = OASE->getLength();
Samuel Antao86ace552016-04-27 22:40:57 +00007297
7298 // If we don't have a length we have to check if the array has size 1
7299 // for this dimension. Also, we should always expect a length if the
7300 // base type is pointer.
7301 if (!Length) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007302 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType(
7303 OASE->getBase()->IgnoreParenImpCasts())
7304 .getCanonicalType();
7305 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
Samuel Antao86ace552016-04-27 22:40:57 +00007306 return ATy->getSize().getSExtValue() != 1;
7307 // If we don't have a constant dimension length, we have to consider
7308 // the current section as having any size, so it is not necessarily
7309 // unitary. If it happen to be unity size, that's user fault.
7310 return true;
7311 }
7312
7313 // Check if the length evaluates to 1.
Fangrui Song407659a2018-11-30 23:41:18 +00007314 Expr::EvalResult Result;
7315 if (!Length->EvaluateAsInt(Result, CGF.getContext()))
Samuel Antao86ace552016-04-27 22:40:57 +00007316 return true; // Can have more that size 1.
7317
Fangrui Song407659a2018-11-30 23:41:18 +00007318 llvm::APSInt ConstLength = Result.Val.getInt();
Samuel Antao86ace552016-04-27 22:40:57 +00007319 return ConstLength.getSExtValue() != 1;
7320 }
7321
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007322 /// Generate the base pointers, section pointers, sizes and map type
Samuel Antao86ace552016-04-27 22:40:57 +00007323 /// bits for the provided map type, map modifier, and expression components.
7324 /// \a IsFirstComponent should be set to true if the provided set of
7325 /// components is the first associated with a capture.
7326 void generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00007327 OpenMPMapClauseKind MapType,
7328 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Samuel Antao86ace552016-04-27 22:40:57 +00007329 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Samuel Antaocc10b852016-07-28 14:23:26 +00007330 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007331 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
Alexey Bataevb3638132018-07-19 16:34:13 +00007332 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007333 bool IsImplicit,
7334 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7335 OverlappedElements = llvm::None) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007336 // The following summarizes what has to be generated for each map and the
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00007337 // types below. The generated information is expressed in this order:
Samuel Antao86ace552016-04-27 22:40:57 +00007338 // base pointer, section pointer, size, flags
7339 // (to add to the ones that come from the map type and modifier).
7340 //
7341 // double d;
7342 // int i[100];
7343 // float *p;
7344 //
7345 // struct S1 {
7346 // int i;
7347 // float f[50];
7348 // }
7349 // struct S2 {
7350 // int i;
7351 // float f[50];
7352 // S1 s;
7353 // double *p;
7354 // struct S2 *ps;
7355 // }
7356 // S2 s;
7357 // S2 *ps;
7358 //
7359 // map(d)
Alexey Bataevb3638132018-07-19 16:34:13 +00007360 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007361 //
7362 // map(i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007363 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007364 //
7365 // map(i[1:23])
Alexey Bataevb3638132018-07-19 16:34:13 +00007366 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007367 //
7368 // map(p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007369 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007370 //
7371 // map(p[1:24])
Alexey Bataevb3638132018-07-19 16:34:13 +00007372 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007373 //
7374 // map(s)
Alexey Bataevb3638132018-07-19 16:34:13 +00007375 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007376 //
7377 // map(s.i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007378 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007379 //
7380 // map(s.s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007381 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007382 //
7383 // map(s.p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007384 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007385 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007386 // map(to: s.p[:22])
7387 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*)
7388 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**)
7389 // &(s.p), &(s.p[0]), 22*sizeof(double),
7390 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***)
7391 // (*) alloc space for struct members, only this is a target parameter
7392 // (**) map the pointer (nothing to be mapped in this example) (the compiler
7393 // optimizes this entry out, same in the examples below)
7394 // (***) map the pointee (map: to)
Samuel Antao86ace552016-04-27 22:40:57 +00007395 //
7396 // map(s.ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007397 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007398 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007399 // map(from: s.ps->s.i)
7400 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7401 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7402 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007403 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007404 // map(to: s.ps->ps)
7405 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7406 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7407 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007408 //
7409 // map(s.ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007410 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7411 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7412 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7413 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007414 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007415 // map(to: s.ps->ps->s.f[:22])
7416 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7417 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7418 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7419 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007420 //
7421 // map(ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007422 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007423 //
7424 // map(ps->i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007425 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007426 //
7427 // map(ps->s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007428 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007429 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007430 // map(from: ps->p)
7431 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007432 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007433 // map(to: ps->p[:22])
7434 // ps, &(ps->p), sizeof(double*), TARGET_PARAM
7435 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1)
7436 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007437 //
7438 // map(ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007439 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007440 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007441 // map(from: ps->ps->s.i)
7442 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7443 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7444 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007445 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007446 // map(from: ps->ps->ps)
7447 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7448 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7449 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007450 //
7451 // map(ps->ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007452 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7453 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7454 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7455 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007456 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007457 // map(to: ps->ps->ps->s.f[:22])
7458 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7459 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7460 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7461 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
7462 //
7463 // map(to: s.f[:22]) map(from: s.p[:33])
7464 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) +
7465 // sizeof(double*) (**), TARGET_PARAM
7466 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO
7467 // &s, &(s.p), sizeof(double*), MEMBER_OF(1)
7468 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7469 // (*) allocate contiguous space needed to fit all mapped members even if
7470 // we allocate space for members not mapped (in this example,
7471 // s.f[22..49] and s.s are not mapped, yet we must allocate space for
7472 // them as well because they fall between &s.f[0] and &s.p)
7473 //
7474 // map(from: s.f[:22]) map(to: ps->p[:33])
7475 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM
7476 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7477 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*)
7478 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO
7479 // (*) the struct this entry pertains to is the 2nd element in the list of
7480 // arguments, hence MEMBER_OF(2)
7481 //
7482 // map(from: s.f[:22], s.s) map(to: ps->p[:33])
7483 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM
7484 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM
7485 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM
7486 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7487 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*)
7488 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO
7489 // (*) the struct this entry pertains to is the 4th element in the list
7490 // of arguments, hence MEMBER_OF(4)
Samuel Antao86ace552016-04-27 22:40:57 +00007491
7492 // Track if the map information being generated is the first for a capture.
7493 bool IsCaptureFirstInfo = IsFirstComponentList;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007494 // When the variable is on a declare target link or in a to clause with
7495 // unified memory, a reference is needed to hold the host/device address
7496 // of the variable.
7497 bool RequiresReference = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007498
7499 // Scan the components from the base to the complete expression.
7500 auto CI = Components.rbegin();
7501 auto CE = Components.rend();
7502 auto I = CI;
7503
7504 // Track if the map information being generated is the first for a list of
7505 // components.
7506 bool IsExpressionFirstInfo = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00007507 Address BP = Address::invalid();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007508 const Expr *AssocExpr = I->getAssociatedExpression();
7509 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7510 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
Samuel Antao86ace552016-04-27 22:40:57 +00007511
Patrick Lystere13b1e32019-01-02 19:28:48 +00007512 if (isa<MemberExpr>(AssocExpr)) {
Samuel Antao86ace552016-04-27 22:40:57 +00007513 // The base is the 'this' pointer. The content of the pointer is going
7514 // to be the base of the field being mapped.
Alexey Bataevb3638132018-07-19 16:34:13 +00007515 BP = CGF.LoadCXXThisAddress();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007516 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7517 (OASE &&
7518 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08007519 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF);
Samuel Antao86ace552016-04-27 22:40:57 +00007520 } else {
7521 // The base is the reference to the variable.
7522 // BP = &Var.
Akira Hatanakaf139ae32019-12-03 15:17:01 -08007523 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF);
Alexey Bataev92327c52018-03-26 16:40:55 +00007524 if (const auto *VD =
7525 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7526 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007527 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7528 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7529 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
7530 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) {
7531 RequiresReference = true;
7532 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataev2c1dffe2018-04-16 20:34:41 +00007533 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007534 }
Alexey Bataev92327c52018-03-26 16:40:55 +00007535 }
Samuel Antao86ace552016-04-27 22:40:57 +00007536
7537 // If the variable is a pointer and is being dereferenced (i.e. is not
Nico Webera6916892016-06-10 18:53:04 +00007538 // the last component), the base has to be the pointer itself, not its
Samuel Antao403ffd42016-07-27 22:49:49 +00007539 // reference. References are ignored for mapping purposes.
7540 QualType Ty =
7541 I->getAssociatedDeclaration()->getType().getNonReferenceType();
7542 if (Ty->isAnyPointerType() && std::next(I) != CE) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007543 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
Samuel Antao86ace552016-04-27 22:40:57 +00007544
7545 // We do not need to generate individual map information for the
7546 // pointer, it can be associated with the combined storage.
7547 ++I;
7548 }
7549 }
7550
Alexey Bataevb3638132018-07-19 16:34:13 +00007551 // Track whether a component of the list should be marked as MEMBER_OF some
7552 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry
7553 // in a component list should be marked as MEMBER_OF, all subsequent entries
7554 // do not belong to the base struct. E.g.
7555 // struct S2 s;
7556 // s.ps->ps->ps->f[:]
7557 // (1) (2) (3) (4)
7558 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a
7559 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3)
7560 // is the pointee of ps(2) which is not member of struct s, so it should not
7561 // be marked as such (it is still PTR_AND_OBJ).
7562 // The variable is initialized to false so that PTR_AND_OBJ entries which
7563 // are not struct members are not considered (e.g. array of pointers to
7564 // data).
7565 bool ShouldBeMemberOf = false;
7566
7567 // Variable keeping track of whether or not we have encountered a component
7568 // in the component list which is a member expression. Useful when we have a
7569 // pointer or a final array section, in which case it is the previous
7570 // component in the list which tells us whether we have a member expression.
7571 // E.g. X.f[:]
7572 // While processing the final array section "[:]" it is "f" which tells us
7573 // whether we are dealing with a member of a declared struct.
7574 const MemberExpr *EncounteredME = nullptr;
7575
Samuel Antao86ace552016-04-27 22:40:57 +00007576 for (; I != CE; ++I) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007577 // If the current component is member of a struct (parent struct) mark it.
7578 if (!EncounteredME) {
7579 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7580 // If we encounter a PTR_AND_OBJ entry from now on it should be marked
7581 // as MEMBER_OF the parent struct.
7582 if (EncounteredME)
7583 ShouldBeMemberOf = true;
7584 }
7585
Samuel Antao86ace552016-04-27 22:40:57 +00007586 auto Next = std::next(I);
7587
7588 // We need to generate the addresses and sizes if this is the last
7589 // component, if the component is a pointer or if it is an array section
7590 // whose length can't be proved to be one. If this is a pointer, it
7591 // becomes the base address for the following components.
7592
7593 // A final array section, is one whose length can't be proved to be one.
7594 bool IsFinalArraySection =
7595 isFinalArraySectionExpression(I->getAssociatedExpression());
7596
7597 // Get information on whether the element is a pointer. Have to do a
7598 // special treatment for array sections given that they are built-in
7599 // types.
7600 const auto *OASE =
7601 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression());
7602 bool IsPointer =
Alexey Bataevb3638132018-07-19 16:34:13 +00007603 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE)
7604 .getCanonicalType()
7605 ->isAnyPointerType()) ||
Samuel Antao86ace552016-04-27 22:40:57 +00007606 I->getAssociatedExpression()->getType()->isAnyPointerType();
7607
7608 if (Next == CE || IsPointer || IsFinalArraySection) {
Samuel Antao86ace552016-04-27 22:40:57 +00007609 // If this is not the last component, we expect the pointer to be
7610 // associated with an array expression or member expression.
7611 assert((Next == CE ||
7612 isa<MemberExpr>(Next->getAssociatedExpression()) ||
7613 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||
7614 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) &&
7615 "Unexpected expression");
7616
Akira Hatanakaf139ae32019-12-03 15:17:01 -08007617 Address LB = CGF.EmitOMPSharedLValue(I->getAssociatedExpression())
7618 .getAddress(CGF);
Samuel Antao86ace552016-04-27 22:40:57 +00007619
Alexey Bataevb3638132018-07-19 16:34:13 +00007620 // If this component is a pointer inside the base struct then we don't
7621 // need to create any entry for it - it will be combined with the object
7622 // it is pointing to into a single PTR_AND_OBJ entry.
7623 bool IsMemberPointer =
7624 IsPointer && EncounteredME &&
7625 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) ==
7626 EncounteredME);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007627 if (!OverlappedElements.empty()) {
7628 // Handle base element with the info for overlapped elements.
7629 assert(!PartialStruct.Base.isValid() && "The base element is set.");
7630 assert(Next == CE &&
7631 "Expected last element for the overlapped elements.");
7632 assert(!IsPointer &&
7633 "Unexpected base element with the pointer type.");
7634 // Mark the whole struct as the struct that requires allocation on the
7635 // device.
7636 PartialStruct.LowestElem = {0, LB};
7637 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(
7638 I->getAssociatedExpression()->getType());
7639 Address HB = CGF.Builder.CreateConstGEP(
7640 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB,
7641 CGF.VoidPtrTy),
James Y Knight751fe282019-02-09 22:22:28 +00007642 TypeSize.getQuantity() - 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007643 PartialStruct.HighestElem = {
7644 std::numeric_limits<decltype(
7645 PartialStruct.HighestElem.first)>::max(),
7646 HB};
7647 PartialStruct.Base = BP;
7648 // Emit data for non-overlapped data.
7649 OpenMPOffloadMappingFlags Flags =
7650 OMP_MAP_MEMBER_OF |
Kelvin Lief579432018-12-18 22:18:41 +00007651 getMapTypeBits(MapType, MapModifiers, IsImplicit,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007652 /*AddPtrFlag=*/false,
7653 /*AddIsTargetParamFlag=*/false);
7654 LB = BP;
7655 llvm::Value *Size = nullptr;
7656 // Do bitcopy of all non-overlapped structure elements.
7657 for (OMPClauseMappableExprCommon::MappableExprComponentListRef
7658 Component : OverlappedElements) {
7659 Address ComponentLB = Address::invalid();
7660 for (const OMPClauseMappableExprCommon::MappableComponent &MC :
7661 Component) {
7662 if (MC.getAssociatedDeclaration()) {
7663 ComponentLB =
7664 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
Akira Hatanakaf139ae32019-12-03 15:17:01 -08007665 .getAddress(CGF);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007666 Size = CGF.Builder.CreatePtrDiff(
7667 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()),
7668 CGF.EmitCastToVoidPtr(LB.getPointer()));
7669 break;
7670 }
7671 }
7672 BasePointers.push_back(BP.getPointer());
7673 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007674 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty,
7675 /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007676 Types.push_back(Flags);
James Y Knight751fe282019-02-09 22:22:28 +00007677 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007678 }
7679 BasePointers.push_back(BP.getPointer());
7680 Pointers.push_back(LB.getPointer());
7681 Size = CGF.Builder.CreatePtrDiff(
7682 CGF.EmitCastToVoidPtr(
James Y Knight751fe282019-02-09 22:22:28 +00007683 CGF.Builder.CreateConstGEP(HB, 1).getPointer()),
Alexey Bataeve82445f2018-09-20 13:54:02 +00007684 CGF.EmitCastToVoidPtr(LB.getPointer()));
Alexey Bataeva90fc662019-06-25 16:00:43 +00007685 Sizes.push_back(
7686 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007687 Types.push_back(Flags);
7688 break;
7689 }
7690 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
Alexey Bataevb3638132018-07-19 16:34:13 +00007691 if (!IsMemberPointer) {
7692 BasePointers.push_back(BP.getPointer());
7693 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007694 Sizes.push_back(
7695 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Samuel Antao03a3cec2016-07-27 22:52:16 +00007696
Alexey Bataevb3638132018-07-19 16:34:13 +00007697 // We need to add a pointer flag for each map that comes from the
7698 // same expression except for the first one. We also need to signal
7699 // this map is the first one that relates with the current capture
7700 // (there is a set of entries for each capture).
7701 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
Kelvin Lief579432018-12-18 22:18:41 +00007702 MapType, MapModifiers, IsImplicit,
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007703 !IsExpressionFirstInfo || RequiresReference,
7704 IsCaptureFirstInfo && !RequiresReference);
Alexey Bataevb3638132018-07-19 16:34:13 +00007705
7706 if (!IsExpressionFirstInfo) {
7707 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007708 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags.
Alexey Bataevb3638132018-07-19 16:34:13 +00007709 if (IsPointer)
7710 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS |
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007711 OMP_MAP_DELETE | OMP_MAP_CLOSE);
Alexey Bataevb3638132018-07-19 16:34:13 +00007712
7713 if (ShouldBeMemberOf) {
7714 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag
7715 // should be later updated with the correct value of MEMBER_OF.
7716 Flags |= OMP_MAP_MEMBER_OF;
7717 // From now on, all subsequent PTR_AND_OBJ entries should not be
7718 // marked as MEMBER_OF.
7719 ShouldBeMemberOf = false;
7720 }
7721 }
7722
7723 Types.push_back(Flags);
Samuel Antao03a3cec2016-07-27 22:52:16 +00007724 }
7725
Alexey Bataevb3638132018-07-19 16:34:13 +00007726 // If we have encountered a member expression so far, keep track of the
7727 // mapped member. If the parent is "*this", then the value declaration
7728 // is nullptr.
7729 if (EncounteredME) {
7730 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl());
7731 unsigned FieldIndex = FD->getFieldIndex();
Samuel Antao03a3cec2016-07-27 22:52:16 +00007732
Alexey Bataevb3638132018-07-19 16:34:13 +00007733 // Update info about the lowest and highest elements for this struct
7734 if (!PartialStruct.Base.isValid()) {
7735 PartialStruct.LowestElem = {FieldIndex, LB};
7736 PartialStruct.HighestElem = {FieldIndex, LB};
7737 PartialStruct.Base = BP;
7738 } else if (FieldIndex < PartialStruct.LowestElem.first) {
7739 PartialStruct.LowestElem = {FieldIndex, LB};
7740 } else if (FieldIndex > PartialStruct.HighestElem.first) {
7741 PartialStruct.HighestElem = {FieldIndex, LB};
7742 }
7743 }
Samuel Antao86ace552016-04-27 22:40:57 +00007744
7745 // If we have a final array section, we are done with this expression.
7746 if (IsFinalArraySection)
7747 break;
7748
7749 // The pointer becomes the base for the next element.
7750 if (Next != CE)
7751 BP = LB;
7752
7753 IsExpressionFirstInfo = false;
7754 IsCaptureFirstInfo = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007755 }
7756 }
7757 }
7758
Alexey Bataevb3638132018-07-19 16:34:13 +00007759 /// Return the adjusted map modifiers if the declaration a capture refers to
7760 /// appears in a first-private clause. This is expected to be used only with
7761 /// directives that start with 'target'.
7762 MappableExprsHandler::OpenMPOffloadMappingFlags
7763 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const {
7764 assert(Cap.capturesVariable() && "Expected capture by reference only!");
7765
7766 // A first private variable captured by reference will use only the
7767 // 'private ptr' and 'map to' flag. Return the right flags if the captured
7768 // declaration is known as first-private in this handler.
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007769 if (FirstPrivateDecls.count(Cap.getCapturedVar())) {
7770 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) &&
7771 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef)
7772 return MappableExprsHandler::OMP_MAP_ALWAYS |
7773 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataevc2b831f2019-04-02 16:03:40 +00007774 if (Cap.getCapturedVar()->getType()->isAnyPointerType())
7775 return MappableExprsHandler::OMP_MAP_TO |
7776 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ;
Alexey Bataevb3638132018-07-19 16:34:13 +00007777 return MappableExprsHandler::OMP_MAP_PRIVATE |
7778 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007779 }
Alexey Bataevb3638132018-07-19 16:34:13 +00007780 return MappableExprsHandler::OMP_MAP_TO |
7781 MappableExprsHandler::OMP_MAP_FROM;
7782 }
7783
7784 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) {
Michael Krused47b9432019-08-05 18:43:21 +00007785 // Rotate by getFlagMemberOffset() bits.
Alexey Bataevb3638132018-07-19 16:34:13 +00007786 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1)
Michael Krused47b9432019-08-05 18:43:21 +00007787 << getFlagMemberOffset());
Alexey Bataevb3638132018-07-19 16:34:13 +00007788 }
7789
7790 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags,
7791 OpenMPOffloadMappingFlags MemberOfFlag) {
7792 // If the entry is PTR_AND_OBJ but has not been marked with the special
7793 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be
7794 // marked as MEMBER_OF.
7795 if ((Flags & OMP_MAP_PTR_AND_OBJ) &&
7796 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF))
7797 return;
7798
7799 // Reset the placeholder value to prepare the flag for the assignment of the
7800 // proper MEMBER_OF value.
7801 Flags &= ~OMP_MAP_MEMBER_OF;
7802 Flags |= MemberOfFlag;
7803 }
7804
Alexey Bataeve82445f2018-09-20 13:54:02 +00007805 void getPlainLayout(const CXXRecordDecl *RD,
7806 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
7807 bool AsBase) const {
7808 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD);
7809
7810 llvm::StructType *St =
7811 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType();
7812
7813 unsigned NumElements = St->getNumElements();
7814 llvm::SmallVector<
7815 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
7816 RecordLayout(NumElements);
7817
7818 // Fill bases.
7819 for (const auto &I : RD->bases()) {
7820 if (I.isVirtual())
7821 continue;
7822 const auto *Base = I.getType()->getAsCXXRecordDecl();
7823 // Ignore empty bases.
7824 if (Base->isEmpty() || CGF.getContext()
7825 .getASTRecordLayout(Base)
7826 .getNonVirtualSize()
7827 .isZero())
7828 continue;
7829
7830 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
7831 RecordLayout[FieldIndex] = Base;
7832 }
7833 // Fill in virtual bases.
7834 for (const auto &I : RD->vbases()) {
7835 const auto *Base = I.getType()->getAsCXXRecordDecl();
7836 // Ignore empty bases.
7837 if (Base->isEmpty())
7838 continue;
7839 unsigned FieldIndex = RL.getVirtualBaseIndex(Base);
7840 if (RecordLayout[FieldIndex])
7841 continue;
7842 RecordLayout[FieldIndex] = Base;
7843 }
7844 // Fill in all the fields.
7845 assert(!RD->isUnion() && "Unexpected union.");
7846 for (const auto *Field : RD->fields()) {
7847 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
7848 // will fill in later.)
Richard Smith78b239e2019-06-20 20:44:45 +00007849 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) {
Alexey Bataeve82445f2018-09-20 13:54:02 +00007850 unsigned FieldIndex = RL.getLLVMFieldNo(Field);
7851 RecordLayout[FieldIndex] = Field;
7852 }
7853 }
7854 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
7855 &Data : RecordLayout) {
7856 if (Data.isNull())
7857 continue;
7858 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>())
7859 getPlainLayout(Base, Layout, /*AsBase=*/true);
7860 else
7861 Layout.push_back(Data.get<const FieldDecl *>());
7862 }
7863 }
7864
Alexey Bataevb3638132018-07-19 16:34:13 +00007865public:
7866 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
Michael Krused47b9432019-08-05 18:43:21 +00007867 : CurDir(&Dir), CGF(CGF) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007868 // Extract firstprivate clause information.
7869 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>())
7870 for (const auto *D : C->varlists())
Alexey Bataevf288cf92019-06-27 18:53:07 +00007871 FirstPrivateDecls.try_emplace(
7872 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit());
Alexey Bataevb3638132018-07-19 16:34:13 +00007873 // Extract device pointer clause information.
7874 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
7875 for (auto L : C->component_lists())
7876 DevPointersMap[L.first].push_back(L.second);
7877 }
7878
Michael Krused47b9432019-08-05 18:43:21 +00007879 /// Constructor for the declare mapper directive.
7880 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF)
7881 : CurDir(&Dir), CGF(CGF) {}
7882
Alexey Bataevb3638132018-07-19 16:34:13 +00007883 /// Generate code for the combined entry if we have a partially mapped struct
7884 /// and take care of the mapping flags of the arguments corresponding to
7885 /// individual struct members.
7886 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers,
7887 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7888 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes,
7889 const StructRangeInfoTy &PartialStruct) const {
7890 // Base is the base of the struct
7891 BasePointers.push_back(PartialStruct.Base.getPointer());
7892 // Pointer is the address of the lowest element
7893 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer();
7894 Pointers.push_back(LB);
7895 // Size is (addr of {highest+1} element) - (addr of lowest element)
7896 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer();
7897 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1);
7898 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy);
7899 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy);
7900 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00007901 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00007902 /*isSigned=*/false);
Alexey Bataevb3638132018-07-19 16:34:13 +00007903 Sizes.push_back(Size);
7904 // Map type is always TARGET_PARAM
7905 Types.push_back(OMP_MAP_TARGET_PARAM);
7906 // Remove TARGET_PARAM flag from the first element
7907 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM;
7908
7909 // All other current entries will be MEMBER_OF the combined entry
7910 // (except for PTR_AND_OBJ entries which do not have a placeholder value
7911 // 0xFFFF in the MEMBER_OF field).
7912 OpenMPOffloadMappingFlags MemberOfFlag =
7913 getMemberOfFlag(BasePointers.size() - 1);
7914 for (auto &M : CurTypes)
7915 setCorrectMemberOfFlag(M, MemberOfFlag);
7916 }
7917
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007918 /// Generate all the base pointers, section pointers, sizes and map
Samuel Antaocc10b852016-07-28 14:23:26 +00007919 /// types for the extracted mappable expressions. Also, for each item that
7920 /// relates with a device pointer, a pair of the relevant declaration and
7921 /// index where it occurs is appended to the device pointers info array.
7922 void generateAllInfo(MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007923 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7924 MapFlagsArrayTy &Types) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007925 // We have to process the component lists that relate with the same
7926 // declaration in a single chunk so that we can generate the map flags
7927 // correctly. Therefore, we organize all lists in a map.
Alexey Bataev5d1c3f62017-06-27 15:46:42 +00007928 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
Samuel Antao8d2d7302016-05-26 18:30:22 +00007929
7930 // Helper function to fill the information map for the different supported
7931 // clauses.
Samuel Antaocc10b852016-07-28 14:23:26 +00007932 auto &&InfoGen = [&Info](
7933 const ValueDecl *D,
7934 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
Kelvin Lief579432018-12-18 22:18:41 +00007935 OpenMPMapClauseKind MapType,
7936 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007937 bool ReturnDevicePointer, bool IsImplicit) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007938 const ValueDecl *VD =
7939 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
Kelvin Lief579432018-12-18 22:18:41 +00007940 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007941 IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00007942 };
Samuel Antao8d2d7302016-05-26 18:30:22 +00007943
Michael Krused47b9432019-08-05 18:43:21 +00007944 assert(CurDir.is<const OMPExecutableDirective *>() &&
7945 "Expect a executable directive");
7946 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
7947 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>())
Mark de Wever51abceb2019-11-12 20:48:11 +01007948 for (const auto L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007949 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(),
Alexey Bataevb3638132018-07-19 16:34:13 +00007950 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007951 }
Michael Krused47b9432019-08-05 18:43:21 +00007952 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>())
Mark de Wever51abceb2019-11-12 20:48:11 +01007953 for (const auto L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007954 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007955 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007956 }
Michael Krused47b9432019-08-05 18:43:21 +00007957 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>())
Mark de Wever51abceb2019-11-12 20:48:11 +01007958 for (const auto L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007959 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007960 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007961 }
Samuel Antao86ace552016-04-27 22:40:57 +00007962
Samuel Antaocc10b852016-07-28 14:23:26 +00007963 // Look at the use_device_ptr clause information and mark the existing map
7964 // entries as such. If there is no map information for an entry in the
7965 // use_device_ptr list, we create one with map type 'alloc' and zero size
Alexey Bataevb3638132018-07-19 16:34:13 +00007966 // section. It is the user fault if that was not mapped before. If there is
7967 // no map information and the pointer is a struct member, then we defer the
7968 // emission of that entry until the whole struct has been processed.
7969 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>>
7970 DeferredInfo;
7971
Alexey Bataevb3638132018-07-19 16:34:13 +00007972 for (const auto *C :
Michael Krused47b9432019-08-05 18:43:21 +00007973 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) {
Mark de Wever51abceb2019-11-12 20:48:11 +01007974 for (const auto L : C->component_lists()) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007975 assert(!L.second.empty() && "Not expecting empty list of components!");
7976 const ValueDecl *VD = L.second.back().getAssociatedDeclaration();
7977 VD = cast<ValueDecl>(VD->getCanonicalDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007978 const Expr *IE = L.second.back().getAssociatedExpression();
Samuel Antaocc10b852016-07-28 14:23:26 +00007979 // If the first component is a member expression, we have to look into
7980 // 'this', which maps to null in the map of map information. Otherwise
7981 // look directly for the information.
7982 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
7983
7984 // We potentially have map information for this declaration already.
7985 // Look for the first set of components that refer to it.
7986 if (It != Info.end()) {
7987 auto CI = std::find_if(
7988 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) {
7989 return MI.Components.back().getAssociatedDeclaration() == VD;
7990 });
7991 // If we found a map entry, signal that the pointer has to be returned
7992 // and move on to the next declaration.
7993 if (CI != It->second.end()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007994 CI->ReturnDevicePointer = true;
Samuel Antaocc10b852016-07-28 14:23:26 +00007995 continue;
7996 }
7997 }
7998
7999 // We didn't find any match in our map information - generate a zero
Alexey Bataevb3638132018-07-19 16:34:13 +00008000 // size array section - if the pointer is a struct member we defer this
8001 // action until the whole struct has been processed.
Alexey Bataevb3638132018-07-19 16:34:13 +00008002 if (isa<MemberExpr>(IE)) {
8003 // Insert the pointer into Info to be processed by
8004 // generateInfoForComponentList. Because it is a member pointer
8005 // without a pointee, no entry will be generated for it, therefore
8006 // we need to generate one after the whole struct has been processed.
8007 // Nonetheless, generateInfoForComponentList must be called to take
8008 // the pointer into account for the calculation of the range of the
8009 // partial struct.
Kelvin Lief579432018-12-18 22:18:41 +00008010 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00008011 /*ReturnDevicePointer=*/false, C->isImplicit());
8012 DeferredInfo[nullptr].emplace_back(IE, VD);
8013 } else {
Michael Krused47b9432019-08-05 18:43:21 +00008014 llvm::Value *Ptr =
8015 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc());
Alexey Bataevb3638132018-07-19 16:34:13 +00008016 BasePointers.emplace_back(Ptr, VD);
8017 Pointers.push_back(Ptr);
Michael Krused47b9432019-08-05 18:43:21 +00008018 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00008019 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM);
8020 }
Samuel Antaocc10b852016-07-28 14:23:26 +00008021 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008022 }
Samuel Antaocc10b852016-07-28 14:23:26 +00008023
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008024 for (const auto &M : Info) {
Samuel Antao86ace552016-04-27 22:40:57 +00008025 // We need to know when we generate information for the first component
8026 // associated with a capture, because the mapping flags depend on it.
8027 bool IsFirstComponentList = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00008028
8029 // Temporary versions of arrays
8030 MapBaseValuesArrayTy CurBasePointers;
8031 MapValuesArrayTy CurPointers;
8032 MapValuesArrayTy CurSizes;
8033 MapFlagsArrayTy CurTypes;
8034 StructRangeInfoTy PartialStruct;
8035
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008036 for (const MapInfo &L : M.second) {
Samuel Antao86ace552016-04-27 22:40:57 +00008037 assert(!L.Components.empty() &&
8038 "Not expecting declaration with no component lists.");
Samuel Antaocc10b852016-07-28 14:23:26 +00008039
8040 // Remember the current base pointer index.
Alexey Bataevb3638132018-07-19 16:34:13 +00008041 unsigned CurrentBasePointersIdx = CurBasePointers.size();
Michael Krused47b9432019-08-05 18:43:21 +00008042 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8043 CurBasePointers, CurPointers, CurSizes,
8044 CurTypes, PartialStruct,
8045 IsFirstComponentList, L.IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00008046
8047 // If this entry relates with a device pointer, set the relevant
8048 // declaration and add the 'return pointer' flag.
Alexey Bataevb3638132018-07-19 16:34:13 +00008049 if (L.ReturnDevicePointer) {
8050 assert(CurBasePointers.size() > CurrentBasePointersIdx &&
Samuel Antaocc10b852016-07-28 14:23:26 +00008051 "Unexpected number of mapped base pointers.");
8052
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008053 const ValueDecl *RelevantVD =
8054 L.Components.back().getAssociatedDeclaration();
Samuel Antaocc10b852016-07-28 14:23:26 +00008055 assert(RelevantVD &&
8056 "No relevant declaration related with device pointer??");
8057
Alexey Bataevb3638132018-07-19 16:34:13 +00008058 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD);
8059 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008060 }
Samuel Antao86ace552016-04-27 22:40:57 +00008061 IsFirstComponentList = false;
8062 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008063
8064 // Append any pending zero-length pointers which are struct members and
8065 // used with use_device_ptr.
8066 auto CI = DeferredInfo.find(M.first);
8067 if (CI != DeferredInfo.end()) {
8068 for (const DeferredDevicePtrEntryTy &L : CI->second) {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008069 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF);
Alexey Bataevb3638132018-07-19 16:34:13 +00008070 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar(
8071 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc());
8072 CurBasePointers.emplace_back(BasePtr, L.VD);
8073 CurPointers.push_back(Ptr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008074 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00008075 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder
8076 // value MEMBER_OF=FFFF so that the entry is later updated with the
8077 // correct value of MEMBER_OF.
8078 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM |
8079 OMP_MAP_MEMBER_OF);
8080 }
8081 }
8082
8083 // If there is an entry in PartialStruct it means we have a struct with
8084 // individual members mapped. Emit an extra combined entry.
8085 if (PartialStruct.Base.isValid())
8086 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8087 PartialStruct);
8088
8089 // We need to append the results of this capture to what we already have.
8090 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8091 Pointers.append(CurPointers.begin(), CurPointers.end());
8092 Sizes.append(CurSizes.begin(), CurSizes.end());
8093 Types.append(CurTypes.begin(), CurTypes.end());
Samuel Antao86ace552016-04-27 22:40:57 +00008094 }
8095 }
8096
Michael Krused47b9432019-08-05 18:43:21 +00008097 /// Generate all the base pointers, section pointers, sizes and map types for
8098 /// the extracted map clauses of user-defined mapper.
8099 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers,
8100 MapValuesArrayTy &Pointers,
8101 MapValuesArrayTy &Sizes,
8102 MapFlagsArrayTy &Types) const {
8103 assert(CurDir.is<const OMPDeclareMapperDecl *>() &&
8104 "Expect a declare mapper directive");
8105 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>();
8106 // We have to process the component lists that relate with the same
8107 // declaration in a single chunk so that we can generate the map flags
8108 // correctly. Therefore, we organize all lists in a map.
8109 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
8110
8111 // Helper function to fill the information map for the different supported
8112 // clauses.
8113 auto &&InfoGen = [&Info](
8114 const ValueDecl *D,
8115 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
8116 OpenMPMapClauseKind MapType,
8117 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8118 bool ReturnDevicePointer, bool IsImplicit) {
8119 const ValueDecl *VD =
8120 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
8121 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
8122 IsImplicit);
8123 };
8124
8125 for (const auto *C : CurMapperDir->clauselists()) {
8126 const auto *MC = cast<OMPMapClause>(C);
Mark de Wever51abceb2019-11-12 20:48:11 +01008127 for (const auto L : MC->component_lists()) {
Michael Krused47b9432019-08-05 18:43:21 +00008128 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(),
8129 /*ReturnDevicePointer=*/false, MC->isImplicit());
8130 }
8131 }
8132
8133 for (const auto &M : Info) {
8134 // We need to know when we generate information for the first component
8135 // associated with a capture, because the mapping flags depend on it.
8136 bool IsFirstComponentList = true;
8137
8138 // Temporary versions of arrays
8139 MapBaseValuesArrayTy CurBasePointers;
8140 MapValuesArrayTy CurPointers;
8141 MapValuesArrayTy CurSizes;
8142 MapFlagsArrayTy CurTypes;
8143 StructRangeInfoTy PartialStruct;
8144
8145 for (const MapInfo &L : M.second) {
8146 assert(!L.Components.empty() &&
8147 "Not expecting declaration with no component lists.");
8148 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8149 CurBasePointers, CurPointers, CurSizes,
8150 CurTypes, PartialStruct,
8151 IsFirstComponentList, L.IsImplicit);
8152 IsFirstComponentList = false;
8153 }
8154
8155 // If there is an entry in PartialStruct it means we have a struct with
8156 // individual members mapped. Emit an extra combined entry.
8157 if (PartialStruct.Base.isValid())
8158 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8159 PartialStruct);
8160
8161 // We need to append the results of this capture to what we already have.
8162 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8163 Pointers.append(CurPointers.begin(), CurPointers.end());
8164 Sizes.append(CurSizes.begin(), CurSizes.end());
8165 Types.append(CurTypes.begin(), CurTypes.end());
8166 }
8167 }
8168
Alexey Bataev60705422018-10-30 15:50:12 +00008169 /// Emit capture info for lambdas for variables captured by reference.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008170 void generateInfoForLambdaCaptures(
8171 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers,
8172 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
8173 MapFlagsArrayTy &Types,
8174 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008175 const auto *RD = VD->getType()
8176 .getCanonicalType()
8177 .getNonReferenceType()
8178 ->getAsCXXRecordDecl();
8179 if (!RD || !RD->isLambda())
8180 return;
8181 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD));
8182 LValue VDLVal = CGF.MakeAddrLValue(
8183 VDAddr, VD->getType().getCanonicalType().getNonReferenceType());
8184 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
8185 FieldDecl *ThisCapture = nullptr;
8186 RD->getCaptureFields(Captures, ThisCapture);
8187 if (ThisCapture) {
8188 LValue ThisLVal =
8189 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture);
Alexey Bataev969dbc02018-11-08 15:47:39 +00008190 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008191 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF),
8192 VDLVal.getPointer(CGF));
8193 BasePointers.push_back(ThisLVal.getPointer(CGF));
8194 Pointers.push_back(ThisLValVal.getPointer(CGF));
Alexey Bataeva90fc662019-06-25 16:00:43 +00008195 Sizes.push_back(
8196 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8197 CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008198 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008199 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8200 }
8201 for (const LambdaCapture &LC : RD->captures()) {
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008202 if (!LC.capturesVariable())
Alexey Bataev60705422018-10-30 15:50:12 +00008203 continue;
8204 const VarDecl *VD = LC.getCapturedVar();
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008205 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType())
8206 continue;
Alexey Bataev60705422018-10-30 15:50:12 +00008207 auto It = Captures.find(VD);
8208 assert(It != Captures.end() && "Found lambda capture without field.");
8209 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second);
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008210 if (LC.getCaptureKind() == LCK_ByRef) {
8211 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second);
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008212 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
8213 VDLVal.getPointer(CGF));
8214 BasePointers.push_back(VarLVal.getPointer(CGF));
8215 Pointers.push_back(VarLValVal.getPointer(CGF));
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008216 Sizes.push_back(CGF.Builder.CreateIntCast(
8217 CGF.getTypeSize(
8218 VD->getType().getCanonicalType().getNonReferenceType()),
8219 CGF.Int64Ty, /*isSigned=*/true));
8220 } else {
8221 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008222 LambdaPointers.try_emplace(VarLVal.getPointer(CGF),
8223 VDLVal.getPointer(CGF));
8224 BasePointers.push_back(VarLVal.getPointer(CGF));
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008225 Pointers.push_back(VarRVal.getScalarVal());
8226 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0));
8227 }
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008228 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008229 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8230 }
8231 }
8232
8233 /// Set correct indices for lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008234 void adjustMemberOfForLambdaCaptures(
8235 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
8236 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
8237 MapFlagsArrayTy &Types) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008238 for (unsigned I = 0, E = Types.size(); I < E; ++I) {
8239 // Set correct member_of idx for all implicit lambda captures.
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008240 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008241 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT))
8242 continue;
Alexey Bataev969dbc02018-11-08 15:47:39 +00008243 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]);
8244 assert(BasePtr && "Unable to find base lambda address.");
Alexey Bataev60705422018-10-30 15:50:12 +00008245 int TgtIdx = -1;
8246 for (unsigned J = I; J > 0; --J) {
8247 unsigned Idx = J - 1;
8248 if (Pointers[Idx] != BasePtr)
8249 continue;
8250 TgtIdx = Idx;
8251 break;
8252 }
8253 assert(TgtIdx != -1 && "Unable to find parent lambda.");
8254 // All other current entries will be MEMBER_OF the combined entry
8255 // (except for PTR_AND_OBJ entries which do not have a placeholder value
8256 // 0xFFFF in the MEMBER_OF field).
8257 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx);
8258 setCorrectMemberOfFlag(Types[I], MemberOfFlag);
8259 }
8260 }
8261
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008262 /// Generate the base pointers, section pointers, sizes and map types
Samuel Antao86ace552016-04-27 22:40:57 +00008263 /// associated to a given capture.
8264 void generateInfoForCapture(const CapturedStmt::Capture *Cap,
Samuel Antao6890b092016-07-28 14:25:09 +00008265 llvm::Value *Arg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008266 MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00008267 MapValuesArrayTy &Pointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008268 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
8269 StructRangeInfoTy &PartialStruct) const {
Samuel Antao86ace552016-04-27 22:40:57 +00008270 assert(!Cap->capturesVariableArrayType() &&
8271 "Not expecting to generate map info for a variable array type!");
8272
Samuel Antao6890b092016-07-28 14:25:09 +00008273 // We need to know when we generating information for the first component
Alexey Bataevb3638132018-07-19 16:34:13 +00008274 const ValueDecl *VD = Cap->capturesThis()
8275 ? nullptr
8276 : Cap->getCapturedVar()->getCanonicalDecl();
Samuel Antao86ace552016-04-27 22:40:57 +00008277
Samuel Antao6890b092016-07-28 14:25:09 +00008278 // If this declaration appears in a is_device_ptr clause we just have to
8279 // pass the pointer by value. If it is a reference to a declaration, we just
Alexey Bataevb3638132018-07-19 16:34:13 +00008280 // pass its value.
8281 if (DevPointersMap.count(VD)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008282 BasePointers.emplace_back(Arg, VD);
Samuel Antao6890b092016-07-28 14:25:09 +00008283 Pointers.push_back(Arg);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008284 Sizes.push_back(
8285 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8286 CGF.Int64Ty, /*isSigned=*/true));
George Rokos065755d2017-11-07 18:27:04 +00008287 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM);
Samuel Antao6890b092016-07-28 14:25:09 +00008288 return;
8289 }
8290
Alexey Bataeve82445f2018-09-20 13:54:02 +00008291 using MapData =
8292 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
Kelvin Lief579432018-12-18 22:18:41 +00008293 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008294 SmallVector<MapData, 4> DeclComponentLists;
Michael Krused47b9432019-08-05 18:43:21 +00008295 assert(CurDir.is<const OMPExecutableDirective *>() &&
8296 "Expect a executable directive");
8297 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
8298 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
Mark de Wever51abceb2019-11-12 20:48:11 +01008299 for (const auto L : C->decl_component_lists(VD)) {
Samuel Antao86ace552016-04-27 22:40:57 +00008300 assert(L.first == VD &&
8301 "We got information for the wrong declaration??");
8302 assert(!L.second.empty() &&
8303 "Not expecting declaration with no component lists.");
Alexey Bataeve82445f2018-09-20 13:54:02 +00008304 DeclComponentLists.emplace_back(L.second, C->getMapType(),
Kelvin Lief579432018-12-18 22:18:41 +00008305 C->getMapTypeModifiers(),
Alexey Bataeve82445f2018-09-20 13:54:02 +00008306 C->isImplicit());
Samuel Antao86ace552016-04-27 22:40:57 +00008307 }
Alexey Bataeve82445f2018-09-20 13:54:02 +00008308 }
8309
8310 // Find overlapping elements (including the offset from the base element).
8311 llvm::SmallDenseMap<
8312 const MapData *,
8313 llvm::SmallVector<
8314 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>,
8315 4>
8316 OverlappedData;
8317 size_t Count = 0;
8318 for (const MapData &L : DeclComponentLists) {
8319 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8320 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008321 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008322 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008323 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008324 ++Count;
8325 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) {
8326 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1;
Kelvin Lief579432018-12-18 22:18:41 +00008327 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008328 auto CI = Components.rbegin();
8329 auto CE = Components.rend();
8330 auto SI = Components1.rbegin();
8331 auto SE = Components1.rend();
8332 for (; CI != CE && SI != SE; ++CI, ++SI) {
8333 if (CI->getAssociatedExpression()->getStmtClass() !=
8334 SI->getAssociatedExpression()->getStmtClass())
8335 break;
8336 // Are we dealing with different variables/fields?
8337 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
8338 break;
8339 }
8340 // Found overlapping if, at least for one component, reached the head of
8341 // the components list.
8342 if (CI == CE || SI == SE) {
8343 assert((CI != CE || SI != SE) &&
8344 "Unexpected full match of the mapping components.");
8345 const MapData &BaseData = CI == CE ? L : L1;
8346 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData =
8347 SI == SE ? Components : Components1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008348 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData);
8349 OverlappedElements.getSecond().push_back(SubData);
8350 }
8351 }
8352 }
8353 // Sort the overlapped elements for each item.
8354 llvm::SmallVector<const FieldDecl *, 4> Layout;
8355 if (!OverlappedData.empty()) {
8356 if (const auto *CRD =
8357 VD->getType().getCanonicalType()->getAsCXXRecordDecl())
8358 getPlainLayout(CRD, Layout, /*AsBase=*/false);
8359 else {
8360 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl();
8361 Layout.append(RD->field_begin(), RD->field_end());
8362 }
8363 }
8364 for (auto &Pair : OverlappedData) {
8365 llvm::sort(
8366 Pair.getSecond(),
8367 [&Layout](
8368 OMPClauseMappableExprCommon::MappableExprComponentListRef First,
8369 OMPClauseMappableExprCommon::MappableExprComponentListRef
8370 Second) {
8371 auto CI = First.rbegin();
8372 auto CE = First.rend();
8373 auto SI = Second.rbegin();
8374 auto SE = Second.rend();
8375 for (; CI != CE && SI != SE; ++CI, ++SI) {
8376 if (CI->getAssociatedExpression()->getStmtClass() !=
8377 SI->getAssociatedExpression()->getStmtClass())
8378 break;
8379 // Are we dealing with different variables/fields?
8380 if (CI->getAssociatedDeclaration() !=
8381 SI->getAssociatedDeclaration())
8382 break;
8383 }
Richard Trieu5061e832018-09-21 21:20:33 +00008384
8385 // Lists contain the same elements.
8386 if (CI == CE && SI == SE)
8387 return false;
8388
8389 // List with less elements is less than list with more elements.
8390 if (CI == CE || SI == SE)
8391 return CI == CE;
8392
Alexey Bataeve82445f2018-09-20 13:54:02 +00008393 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
8394 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
8395 if (FD1->getParent() == FD2->getParent())
8396 return FD1->getFieldIndex() < FD2->getFieldIndex();
8397 const auto It =
8398 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) {
8399 return FD == FD1 || FD == FD2;
8400 });
8401 return *It == FD1;
8402 });
8403 }
8404
8405 // Associated with a capture, because the mapping flags depend on it.
8406 // Go through all of the elements with the overlapped elements.
8407 for (const auto &Pair : OverlappedData) {
8408 const MapData &L = *Pair.getFirst();
8409 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8410 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008411 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008412 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008413 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008414 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
8415 OverlappedComponents = Pair.getSecond();
8416 bool IsFirstComponentList = true;
Kelvin Lief579432018-12-18 22:18:41 +00008417 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008418 BasePointers, Pointers, Sizes, Types,
8419 PartialStruct, IsFirstComponentList,
8420 IsImplicit, OverlappedComponents);
8421 }
8422 // Go through other elements without overlapped elements.
8423 bool IsFirstComponentList = OverlappedData.empty();
8424 for (const MapData &L : DeclComponentLists) {
8425 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8426 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008427 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008428 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008429 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008430 auto It = OverlappedData.find(&L);
8431 if (It == OverlappedData.end())
Kelvin Lief579432018-12-18 22:18:41 +00008432 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008433 BasePointers, Pointers, Sizes, Types,
8434 PartialStruct, IsFirstComponentList,
8435 IsImplicit);
8436 IsFirstComponentList = false;
8437 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008438 }
Samuel Antao86ace552016-04-27 22:40:57 +00008439
Alexey Bataevb3638132018-07-19 16:34:13 +00008440 /// Generate the base pointers, section pointers, sizes and map types
8441 /// associated with the declare target link variables.
8442 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers,
8443 MapValuesArrayTy &Pointers,
8444 MapValuesArrayTy &Sizes,
8445 MapFlagsArrayTy &Types) const {
Michael Krused47b9432019-08-05 18:43:21 +00008446 assert(CurDir.is<const OMPExecutableDirective *>() &&
8447 "Expect a executable directive");
8448 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
Alexey Bataevb3638132018-07-19 16:34:13 +00008449 // Map other list items in the map clause which are not captured variables
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00008450 // but "declare target link" global variables.
Michael Krused47b9432019-08-05 18:43:21 +00008451 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
Mark de Wever51abceb2019-11-12 20:48:11 +01008452 for (const auto L : C->component_lists()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00008453 if (!L.first)
8454 continue;
8455 const auto *VD = dyn_cast<VarDecl>(L.first);
8456 if (!VD)
8457 continue;
8458 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00008459 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00008460 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
8461 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)
Alexey Bataevb3638132018-07-19 16:34:13 +00008462 continue;
8463 StructRangeInfoTy PartialStruct;
8464 generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00008465 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008466 Pointers, Sizes, Types, PartialStruct,
8467 /*IsFirstComponentList=*/true, C->isImplicit());
8468 assert(!PartialStruct.Base.isValid() &&
8469 "No partial structs for declare target link expected.");
8470 }
8471 }
Samuel Antao86ace552016-04-27 22:40:57 +00008472 }
Samuel Antaod486f842016-05-26 16:53:38 +00008473
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008474 /// Generate the default map information for a given capture \a CI,
Samuel Antaod486f842016-05-26 16:53:38 +00008475 /// record field declaration \a RI and captured value \a CV.
Samuel Antaocc10b852016-07-28 14:23:26 +00008476 void generateDefaultMapInfo(const CapturedStmt::Capture &CI,
8477 const FieldDecl &RI, llvm::Value *CV,
8478 MapBaseValuesArrayTy &CurBasePointers,
8479 MapValuesArrayTy &CurPointers,
8480 MapValuesArrayTy &CurSizes,
Alexey Bataevb3638132018-07-19 16:34:13 +00008481 MapFlagsArrayTy &CurMapTypes) const {
Alexey Bataevf288cf92019-06-27 18:53:07 +00008482 bool IsImplicit = true;
Samuel Antaod486f842016-05-26 16:53:38 +00008483 // Do the default mapping.
8484 if (CI.capturesThis()) {
8485 CurBasePointers.push_back(CV);
8486 CurPointers.push_back(CV);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008487 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr());
Alexey Bataeva90fc662019-06-25 16:00:43 +00008488 CurSizes.push_back(
8489 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()),
8490 CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008491 // Default map type.
Samuel Antaocc10b852016-07-28 14:23:26 +00008492 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM);
Samuel Antaod486f842016-05-26 16:53:38 +00008493 } else if (CI.capturesVariableByCopy()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008494 CurBasePointers.push_back(CV);
8495 CurPointers.push_back(CV);
Samuel Antaod486f842016-05-26 16:53:38 +00008496 if (!RI.getType()->isAnyPointerType()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008497 // We have to signal to the runtime captures passed by value that are
8498 // not pointers.
George Rokos065755d2017-11-07 18:27:04 +00008499 CurMapTypes.push_back(OMP_MAP_LITERAL);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008500 CurSizes.push_back(CGF.Builder.CreateIntCast(
8501 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008502 } else {
8503 // Pointers are implicitly mapped with a zero size and no flags
8504 // (other than first map that is added for all implicit maps).
Alexey Bataevb3638132018-07-19 16:34:13 +00008505 CurMapTypes.push_back(OMP_MAP_NONE);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008506 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
Samuel Antaod486f842016-05-26 16:53:38 +00008507 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008508 const VarDecl *VD = CI.getCapturedVar();
8509 auto I = FirstPrivateDecls.find(VD);
8510 if (I != FirstPrivateDecls.end())
8511 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008512 } else {
8513 assert(CI.capturesVariable() && "Expected captured reference.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008514 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr());
Samuel Antaod486f842016-05-26 16:53:38 +00008515 QualType ElementType = PtrTy->getPointeeType();
Alexey Bataeva90fc662019-06-25 16:00:43 +00008516 CurSizes.push_back(CGF.Builder.CreateIntCast(
8517 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008518 // The default map type for a scalar/complex type is 'to' because by
8519 // default the value doesn't have to be retrieved. For an aggregate
8520 // type, the default is 'tofrom'.
Alexey Bataevb3638132018-07-19 16:34:13 +00008521 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI));
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008522 const VarDecl *VD = CI.getCapturedVar();
Alexey Bataevf288cf92019-06-27 18:53:07 +00008523 auto I = FirstPrivateDecls.find(VD);
8524 if (I != FirstPrivateDecls.end() &&
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008525 VD->getType().isConstant(CGF.getContext())) {
8526 llvm::Constant *Addr =
8527 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD);
8528 // Copy the value of the original variable to the new global copy.
8529 CGF.Builder.CreateMemCpy(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008530 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(CGF),
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008531 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)),
Rui Ueyama49a3ad22019-07-16 04:46:31 +00008532 CurSizes.back(), /*IsVolatile=*/false);
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008533 // Use new global variable as the base pointers.
8534 CurBasePointers.push_back(Addr);
8535 CurPointers.push_back(Addr);
8536 } else {
8537 CurBasePointers.push_back(CV);
Alexey Bataevf288cf92019-06-27 18:53:07 +00008538 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) {
Alexey Bataevc2b831f2019-04-02 16:03:40 +00008539 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue(
8540 CV, ElementType, CGF.getContext().getDeclAlign(VD),
8541 AlignmentSource::Decl));
8542 CurPointers.push_back(PtrAddr.getPointer());
8543 } else {
8544 CurPointers.push_back(CV);
8545 }
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008546 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008547 if (I != FirstPrivateDecls.end())
8548 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008549 }
George Rokos065755d2017-11-07 18:27:04 +00008550 // Every default map produces a single argument which is a target parameter.
8551 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM;
Alexey Bataevb3638132018-07-19 16:34:13 +00008552
8553 // Add flag stating this is an implicit map.
Alexey Bataevf288cf92019-06-27 18:53:07 +00008554 if (IsImplicit)
8555 CurMapTypes.back() |= OMP_MAP_IMPLICIT;
Samuel Antaod486f842016-05-26 16:53:38 +00008556 }
Samuel Antao86ace552016-04-27 22:40:57 +00008557};
Samuel Antaodf158d52016-04-27 22:58:19 +00008558} // anonymous namespace
8559
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008560/// Emit the arrays used to pass the captures and map information to the
Samuel Antaodf158d52016-04-27 22:58:19 +00008561/// offloading runtime library. If there is no map or capture information,
8562/// return nullptr by reference.
8563static void
Samuel Antaocc10b852016-07-28 14:23:26 +00008564emitOffloadingArrays(CodeGenFunction &CGF,
8565 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers,
Samuel Antaodf158d52016-04-27 22:58:19 +00008566 MappableExprsHandler::MapValuesArrayTy &Pointers,
8567 MappableExprsHandler::MapValuesArrayTy &Sizes,
Samuel Antaocc10b852016-07-28 14:23:26 +00008568 MappableExprsHandler::MapFlagsArrayTy &MapTypes,
8569 CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008570 CodeGenModule &CGM = CGF.CGM;
8571 ASTContext &Ctx = CGF.getContext();
Samuel Antaodf158d52016-04-27 22:58:19 +00008572
Samuel Antaocc10b852016-07-28 14:23:26 +00008573 // Reset the array information.
8574 Info.clearArrayInfo();
8575 Info.NumberOfPtrs = BasePointers.size();
Samuel Antaodf158d52016-04-27 22:58:19 +00008576
Samuel Antaocc10b852016-07-28 14:23:26 +00008577 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008578 // Detect if we have any capture size requiring runtime evaluation of the
8579 // size so that a constant array could be eventually used.
8580 bool hasRuntimeEvaluationCaptureSize = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008581 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008582 if (!isa<llvm::Constant>(S)) {
8583 hasRuntimeEvaluationCaptureSize = true;
8584 break;
8585 }
8586
Samuel Antaocc10b852016-07-28 14:23:26 +00008587 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true);
Richard Smith772e2662019-10-04 01:25:59 +00008588 QualType PointerArrayType = Ctx.getConstantArrayType(
8589 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal,
8590 /*IndexTypeQuals=*/0);
Samuel Antaodf158d52016-04-27 22:58:19 +00008591
Samuel Antaocc10b852016-07-28 14:23:26 +00008592 Info.BasePointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008593 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
Samuel Antaocc10b852016-07-28 14:23:26 +00008594 Info.PointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008595 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
8596
8597 // If we don't have any VLA types or other types that require runtime
8598 // evaluation, we can use a constant array for the map sizes, otherwise we
8599 // need to fill up the arrays as we do for the pointers.
Alexey Bataeva90fc662019-06-25 16:00:43 +00008600 QualType Int64Ty =
8601 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Samuel Antaodf158d52016-04-27 22:58:19 +00008602 if (hasRuntimeEvaluationCaptureSize) {
Richard Smith772e2662019-10-04 01:25:59 +00008603 QualType SizeArrayType = Ctx.getConstantArrayType(
8604 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal,
8605 /*IndexTypeQuals=*/0);
Samuel Antaocc10b852016-07-28 14:23:26 +00008606 Info.SizesArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008607 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
8608 } else {
8609 // We expect all the sizes to be constant, so we collect them to create
8610 // a constant array.
8611 SmallVector<llvm::Constant *, 16> ConstSizes;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008612 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008613 ConstSizes.push_back(cast<llvm::Constant>(S));
8614
8615 auto *SizesArrayInit = llvm::ConstantArray::get(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008616 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008617 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008618 auto *SizesArrayGbl = new llvm::GlobalVariable(
8619 CGM.getModule(), SizesArrayInit->getType(),
8620 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008621 SizesArrayInit, Name);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008622 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008623 Info.SizesArray = SizesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008624 }
8625
8626 // The map types are always constant so we don't need to generate code to
8627 // fill arrays. Instead, we create an array constant.
Alexey Bataevb3638132018-07-19 16:34:13 +00008628 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0);
8629 llvm::copy(MapTypes, Mapping.begin());
Samuel Antaodf158d52016-04-27 22:58:19 +00008630 llvm::Constant *MapTypesArrayInit =
Alexey Bataevb3638132018-07-19 16:34:13 +00008631 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008632 std::string MaptypesName =
8633 CGM.getOpenMPRuntime().getName({"offload_maptypes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008634 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
8635 CGM.getModule(), MapTypesArrayInit->getType(),
8636 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008637 MapTypesArrayInit, MaptypesName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008638 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008639 Info.MapTypesArray = MapTypesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008640
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008641 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) {
8642 llvm::Value *BPVal = *BasePointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008643 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008644 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008645 Info.BasePointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008646 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8647 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008648 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8649 CGF.Builder.CreateStore(BPVal, BPAddr);
8650
Samuel Antaocc10b852016-07-28 14:23:26 +00008651 if (Info.requiresDevicePointerInfo())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008652 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl())
Alexey Bataev43a919f2018-04-13 17:48:43 +00008653 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr);
Samuel Antaocc10b852016-07-28 14:23:26 +00008654
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008655 llvm::Value *PVal = Pointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008656 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008657 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008658 Info.PointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008659 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8660 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008661 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8662 CGF.Builder.CreateStore(PVal, PAddr);
8663
8664 if (hasRuntimeEvaluationCaptureSize) {
8665 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008666 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008667 Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008668 /*Idx0=*/0,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008669 /*Idx1=*/I);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008670 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty));
Samuel Antaodf158d52016-04-27 22:58:19 +00008671 CGF.Builder.CreateStore(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008672 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true),
Samuel Antaodf158d52016-04-27 22:58:19 +00008673 SAddr);
8674 }
8675 }
8676 }
8677}
Michael Krused47b9432019-08-05 18:43:21 +00008678
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008679/// Emit the arguments to be passed to the runtime library based on the
Samuel Antaodf158d52016-04-27 22:58:19 +00008680/// arrays of pointers, sizes and map types.
8681static void emitOffloadingArraysArgument(
8682 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg,
8683 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008684 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008685 CodeGenModule &CGM = CGF.CGM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008686 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008687 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008688 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8689 Info.BasePointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008690 /*Idx0=*/0, /*Idx1=*/0);
8691 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008692 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8693 Info.PointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008694 /*Idx0=*/0,
8695 /*Idx1=*/0);
8696 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008697 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008698 /*Idx0=*/0, /*Idx1=*/0);
8699 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
George Rokos63bc9d62017-11-21 18:25:12 +00008700 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008701 Info.MapTypesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008702 /*Idx0=*/0,
8703 /*Idx1=*/0);
8704 } else {
8705 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
8706 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008707 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008708 MapTypesArrayArg =
George Rokos63bc9d62017-11-21 18:25:12 +00008709 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008710 }
Samuel Antao86ace552016-04-27 22:40:57 +00008711}
8712
Alexey Bataev7bb33532019-01-07 21:30:43 +00008713/// Check for inner distribute directive.
8714static const OMPExecutableDirective *
8715getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
8716 const auto *CS = D.getInnermostCapturedStmt();
8717 const auto *Body =
8718 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00008719 const Stmt *ChildStmt =
8720 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
Alexey Bataev7bb33532019-01-07 21:30:43 +00008721
Alexey Bataev5c427362019-04-10 19:11:33 +00008722 if (const auto *NestedDir =
8723 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008724 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind();
8725 switch (D.getDirectiveKind()) {
8726 case OMPD_target:
8727 if (isOpenMPDistributeDirective(DKind))
8728 return NestedDir;
8729 if (DKind == OMPD_teams) {
8730 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
8731 /*IgnoreCaptured=*/true);
8732 if (!Body)
8733 return nullptr;
Alexey Bataev5c427362019-04-10 19:11:33 +00008734 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
8735 if (const auto *NND =
8736 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008737 DKind = NND->getDirectiveKind();
8738 if (isOpenMPDistributeDirective(DKind))
8739 return NND;
8740 }
8741 }
8742 return nullptr;
8743 case OMPD_target_teams:
8744 if (isOpenMPDistributeDirective(DKind))
8745 return NestedDir;
8746 return nullptr;
8747 case OMPD_target_parallel:
8748 case OMPD_target_simd:
8749 case OMPD_target_parallel_for:
8750 case OMPD_target_parallel_for_simd:
8751 return nullptr;
8752 case OMPD_target_teams_distribute:
8753 case OMPD_target_teams_distribute_simd:
8754 case OMPD_target_teams_distribute_parallel_for:
8755 case OMPD_target_teams_distribute_parallel_for_simd:
8756 case OMPD_parallel:
8757 case OMPD_for:
8758 case OMPD_parallel_for:
cchen47d60942019-12-05 13:43:48 -05008759 case OMPD_parallel_master:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008760 case OMPD_parallel_sections:
8761 case OMPD_for_simd:
8762 case OMPD_parallel_for_simd:
8763 case OMPD_cancel:
8764 case OMPD_cancellation_point:
8765 case OMPD_ordered:
8766 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00008767 case OMPD_allocate:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008768 case OMPD_task:
8769 case OMPD_simd:
8770 case OMPD_sections:
8771 case OMPD_section:
8772 case OMPD_single:
8773 case OMPD_master:
8774 case OMPD_critical:
8775 case OMPD_taskyield:
8776 case OMPD_barrier:
8777 case OMPD_taskwait:
8778 case OMPD_taskgroup:
8779 case OMPD_atomic:
8780 case OMPD_flush:
8781 case OMPD_teams:
8782 case OMPD_target_data:
8783 case OMPD_target_exit_data:
8784 case OMPD_target_enter_data:
8785 case OMPD_distribute:
8786 case OMPD_distribute_simd:
8787 case OMPD_distribute_parallel_for:
8788 case OMPD_distribute_parallel_for_simd:
8789 case OMPD_teams_distribute:
8790 case OMPD_teams_distribute_simd:
8791 case OMPD_teams_distribute_parallel_for:
8792 case OMPD_teams_distribute_parallel_for_simd:
8793 case OMPD_target_update:
8794 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00008795 case OMPD_declare_variant:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008796 case OMPD_declare_target:
8797 case OMPD_end_declare_target:
8798 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00008799 case OMPD_declare_mapper:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008800 case OMPD_taskloop:
8801 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00008802 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00008803 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00008804 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04008805 case OMPD_parallel_master_taskloop_simd:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008806 case OMPD_requires:
8807 case OMPD_unknown:
8808 llvm_unreachable("Unexpected directive.");
8809 }
8810 }
8811
8812 return nullptr;
8813}
8814
Michael Krused47b9432019-08-05 18:43:21 +00008815/// Emit the user-defined mapper function. The code generation follows the
8816/// pattern in the example below.
8817/// \code
8818/// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle,
8819/// void *base, void *begin,
8820/// int64_t size, int64_t type) {
8821/// // Allocate space for an array section first.
8822/// if (size > 1 && !maptype.IsDelete)
8823/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
8824/// size*sizeof(Ty), clearToFrom(type));
8825/// // Map members.
8826/// for (unsigned i = 0; i < size; i++) {
8827/// // For each component specified by this mapper:
8828/// for (auto c : all_components) {
8829/// if (c.hasMapper())
8830/// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size,
8831/// c.arg_type);
8832/// else
8833/// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base,
8834/// c.arg_begin, c.arg_size, c.arg_type);
8835/// }
8836/// }
8837/// // Delete the array section.
8838/// if (size > 1 && maptype.IsDelete)
8839/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
8840/// size*sizeof(Ty), clearToFrom(type));
8841/// }
8842/// \endcode
8843void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D,
8844 CodeGenFunction *CGF) {
8845 if (UDMMap.count(D) > 0)
8846 return;
8847 ASTContext &C = CGM.getContext();
8848 QualType Ty = D->getType();
8849 QualType PtrTy = C.getPointerType(Ty).withRestrict();
8850 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
8851 auto *MapperVarDecl =
8852 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl());
8853 SourceLocation Loc = D->getLocation();
8854 CharUnits ElementSize = C.getTypeSizeInChars(Ty);
8855
8856 // Prepare mapper function arguments and attributes.
8857 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
8858 C.VoidPtrTy, ImplicitParamDecl::Other);
8859 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
8860 ImplicitParamDecl::Other);
8861 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
8862 C.VoidPtrTy, ImplicitParamDecl::Other);
8863 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
8864 ImplicitParamDecl::Other);
8865 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
8866 ImplicitParamDecl::Other);
8867 FunctionArgList Args;
8868 Args.push_back(&HandleArg);
8869 Args.push_back(&BaseArg);
8870 Args.push_back(&BeginArg);
8871 Args.push_back(&SizeArg);
8872 Args.push_back(&TypeArg);
8873 const CGFunctionInfo &FnInfo =
8874 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
8875 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
8876 SmallString<64> TyStr;
8877 llvm::raw_svector_ostream Out(TyStr);
8878 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out);
8879 std::string Name = getName({"omp_mapper", TyStr, D->getName()});
8880 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
8881 Name, &CGM.getModule());
8882 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
8883 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
8884 // Start the mapper function code generation.
8885 CodeGenFunction MapperCGF(CGM);
8886 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
8887 // Compute the starting and end addreses of array elements.
8888 llvm::Value *Size = MapperCGF.EmitLoadOfScalar(
8889 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false,
8890 C.getPointerType(Int64Ty), Loc);
8891 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast(
8892 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(),
8893 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy)));
8894 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size);
8895 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar(
8896 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false,
8897 C.getPointerType(Int64Ty), Loc);
8898 // Prepare common arguments for array initiation and deletion.
8899 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar(
8900 MapperCGF.GetAddrOfLocalVar(&HandleArg),
8901 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8902 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar(
8903 MapperCGF.GetAddrOfLocalVar(&BaseArg),
8904 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8905 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar(
8906 MapperCGF.GetAddrOfLocalVar(&BeginArg),
8907 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
8908
8909 // Emit array initiation if this is an array section and \p MapType indicates
8910 // that memory allocation is required.
8911 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head");
8912 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
8913 ElementSize, HeadBB, /*IsInit=*/true);
8914
8915 // Emit a for loop to iterate through SizeArg of elements and map all of them.
8916
8917 // Emit the loop header block.
8918 MapperCGF.EmitBlock(HeadBB);
8919 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body");
8920 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done");
8921 // Evaluate whether the initial condition is satisfied.
8922 llvm::Value *IsEmpty =
8923 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty");
8924 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
8925 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock();
8926
8927 // Emit the loop body block.
8928 MapperCGF.EmitBlock(BodyBB);
8929 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI(
8930 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent");
8931 PtrPHI->addIncoming(PtrBegin, EntryBB);
8932 Address PtrCurrent =
8933 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg)
8934 .getAlignment()
8935 .alignmentOfArrayElement(ElementSize));
8936 // Privatize the declared variable of mapper to be the current array element.
8937 CodeGenFunction::OMPPrivateScope Scope(MapperCGF);
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08008938 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() {
Michael Krused47b9432019-08-05 18:43:21 +00008939 return MapperCGF
8940 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>())
Akira Hatanakaf139ae32019-12-03 15:17:01 -08008941 .getAddress(MapperCGF);
Michael Krused47b9432019-08-05 18:43:21 +00008942 });
8943 (void)Scope.Privatize();
8944
8945 // Get map clause information. Fill up the arrays with all mapped variables.
8946 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
8947 MappableExprsHandler::MapValuesArrayTy Pointers;
8948 MappableExprsHandler::MapValuesArrayTy Sizes;
8949 MappableExprsHandler::MapFlagsArrayTy MapTypes;
8950 MappableExprsHandler MEHandler(*D, MapperCGF);
8951 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes);
8952
8953 // Call the runtime API __tgt_mapper_num_components to get the number of
8954 // pre-existing components.
8955 llvm::Value *OffloadingArgs[] = {Handle};
8956 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall(
8957 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs);
8958 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl(
8959 PreviousSize,
8960 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset()));
8961
8962 // Fill up the runtime mapper handle for all components.
8963 for (unsigned I = 0; I < BasePointers.size(); ++I) {
8964 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast(
8965 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
8966 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast(
8967 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
8968 llvm::Value *CurSizeArg = Sizes[I];
8969
8970 // Extract the MEMBER_OF field from the map type.
8971 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member");
8972 MapperCGF.EmitBlock(MemberBB);
8973 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]);
8974 llvm::Value *Member = MapperCGF.Builder.CreateAnd(
8975 OriMapType,
8976 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF));
8977 llvm::BasicBlock *MemberCombineBB =
8978 MapperCGF.createBasicBlock("omp.member.combine");
8979 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type");
8980 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member);
8981 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB);
8982 // Add the number of pre-existing components to the MEMBER_OF field if it
8983 // is valid.
8984 MapperCGF.EmitBlock(MemberCombineBB);
8985 llvm::Value *CombinedMember =
8986 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
8987 // Do nothing if it is not a member of previous components.
8988 MapperCGF.EmitBlock(TypeBB);
8989 llvm::PHINode *MemberMapType =
8990 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype");
8991 MemberMapType->addIncoming(OriMapType, MemberBB);
8992 MemberMapType->addIncoming(CombinedMember, MemberCombineBB);
8993
8994 // Combine the map type inherited from user-defined mapper with that
8995 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM
8996 // bits of the \a MapType, which is the input argument of the mapper
8997 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM
8998 // bits of MemberMapType.
8999 // [OpenMP 5.0], 1.2.6. map-type decay.
9000 // | alloc | to | from | tofrom | release | delete
9001 // ----------------------------------------------------------
9002 // alloc | alloc | alloc | alloc | alloc | release | delete
9003 // to | alloc | to | alloc | to | release | delete
9004 // from | alloc | alloc | from | from | release | delete
9005 // tofrom | alloc | to | from | tofrom | release | delete
9006 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd(
9007 MapType,
9008 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO |
9009 MappableExprsHandler::OMP_MAP_FROM));
9010 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc");
9011 llvm::BasicBlock *AllocElseBB =
9012 MapperCGF.createBasicBlock("omp.type.alloc.else");
9013 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to");
9014 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else");
9015 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from");
9016 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end");
9017 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom);
9018 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
9019 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM.
9020 MapperCGF.EmitBlock(AllocBB);
9021 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd(
9022 MemberMapType,
9023 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9024 MappableExprsHandler::OMP_MAP_FROM)));
9025 MapperCGF.Builder.CreateBr(EndBB);
9026 MapperCGF.EmitBlock(AllocElseBB);
9027 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ(
9028 LeftToFrom,
9029 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO));
9030 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
9031 // In case of to, clear OMP_MAP_FROM.
9032 MapperCGF.EmitBlock(ToBB);
9033 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd(
9034 MemberMapType,
9035 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM));
9036 MapperCGF.Builder.CreateBr(EndBB);
9037 MapperCGF.EmitBlock(ToElseBB);
9038 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ(
9039 LeftToFrom,
9040 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM));
9041 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB);
9042 // In case of from, clear OMP_MAP_TO.
9043 MapperCGF.EmitBlock(FromBB);
9044 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd(
9045 MemberMapType,
9046 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO));
9047 // In case of tofrom, do nothing.
9048 MapperCGF.EmitBlock(EndBB);
9049 llvm::PHINode *CurMapType =
9050 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype");
9051 CurMapType->addIncoming(AllocMapType, AllocBB);
9052 CurMapType->addIncoming(ToMapType, ToBB);
9053 CurMapType->addIncoming(FromMapType, FromBB);
9054 CurMapType->addIncoming(MemberMapType, ToElseBB);
9055
9056 // TODO: call the corresponding mapper function if a user-defined mapper is
9057 // associated with this map clause.
9058 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9059 // data structure.
9060 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg,
9061 CurSizeArg, CurMapType};
9062 MapperCGF.EmitRuntimeCall(
9063 createRuntimeFunction(OMPRTL__tgt_push_mapper_component),
9064 OffloadingArgs);
9065 }
9066
9067 // Update the pointer to point to the next element that needs to be mapped,
9068 // and check whether we have mapped all elements.
9069 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32(
9070 PtrPHI, /*Idx0=*/1, "omp.arraymap.next");
9071 PtrPHI->addIncoming(PtrNext, BodyBB);
9072 llvm::Value *IsDone =
9073 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone");
9074 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit");
9075 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
9076
9077 MapperCGF.EmitBlock(ExitBB);
9078 // Emit array deletion if this is an array section and \p MapType indicates
9079 // that deletion is required.
9080 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
9081 ElementSize, DoneBB, /*IsInit=*/false);
9082
9083 // Emit the function exit block.
9084 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true);
9085 MapperCGF.FinishFunction();
9086 UDMMap.try_emplace(D, Fn);
9087 if (CGF) {
9088 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn);
9089 Decls.second.push_back(D);
9090 }
9091}
9092
9093/// Emit the array initialization or deletion portion for user-defined mapper
9094/// code generation. First, it evaluates whether an array section is mapped and
9095/// whether the \a MapType instructs to delete this section. If \a IsInit is
9096/// true, and \a MapType indicates to not delete this array, array
9097/// initialization code is generated. If \a IsInit is false, and \a MapType
9098/// indicates to not this array, array deletion code is generated.
9099void CGOpenMPRuntime::emitUDMapperArrayInitOrDel(
9100 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base,
9101 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType,
9102 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) {
9103 StringRef Prefix = IsInit ? ".init" : ".del";
9104
9105 // Evaluate if this is an array section.
9106 llvm::BasicBlock *IsDeleteBB =
Alexey Bataev8b321922020-01-16 15:46:34 -05009107 MapperCGF.createBasicBlock(getName({"omp.array", Prefix, ".evaldelete"}));
9108 llvm::BasicBlock *BodyBB =
9109 MapperCGF.createBasicBlock(getName({"omp.array", Prefix}));
Michael Krused47b9432019-08-05 18:43:21 +00009110 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE(
9111 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray");
9112 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB);
9113
9114 // Evaluate if we are going to delete this section.
9115 MapperCGF.EmitBlock(IsDeleteBB);
9116 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd(
9117 MapType,
9118 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE));
9119 llvm::Value *DeleteCond;
9120 if (IsInit) {
9121 DeleteCond = MapperCGF.Builder.CreateIsNull(
Alexey Bataev8b321922020-01-16 15:46:34 -05009122 DeleteBit, getName({"omp.array", Prefix, ".delete"}));
Michael Krused47b9432019-08-05 18:43:21 +00009123 } else {
9124 DeleteCond = MapperCGF.Builder.CreateIsNotNull(
Alexey Bataev8b321922020-01-16 15:46:34 -05009125 DeleteBit, getName({"omp.array", Prefix, ".delete"}));
Michael Krused47b9432019-08-05 18:43:21 +00009126 }
9127 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB);
9128
9129 MapperCGF.EmitBlock(BodyBB);
9130 // Get the array size by multiplying element size and element number (i.e., \p
9131 // Size).
9132 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul(
9133 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
9134 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves
9135 // memory allocation/deletion purpose only.
9136 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd(
9137 MapType,
9138 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9139 MappableExprsHandler::OMP_MAP_FROM)));
9140 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9141 // data structure.
9142 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg};
9143 MapperCGF.EmitRuntimeCall(
9144 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs);
9145}
9146
Alexey Bataev7bb33532019-01-07 21:30:43 +00009147void CGOpenMPRuntime::emitTargetNumIterationsCall(
Alexey Bataevec7946e2019-09-23 14:06:51 +00009148 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9149 llvm::Value *DeviceID,
9150 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9151 const OMPLoopDirective &D)>
9152 SizeEmitter) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00009153 OpenMPDirectiveKind Kind = D.getDirectiveKind();
9154 const OMPExecutableDirective *TD = &D;
9155 // Get nested teams distribute kind directive, if any.
9156 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind))
9157 TD = getNestedDistributeDirective(CGM.getContext(), D);
9158 if (!TD)
9159 return;
9160 const auto *LD = cast<OMPLoopDirective>(TD);
Alexey Bataevec7946e2019-09-23 14:06:51 +00009161 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF,
Alexey Bataev7bb33532019-01-07 21:30:43 +00009162 PrePostActionTy &) {
Alexey Bataevec7946e2019-09-23 14:06:51 +00009163 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) {
9164 llvm::Value *Args[] = {DeviceID, NumIterations};
9165 CGF.EmitRuntimeCall(
9166 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args);
9167 }
Alexey Bataev7bb33532019-01-07 21:30:43 +00009168 };
9169 emitInlinedDirective(CGF, OMPD_unknown, CodeGen);
9170}
9171
Alexey Bataevec7946e2019-09-23 14:06:51 +00009172void CGOpenMPRuntime::emitTargetCall(
9173 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9174 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
9175 const Expr *Device,
9176 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9177 const OMPLoopDirective &D)>
9178 SizeEmitter) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00009179 if (!CGF.HaveInsertPoint())
9180 return;
Samuel Antaobed3c462015-10-02 16:14:20 +00009181
Samuel Antaoee8fb302016-01-06 13:42:12 +00009182 assert(OutlinedFn && "Invalid outlined function!");
9183
Alexey Bataev8451efa2018-01-15 19:06:12 +00009184 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>();
9185 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
Alexey Bataev475a7442018-01-12 19:39:11 +00009186 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009187 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF,
9188 PrePostActionTy &) {
9189 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9190 };
9191 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen);
Samuel Antao86ace552016-04-27 22:40:57 +00009192
Alexey Bataev8451efa2018-01-15 19:06:12 +00009193 CodeGenFunction::OMPTargetDataInfo InputInfo;
9194 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobed3c462015-10-02 16:14:20 +00009195 // Fill up the pointer arrays and transfer execution to the device.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009196 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo,
Alexey Bataevec7946e2019-09-23 14:06:51 +00009197 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars,
9198 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobed3c462015-10-02 16:14:20 +00009199 // On top of the arrays that were filled up, the target offloading call
9200 // takes as arguments the device id as well as the host pointer. The host
9201 // pointer is used by the runtime library to identify the current target
9202 // region, so it only has to be unique and not necessarily point to
9203 // anything. It could be the pointer to the outlined function that
9204 // implements the target region, but we aren't using that so that the
9205 // compiler doesn't need to keep that, and could therefore inline the host
9206 // function if proven worthwhile during optimization.
9207
Samuel Antaoee8fb302016-01-06 13:42:12 +00009208 // From this point on, we need to have an ID of the target region defined.
9209 assert(OutlinedFnID && "Invalid outlined function ID!");
Samuel Antaobed3c462015-10-02 16:14:20 +00009210
9211 // Emit device ID if any.
9212 llvm::Value *DeviceID;
George Rokos63bc9d62017-11-21 18:25:12 +00009213 if (Device) {
Samuel Antaobed3c462015-10-02 16:14:20 +00009214 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009215 CGF.Int64Ty, /*isSigned=*/true);
9216 } else {
9217 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9218 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009219
Samuel Antaodf158d52016-04-27 22:58:19 +00009220 // Emit the number of elements in the offloading arrays.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009221 llvm::Value *PointerNum =
9222 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaodf158d52016-04-27 22:58:19 +00009223
Samuel Antaob68e2db2016-03-03 16:20:23 +00009224 // Return value of the runtime offloading call.
9225 llvm::Value *Return;
9226
Alexey Bataev5c427362019-04-10 19:11:33 +00009227 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D);
9228 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009229
Alexey Bataevec7946e2019-09-23 14:06:51 +00009230 // Emit tripcount for the target loop-based directive.
9231 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter);
9232
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009233 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00009234 // The target region is an outlined function launched by the runtime
9235 // via calls __tgt_target() or __tgt_target_teams().
9236 //
9237 // __tgt_target() launches a target region with one team and one thread,
9238 // executing a serial region. This master thread may in turn launch
9239 // more threads within its team upon encountering a parallel region,
9240 // however, no additional teams can be launched on the device.
9241 //
9242 // __tgt_target_teams() launches a target region with one or more teams,
9243 // each with one or more threads. This call is required for target
9244 // constructs such as:
9245 // 'target teams'
9246 // 'target' / 'teams'
9247 // 'target teams distribute parallel for'
9248 // 'target parallel'
9249 // and so on.
9250 //
9251 // Note that on the host and CPU targets, the runtime implementation of
9252 // these calls simply call the outlined function without forking threads.
9253 // The outlined functions themselves have runtime calls to
9254 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by
9255 // the compiler in emitTeamsCall() and emitParallelCall().
9256 //
9257 // In contrast, on the NVPTX target, the implementation of
9258 // __tgt_target_teams() launches a GPU kernel with the requested number
9259 // of teams and threads so no additional calls to the runtime are required.
Samuel Antaob68e2db2016-03-03 16:20:23 +00009260 if (NumTeams) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00009261 // If we have NumTeams defined this means that we have an enclosed teams
9262 // region. Therefore we also expect to have NumThreads defined. These two
9263 // values should be defined in the presence of a teams directive,
9264 // regardless of having any clauses associated. If the user is using teams
9265 // but no clauses, these two values will be the default that should be
9266 // passed to the runtime library - a 32-bit integer with the value zero.
9267 assert(NumThreads && "Thread limit expression should be available along "
9268 "with number of teams.");
Alexey Bataev8451efa2018-01-15 19:06:12 +00009269 llvm::Value *OffloadingArgs[] = {DeviceID,
9270 OutlinedFnID,
9271 PointerNum,
9272 InputInfo.BasePointersArray.getPointer(),
9273 InputInfo.PointersArray.getPointer(),
9274 InputInfo.SizesArray.getPointer(),
9275 MapTypesArray,
9276 NumTeams,
9277 NumThreads};
Samuel Antaob68e2db2016-03-03 16:20:23 +00009278 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00009279 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait
9280 : OMPRTL__tgt_target_teams),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009281 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009282 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009283 llvm::Value *OffloadingArgs[] = {DeviceID,
9284 OutlinedFnID,
9285 PointerNum,
9286 InputInfo.BasePointersArray.getPointer(),
9287 InputInfo.PointersArray.getPointer(),
9288 InputInfo.SizesArray.getPointer(),
9289 MapTypesArray};
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009290 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00009291 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait
9292 : OMPRTL__tgt_target),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009293 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009294 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009295
Alexey Bataev2a007e02017-10-02 14:20:58 +00009296 // Check the error code and execute the host version if required.
9297 llvm::BasicBlock *OffloadFailedBlock =
9298 CGF.createBasicBlock("omp_offload.failed");
9299 llvm::BasicBlock *OffloadContBlock =
9300 CGF.createBasicBlock("omp_offload.cont");
9301 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return);
9302 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
9303
9304 CGF.EmitBlock(OffloadFailedBlock);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009305 if (RequiresOuterTask) {
9306 CapturedVars.clear();
9307 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9308 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009309 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev2a007e02017-10-02 14:20:58 +00009310 CGF.EmitBranch(OffloadContBlock);
9311
9312 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00009313 };
9314
Samuel Antaoee8fb302016-01-06 13:42:12 +00009315 // Notify that the host version must be executed.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009316 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars,
9317 RequiresOuterTask](CodeGenFunction &CGF,
9318 PrePostActionTy &) {
9319 if (RequiresOuterTask) {
9320 CapturedVars.clear();
9321 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9322 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009323 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009324 };
9325
9326 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray,
9327 &CapturedVars, RequiresOuterTask,
9328 &CS](CodeGenFunction &CGF, PrePostActionTy &) {
9329 // Fill up the arrays with all the captured variables.
9330 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
9331 MappableExprsHandler::MapValuesArrayTy Pointers;
9332 MappableExprsHandler::MapValuesArrayTy Sizes;
9333 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9334
Alexey Bataev8451efa2018-01-15 19:06:12 +00009335 // Get mappable expression information.
9336 MappableExprsHandler MEHandler(D, CGF);
Alexey Bataev969dbc02018-11-08 15:47:39 +00009337 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
Alexey Bataev8451efa2018-01-15 19:06:12 +00009338
9339 auto RI = CS.getCapturedRecordDecl()->field_begin();
9340 auto CV = CapturedVars.begin();
9341 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
9342 CE = CS.capture_end();
9343 CI != CE; ++CI, ++RI, ++CV) {
Alexey Bataevb3638132018-07-19 16:34:13 +00009344 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers;
9345 MappableExprsHandler::MapValuesArrayTy CurPointers;
9346 MappableExprsHandler::MapValuesArrayTy CurSizes;
9347 MappableExprsHandler::MapFlagsArrayTy CurMapTypes;
9348 MappableExprsHandler::StructRangeInfoTy PartialStruct;
Alexey Bataev8451efa2018-01-15 19:06:12 +00009349
9350 // VLA sizes are passed to the outlined region by copy and do not have map
9351 // information associated.
9352 if (CI->capturesVariableArrayType()) {
9353 CurBasePointers.push_back(*CV);
9354 CurPointers.push_back(*CV);
Alexey Bataeva90fc662019-06-25 16:00:43 +00009355 CurSizes.push_back(CGF.Builder.CreateIntCast(
9356 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev8451efa2018-01-15 19:06:12 +00009357 // Copy to the device as an argument. No need to retrieve it.
9358 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL |
Alexey Bataevf288cf92019-06-27 18:53:07 +00009359 MappableExprsHandler::OMP_MAP_TARGET_PARAM |
9360 MappableExprsHandler::OMP_MAP_IMPLICIT);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009361 } else {
9362 // If we have any information in the map clause, we use it, otherwise we
9363 // just do a default mapping.
9364 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00009365 CurSizes, CurMapTypes, PartialStruct);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009366 if (CurBasePointers.empty())
9367 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers,
9368 CurPointers, CurSizes, CurMapTypes);
Alexey Bataev60705422018-10-30 15:50:12 +00009369 // Generate correct mapping for variables captured by reference in
9370 // lambdas.
9371 if (CI->capturesVariable())
Alexey Bataev969dbc02018-11-08 15:47:39 +00009372 MEHandler.generateInfoForLambdaCaptures(
9373 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes,
9374 CurMapTypes, LambdaPointers);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009375 }
9376 // We expect to have at least an element of information for this capture.
9377 assert(!CurBasePointers.empty() &&
9378 "Non-existing map pointer for capture!");
9379 assert(CurBasePointers.size() == CurPointers.size() &&
9380 CurBasePointers.size() == CurSizes.size() &&
9381 CurBasePointers.size() == CurMapTypes.size() &&
9382 "Inconsistent map information sizes!");
9383
Alexey Bataevb3638132018-07-19 16:34:13 +00009384 // If there is an entry in PartialStruct it means we have a struct with
9385 // individual members mapped. Emit an extra combined entry.
9386 if (PartialStruct.Base.isValid())
9387 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes,
9388 CurMapTypes, PartialStruct);
9389
Alexey Bataev8451efa2018-01-15 19:06:12 +00009390 // We need to append the results of this capture to what we already have.
9391 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
9392 Pointers.append(CurPointers.begin(), CurPointers.end());
9393 Sizes.append(CurSizes.begin(), CurSizes.end());
9394 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end());
9395 }
Alexey Bataev60705422018-10-30 15:50:12 +00009396 // Adjust MEMBER_OF flags for the lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00009397 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers,
9398 Pointers, MapTypes);
Alexey Bataev92327c52018-03-26 16:40:55 +00009399 // Map other list items in the map clause which are not captured variables
9400 // but "declare target link" global variables.
Alexey Bataevb3638132018-07-19 16:34:13 +00009401 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes,
9402 MapTypes);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009403
9404 TargetDataInfo Info;
9405 // Fill up the arrays and create the arguments.
9406 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
9407 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
9408 Info.PointersArray, Info.SizesArray,
9409 Info.MapTypesArray, Info);
9410 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
9411 InputInfo.BasePointersArray =
9412 Address(Info.BasePointersArray, CGM.getPointerAlign());
9413 InputInfo.PointersArray =
9414 Address(Info.PointersArray, CGM.getPointerAlign());
9415 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign());
9416 MapTypesArray = Info.MapTypesArray;
9417 if (RequiresOuterTask)
9418 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
9419 else
9420 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
9421 };
9422
9423 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask](
9424 CodeGenFunction &CGF, PrePostActionTy &) {
9425 if (RequiresOuterTask) {
9426 CodeGenFunction::OMPTargetDataInfo InputInfo;
9427 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo);
9428 } else {
9429 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen);
9430 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009431 };
9432
9433 // If we have a target function ID it means that we need to support
9434 // offloading, otherwise, just execute on the host. We need to execute on host
9435 // regardless of the conditional in the if clause if, e.g., the user do not
9436 // specify target triples.
9437 if (OutlinedFnID) {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009438 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -05009439 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009440 } else {
9441 RegionCodeGenTy ThenRCG(TargetThenGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00009442 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00009443 }
9444 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009445 RegionCodeGenTy ElseRCG(TargetElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00009446 ElseRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00009447 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009448}
Samuel Antaoee8fb302016-01-06 13:42:12 +00009449
9450void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
9451 StringRef ParentName) {
9452 if (!S)
9453 return;
9454
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009455 // Codegen OMP target directives that offload compute to the device.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009456 bool RequiresDeviceCodegen =
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009457 isa<OMPExecutableDirective>(S) &&
9458 isOpenMPTargetExecutionDirective(
9459 cast<OMPExecutableDirective>(S)->getDirectiveKind());
Samuel Antaoee8fb302016-01-06 13:42:12 +00009460
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009461 if (RequiresDeviceCodegen) {
9462 const auto &E = *cast<OMPExecutableDirective>(S);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009463 unsigned DeviceID;
9464 unsigned FileID;
9465 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009466 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID,
Samuel Antao2de62b02016-02-13 23:35:10 +00009467 FileID, Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009468
9469 // Is this a target region that should not be emitted as an entry point? If
9470 // so just signal we are done with this target region.
Samuel Antao2de62b02016-02-13 23:35:10 +00009471 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
9472 ParentName, Line))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009473 return;
9474
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009475 switch (E.getDirectiveKind()) {
9476 case OMPD_target:
9477 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName,
9478 cast<OMPTargetDirective>(E));
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009479 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009480 case OMPD_target_parallel:
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009481 CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009482 CGM, ParentName, cast<OMPTargetParallelDirective>(E));
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009483 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009484 case OMPD_target_teams:
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009485 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009486 CGM, ParentName, cast<OMPTargetTeamsDirective>(E));
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009487 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009488 case OMPD_target_teams_distribute:
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009489 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009490 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E));
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009491 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009492 case OMPD_target_teams_distribute_simd:
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009493 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009494 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E));
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009495 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009496 case OMPD_target_parallel_for:
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009497 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009498 CGM, ParentName, cast<OMPTargetParallelForDirective>(E));
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009499 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009500 case OMPD_target_parallel_for_simd:
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009501 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009502 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E));
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009503 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009504 case OMPD_target_simd:
Alexey Bataevf8365372017-11-17 17:57:25 +00009505 CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009506 CGM, ParentName, cast<OMPTargetSimdDirective>(E));
Alexey Bataevf8365372017-11-17 17:57:25 +00009507 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009508 case OMPD_target_teams_distribute_parallel_for:
Carlo Bertolli52978c32018-01-03 21:12:44 +00009509 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
9510 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009511 cast<OMPTargetTeamsDistributeParallelForDirective>(E));
Carlo Bertolli52978c32018-01-03 21:12:44 +00009512 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009513 case OMPD_target_teams_distribute_parallel_for_simd:
Alexey Bataev647dd842018-01-15 20:59:40 +00009514 CodeGenFunction::
9515 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
9516 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009517 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E));
Alexey Bataev647dd842018-01-15 20:59:40 +00009518 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009519 case OMPD_parallel:
9520 case OMPD_for:
9521 case OMPD_parallel_for:
cchen47d60942019-12-05 13:43:48 -05009522 case OMPD_parallel_master:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009523 case OMPD_parallel_sections:
9524 case OMPD_for_simd:
9525 case OMPD_parallel_for_simd:
9526 case OMPD_cancel:
9527 case OMPD_cancellation_point:
9528 case OMPD_ordered:
9529 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00009530 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009531 case OMPD_task:
9532 case OMPD_simd:
9533 case OMPD_sections:
9534 case OMPD_section:
9535 case OMPD_single:
9536 case OMPD_master:
9537 case OMPD_critical:
9538 case OMPD_taskyield:
9539 case OMPD_barrier:
9540 case OMPD_taskwait:
9541 case OMPD_taskgroup:
9542 case OMPD_atomic:
9543 case OMPD_flush:
9544 case OMPD_teams:
9545 case OMPD_target_data:
9546 case OMPD_target_exit_data:
9547 case OMPD_target_enter_data:
9548 case OMPD_distribute:
9549 case OMPD_distribute_simd:
9550 case OMPD_distribute_parallel_for:
9551 case OMPD_distribute_parallel_for_simd:
9552 case OMPD_teams_distribute:
9553 case OMPD_teams_distribute_simd:
9554 case OMPD_teams_distribute_parallel_for:
9555 case OMPD_teams_distribute_parallel_for_simd:
9556 case OMPD_target_update:
9557 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00009558 case OMPD_declare_variant:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009559 case OMPD_declare_target:
9560 case OMPD_end_declare_target:
9561 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00009562 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009563 case OMPD_taskloop:
9564 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +00009565 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +00009566 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +00009567 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -04009568 case OMPD_parallel_master_taskloop_simd:
Kelvin Li1408f912018-09-26 04:28:39 +00009569 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009570 case OMPD_unknown:
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009571 llvm_unreachable("Unknown target directive for OpenMP device codegen.");
9572 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009573 return;
9574 }
9575
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009576 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
Alexey Bataev475a7442018-01-12 19:39:11 +00009577 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009578 return;
9579
9580 scanForTargetRegionsFunctions(
Alexey Bataev475a7442018-01-12 19:39:11 +00009581 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009582 return;
9583 }
9584
9585 // If this is a lambda function, look into its body.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009586 if (const auto *L = dyn_cast<LambdaExpr>(S))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009587 S = L->getBody();
9588
9589 // Keep looking for target regions recursively.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009590 for (const Stmt *II : S->children())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009591 scanForTargetRegionsFunctions(II, ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009592}
9593
9594bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009595 // If emitting code for the host, we do not process FD here. Instead we do
9596 // the normal code generation.
Alexey Bataev729e2422019-08-23 16:11:14 +00009597 if (!CGM.getLangOpts().OpenMPIsDevice) {
9598 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) {
9599 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9600 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9601 // Do not emit device_type(nohost) functions for the host.
9602 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
9603 return true;
9604 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009605 return false;
Alexey Bataev729e2422019-08-23 16:11:14 +00009606 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009607
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009608 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009609 // Try to detect target regions in the function.
Alexey Bataev729e2422019-08-23 16:11:14 +00009610 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) {
Alexey Bataev45588422020-01-07 14:11:45 -05009611 StringRef Name = CGM.getMangledName(GD);
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009612 scanForTargetRegionsFunctions(FD->getBody(), Name);
Alexey Bataev729e2422019-08-23 16:11:14 +00009613 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9614 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9615 // Do not emit device_type(nohost) functions for the host.
9616 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
9617 return true;
9618 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009619
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009620 // Do not to emit function if it is not marked as declare target.
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009621 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
Alexey Bataev45588422020-01-07 14:11:45 -05009622 AlreadyEmittedTargetDecls.count(VD) == 0;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009623}
9624
9625bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
9626 if (!CGM.getLangOpts().OpenMPIsDevice)
9627 return false;
9628
9629 // Check if there are Ctors/Dtors in this declaration and look for target
9630 // regions in it. We use the complete variant to produce the kernel name
9631 // mangling.
9632 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009633 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
9634 for (const CXXConstructorDecl *Ctor : RD->ctors()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009635 StringRef ParentName =
9636 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
9637 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
9638 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009639 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009640 StringRef ParentName =
9641 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
9642 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
9643 }
9644 }
9645
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009646 // Do not to emit variable if it is not marked as declare target.
Alexey Bataev92327c52018-03-26 16:40:55 +00009647 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009648 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
9649 cast<VarDecl>(GD.getDecl()));
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009650 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
9651 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9652 HasRequiresUnifiedSharedMemory)) {
Alexey Bataevd01b7492018-08-15 19:45:12 +00009653 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009654 return true;
9655 }
9656 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009657}
9658
Alexey Bataev1af5bd52019-03-05 17:47:18 +00009659llvm::Constant *
9660CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF,
9661 const VarDecl *VD) {
9662 assert(VD->getType().isConstant(CGM.getContext()) &&
9663 "Expected constant variable.");
9664 StringRef VarName;
9665 llvm::Constant *Addr;
9666 llvm::GlobalValue::LinkageTypes Linkage;
9667 QualType Ty = VD->getType();
9668 SmallString<128> Buffer;
9669 {
9670 unsigned DeviceID;
9671 unsigned FileID;
9672 unsigned Line;
9673 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID,
9674 FileID, Line);
9675 llvm::raw_svector_ostream OS(Buffer);
9676 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID)
9677 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
9678 VarName = OS.str();
9679 }
9680 Linkage = llvm::GlobalValue::InternalLinkage;
9681 Addr =
9682 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName,
9683 getDefaultFirstprivateAddressSpace());
9684 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage);
9685 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty);
9686 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr));
9687 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9688 VarName, Addr, VarSize,
9689 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage);
9690 return Addr;
9691}
9692
Alexey Bataev03f270c2018-03-30 18:31:07 +00009693void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
9694 llvm::Constant *Addr) {
Alexey Bataev36724b72019-10-03 16:46:49 +00009695 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
9696 !CGM.getLangOpts().OpenMPIsDevice)
Alexey Bataev4db9dc62019-09-23 15:53:51 +00009697 return;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009698 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9699 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
9700 if (!Res) {
9701 if (CGM.getLangOpts().OpenMPIsDevice) {
9702 // Register non-target variables being emitted in device code (debug info
9703 // may cause this).
9704 StringRef VarName = CGM.getMangledName(VD);
9705 EmittedNonTargetVariables.try_emplace(VarName, Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009706 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009707 return;
Alexey Bataev03f270c2018-03-30 18:31:07 +00009708 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009709 // Register declare target variables.
9710 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
9711 StringRef VarName;
9712 CharUnits VarSize;
9713 llvm::GlobalValue::LinkageTypes Linkage;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009714
9715 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9716 !HasRequiresUnifiedSharedMemory) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009717 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9718 VarName = CGM.getMangledName(VD);
9719 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) {
9720 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType());
9721 assert(!VarSize.isZero() && "Expected non-zero size of the variable");
9722 } else {
9723 VarSize = CharUnits::Zero();
9724 }
9725 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
9726 // Temp solution to prevent optimizations of the internal variables.
9727 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) {
9728 std::string RefName = getName({VarName, "ref"});
9729 if (!CGM.GetGlobalValue(RefName)) {
9730 llvm::Constant *AddrRef =
9731 getOrCreateInternalVariable(Addr->getType(), RefName);
9732 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef);
9733 GVAddrRef->setConstant(/*Val=*/true);
9734 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage);
9735 GVAddrRef->setInitializer(Addr);
9736 CGM.addCompilerUsedGlobal(GVAddrRef);
9737 }
9738 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009739 } else {
9740 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
9741 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9742 HasRequiresUnifiedSharedMemory)) &&
9743 "Declare target attribute must link or to with unified memory.");
9744 if (*Res == OMPDeclareTargetDeclAttr::MT_Link)
9745 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink;
9746 else
9747 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9748
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009749 if (CGM.getLangOpts().OpenMPIsDevice) {
9750 VarName = Addr->getName();
9751 Addr = nullptr;
9752 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009753 VarName = getAddrOfDeclareTargetVar(VD).getName();
9754 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009755 }
9756 VarSize = CGM.getPointerSize();
9757 Linkage = llvm::GlobalValue::WeakAnyLinkage;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009758 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009759
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009760 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9761 VarName, Addr, VarSize, Flags, Linkage);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009762}
9763
Samuel Antaoee8fb302016-01-06 13:42:12 +00009764bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009765 if (isa<FunctionDecl>(GD.getDecl()) ||
9766 isa<OMPDeclareReductionDecl>(GD.getDecl()))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009767 return emitTargetFunctions(GD);
9768
9769 return emitTargetGlobalVariable(GD);
9770}
9771
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009772void CGOpenMPRuntime::emitDeferredTargetDecls() const {
9773 for (const VarDecl *VD : DeferredGlobalVariables) {
9774 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009775 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009776 if (!Res)
9777 continue;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009778 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9779 !HasRequiresUnifiedSharedMemory) {
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009780 CGM.EmitGlobal(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009781 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009782 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
9783 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9784 HasRequiresUnifiedSharedMemory)) &&
9785 "Expected link clause or to clause with unified memory.");
9786 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009787 }
9788 }
9789}
9790
Alexey Bataev60705422018-10-30 15:50:12 +00009791void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas(
9792 CodeGenFunction &CGF, const OMPExecutableDirective &D) const {
9793 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) &&
9794 " Expected target-based directive.");
9795}
9796
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05009797void CGOpenMPRuntime::processRequiresDirective(const OMPRequiresDecl *D) {
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009798 for (const OMPClause *Clause : D->clauselists()) {
9799 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
9800 HasRequiresUnifiedSharedMemory = true;
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05009801 } else if (const auto *AC =
9802 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) {
9803 switch (AC->getAtomicDefaultMemOrderKind()) {
9804 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel:
9805 RequiresAtomicOrdering = llvm::AtomicOrdering::AcquireRelease;
9806 break;
9807 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst:
9808 RequiresAtomicOrdering = llvm::AtomicOrdering::SequentiallyConsistent;
9809 break;
9810 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed:
9811 RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic;
9812 break;
9813 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown:
9814 break;
9815 }
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009816 }
9817 }
9818}
9819
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05009820llvm::AtomicOrdering CGOpenMPRuntime::getDefaultMemoryOrdering() const {
9821 return RequiresAtomicOrdering;
9822}
9823
Alexey Bataevc5687252019-03-21 19:35:27 +00009824bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD,
9825 LangAS &AS) {
9826 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())
9827 return false;
9828 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
9829 switch(A->getAllocatorType()) {
9830 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
9831 // Not supported, fallback to the default mem space.
9832 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
9833 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
9834 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
9835 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
9836 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
9837 case OMPAllocateDeclAttr::OMPConstMemAlloc:
9838 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
9839 AS = LangAS::Default;
9840 return true;
9841 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
9842 llvm_unreachable("Expected predefined allocator for the variables with the "
9843 "static storage.");
9844 }
9845 return false;
9846}
9847
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00009848bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const {
9849 return HasRequiresUnifiedSharedMemory;
9850}
9851
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009852CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
9853 CodeGenModule &CGM)
9854 : CGM(CGM) {
9855 if (CGM.getLangOpts().OpenMPIsDevice) {
9856 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
9857 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
9858 }
9859}
9860
9861CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() {
9862 if (CGM.getLangOpts().OpenMPIsDevice)
9863 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
9864}
9865
Alexey Bataev6d944102018-05-02 15:45:28 +00009866bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009867 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal)
9868 return true;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009869
Alexey Bataev6d944102018-05-02 15:45:28 +00009870 const auto *D = cast<FunctionDecl>(GD.getDecl());
Alexey Bataev34f8a702018-03-28 14:28:54 +00009871 // Do not to emit function if it is marked as declare target as it was already
9872 // emitted.
Alexey Bataev97b72212018-08-14 18:31:20 +00009873 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
Alexey Bataev45588422020-01-07 14:11:45 -05009874 if (D->hasBody() && AlreadyEmittedTargetDecls.count(D) == 0) {
9875 if (auto *F = dyn_cast_or_null<llvm::Function>(
9876 CGM.GetGlobalValue(CGM.getMangledName(GD))))
Alexey Bataev34f8a702018-03-28 14:28:54 +00009877 return !F->isDeclaration();
9878 return false;
9879 }
9880 return true;
9881 }
9882
Alexey Bataev45588422020-01-07 14:11:45 -05009883 return !AlreadyEmittedTargetDecls.insert(D).second;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009884}
9885
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009886llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() {
9887 // If we don't have entries or if we are emitting code for the device, we
9888 // don't need to do anything.
9889 if (CGM.getLangOpts().OMPTargetTriples.empty() ||
9890 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice ||
9891 (OffloadEntriesInfoManager.empty() &&
9892 !HasEmittedDeclareTargetRegion &&
9893 !HasEmittedTargetRegion))
9894 return nullptr;
9895
9896 // Create and register the function that handles the requires directives.
9897 ASTContext &C = CGM.getContext();
9898
9899 llvm::Function *RequiresRegFn;
9900 {
9901 CodeGenFunction CGF(CGM);
9902 const auto &FI = CGM.getTypes().arrangeNullaryFunction();
9903 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
9904 std::string ReqName = getName({"omp_offloading", "requires_reg"});
9905 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI);
9906 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {});
9907 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE;
9908 // TODO: check for other requires clauses.
9909 // The requires directive takes effect only when a target region is
9910 // present in the compilation unit. Otherwise it is ignored and not
9911 // passed to the runtime. This avoids the runtime from throwing an error
9912 // for mismatching requires clauses across compilation units that don't
9913 // contain at least 1 target region.
9914 assert((HasEmittedTargetRegion ||
9915 HasEmittedDeclareTargetRegion ||
9916 !OffloadEntriesInfoManager.empty()) &&
9917 "Target or declare target region expected.");
9918 if (HasRequiresUnifiedSharedMemory)
9919 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY;
9920 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires),
9921 llvm::ConstantInt::get(CGM.Int64Ty, Flags));
9922 CGF.FinishFunction();
9923 }
9924 return RequiresRegFn;
9925}
9926
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009927void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
9928 const OMPExecutableDirective &D,
9929 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00009930 llvm::Function *OutlinedFn,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009931 ArrayRef<llvm::Value *> CapturedVars) {
9932 if (!CGF.HaveInsertPoint())
9933 return;
9934
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009935 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009936 CodeGenFunction::RunCleanupsScope Scope(CGF);
9937
9938 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
9939 llvm::Value *Args[] = {
9940 RTLoc,
9941 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
9942 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
9943 llvm::SmallVector<llvm::Value *, 16> RealArgs;
9944 RealArgs.append(std::begin(Args), std::end(Args));
9945 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
9946
James Y Knight9871db02019-02-05 16:42:33 +00009947 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009948 CGF.EmitRuntimeCall(RTLFn, RealArgs);
9949}
9950
9951void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
Carlo Bertollic6872252016-04-04 15:55:02 +00009952 const Expr *NumTeams,
9953 const Expr *ThreadLimit,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009954 SourceLocation Loc) {
9955 if (!CGF.HaveInsertPoint())
9956 return;
9957
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009958 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009959
Carlo Bertollic6872252016-04-04 15:55:02 +00009960 llvm::Value *NumTeamsVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009961 NumTeams
Carlo Bertollic6872252016-04-04 15:55:02 +00009962 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
9963 CGF.CGM.Int32Ty, /* isSigned = */ true)
9964 : CGF.Builder.getInt32(0);
9965
9966 llvm::Value *ThreadLimitVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009967 ThreadLimit
Carlo Bertollic6872252016-04-04 15:55:02 +00009968 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
9969 CGF.CGM.Int32Ty, /* isSigned = */ true)
9970 : CGF.Builder.getInt32(0);
9971
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009972 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
Carlo Bertollic6872252016-04-04 15:55:02 +00009973 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
9974 ThreadLimitVal};
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009975 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams),
9976 PushNumTeamsArgs);
9977}
Samuel Antaodf158d52016-04-27 22:58:19 +00009978
Samuel Antaocc10b852016-07-28 14:23:26 +00009979void CGOpenMPRuntime::emitTargetDataCalls(
9980 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
9981 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009982 if (!CGF.HaveInsertPoint())
9983 return;
9984
Samuel Antaocc10b852016-07-28 14:23:26 +00009985 // Action used to replace the default codegen action and turn privatization
9986 // off.
9987 PrePostActionTy NoPrivAction;
Samuel Antaodf158d52016-04-27 22:58:19 +00009988
9989 // Generate the code for the opening of the data environment. Capture all the
9990 // arguments of the runtime call by reference because they are used in the
9991 // closing of the region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009992 auto &&BeginThenGen = [this, &D, Device, &Info,
9993 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009994 // Fill up the arrays with all the mapped variables.
Samuel Antaocc10b852016-07-28 14:23:26 +00009995 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
Samuel Antaodf158d52016-04-27 22:58:19 +00009996 MappableExprsHandler::MapValuesArrayTy Pointers;
9997 MappableExprsHandler::MapValuesArrayTy Sizes;
9998 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9999
10000 // Get map clause information.
10001 MappableExprsHandler MCHandler(D, CGF);
10002 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
Samuel Antaodf158d52016-04-27 22:58:19 +000010003
10004 // Fill up the arrays and create the arguments.
Samuel Antaocc10b852016-07-28 14:23:26 +000010005 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +000010006
10007 llvm::Value *BasePointersArrayArg = nullptr;
10008 llvm::Value *PointersArrayArg = nullptr;
10009 llvm::Value *SizesArrayArg = nullptr;
10010 llvm::Value *MapTypesArrayArg = nullptr;
10011 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +000010012 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +000010013
10014 // Emit device ID if any.
10015 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010016 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +000010017 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010018 CGF.Int64Ty, /*isSigned=*/true);
10019 } else {
10020 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10021 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010022
10023 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010024 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +000010025
10026 llvm::Value *OffloadingArgs[] = {
10027 DeviceID, PointerNum, BasePointersArrayArg,
10028 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010029 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin),
Samuel Antaodf158d52016-04-27 22:58:19 +000010030 OffloadingArgs);
Samuel Antaocc10b852016-07-28 14:23:26 +000010031
10032 // If device pointer privatization is required, emit the body of the region
10033 // here. It will have to be duplicated: with and without privatization.
10034 if (!Info.CaptureDeviceAddrMap.empty())
10035 CodeGen(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010036 };
10037
10038 // Generate code for the closing of the data region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010039 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF,
10040 PrePostActionTy &) {
Samuel Antaocc10b852016-07-28 14:23:26 +000010041 assert(Info.isValid() && "Invalid data environment closing arguments.");
Samuel Antaodf158d52016-04-27 22:58:19 +000010042
10043 llvm::Value *BasePointersArrayArg = nullptr;
10044 llvm::Value *PointersArrayArg = nullptr;
10045 llvm::Value *SizesArrayArg = nullptr;
10046 llvm::Value *MapTypesArrayArg = nullptr;
10047 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +000010048 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +000010049
10050 // Emit device ID if any.
10051 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010052 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +000010053 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010054 CGF.Int64Ty, /*isSigned=*/true);
10055 } else {
10056 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10057 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010058
10059 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010060 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +000010061
10062 llvm::Value *OffloadingArgs[] = {
10063 DeviceID, PointerNum, BasePointersArrayArg,
10064 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010065 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end),
Samuel Antaodf158d52016-04-27 22:58:19 +000010066 OffloadingArgs);
10067 };
10068
Samuel Antaocc10b852016-07-28 14:23:26 +000010069 // If we need device pointer privatization, we need to emit the body of the
10070 // region with no privatization in the 'else' branch of the conditional.
10071 // Otherwise, we don't have to do anything.
10072 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF,
10073 PrePostActionTy &) {
10074 if (!Info.CaptureDeviceAddrMap.empty()) {
10075 CodeGen.setAction(NoPrivAction);
10076 CodeGen(CGF);
10077 }
10078 };
10079
10080 // We don't have to do anything to close the region if the if clause evaluates
10081 // to false.
10082 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
Samuel Antaodf158d52016-04-27 22:58:19 +000010083
10084 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -050010085 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +000010086 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +000010087 RegionCodeGenTy RCG(BeginThenGen);
10088 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010089 }
10090
Samuel Antaocc10b852016-07-28 14:23:26 +000010091 // If we don't require privatization of device pointers, we emit the body in
10092 // between the runtime calls. This avoids duplicating the body code.
10093 if (Info.CaptureDeviceAddrMap.empty()) {
10094 CodeGen.setAction(NoPrivAction);
10095 CodeGen(CGF);
10096 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010097
10098 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -050010099 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +000010100 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +000010101 RegionCodeGenTy RCG(EndThenGen);
10102 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010103 }
10104}
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010105
Samuel Antao8d2d7302016-05-26 18:30:22 +000010106void CGOpenMPRuntime::emitTargetDataStandAloneCall(
Samuel Antao8dd66282016-04-27 23:14:30 +000010107 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10108 const Expr *Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010109 if (!CGF.HaveInsertPoint())
10110 return;
10111
Samuel Antao8dd66282016-04-27 23:14:30 +000010112 assert((isa<OMPTargetEnterDataDirective>(D) ||
Samuel Antao8d2d7302016-05-26 18:30:22 +000010113 isa<OMPTargetExitDataDirective>(D) ||
10114 isa<OMPTargetUpdateDirective>(D)) &&
10115 "Expecting either target enter, exit data, or update directives.");
Samuel Antao8dd66282016-04-27 23:14:30 +000010116
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010117 CodeGenFunction::OMPTargetDataInfo InputInfo;
10118 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010119 // Generate the code for the opening of the data environment.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010120 auto &&ThenGen = [this, &D, Device, &InputInfo,
10121 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010122 // Emit device ID if any.
10123 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010124 if (Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010125 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010126 CGF.Int64Ty, /*isSigned=*/true);
10127 } else {
10128 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10129 }
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010130
10131 // Emit the number of elements in the offloading arrays.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010132 llvm::Constant *PointerNum =
10133 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010134
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010135 llvm::Value *OffloadingArgs[] = {DeviceID,
10136 PointerNum,
10137 InputInfo.BasePointersArray.getPointer(),
10138 InputInfo.PointersArray.getPointer(),
10139 InputInfo.SizesArray.getPointer(),
10140 MapTypesArray};
Samuel Antao8d2d7302016-05-26 18:30:22 +000010141
Samuel Antao8d2d7302016-05-26 18:30:22 +000010142 // Select the right runtime function call for each expected standalone
10143 // directive.
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010144 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Samuel Antao8d2d7302016-05-26 18:30:22 +000010145 OpenMPRTLFunction RTLFn;
10146 switch (D.getDirectiveKind()) {
Samuel Antao8d2d7302016-05-26 18:30:22 +000010147 case OMPD_target_enter_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010148 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait
10149 : OMPRTL__tgt_target_data_begin;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010150 break;
10151 case OMPD_target_exit_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010152 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait
10153 : OMPRTL__tgt_target_data_end;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010154 break;
10155 case OMPD_target_update:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010156 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait
10157 : OMPRTL__tgt_target_data_update;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010158 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010159 case OMPD_parallel:
10160 case OMPD_for:
10161 case OMPD_parallel_for:
cchen47d60942019-12-05 13:43:48 -050010162 case OMPD_parallel_master:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010163 case OMPD_parallel_sections:
10164 case OMPD_for_simd:
10165 case OMPD_parallel_for_simd:
10166 case OMPD_cancel:
10167 case OMPD_cancellation_point:
10168 case OMPD_ordered:
10169 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +000010170 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010171 case OMPD_task:
10172 case OMPD_simd:
10173 case OMPD_sections:
10174 case OMPD_section:
10175 case OMPD_single:
10176 case OMPD_master:
10177 case OMPD_critical:
10178 case OMPD_taskyield:
10179 case OMPD_barrier:
10180 case OMPD_taskwait:
10181 case OMPD_taskgroup:
10182 case OMPD_atomic:
10183 case OMPD_flush:
10184 case OMPD_teams:
10185 case OMPD_target_data:
10186 case OMPD_distribute:
10187 case OMPD_distribute_simd:
10188 case OMPD_distribute_parallel_for:
10189 case OMPD_distribute_parallel_for_simd:
10190 case OMPD_teams_distribute:
10191 case OMPD_teams_distribute_simd:
10192 case OMPD_teams_distribute_parallel_for:
10193 case OMPD_teams_distribute_parallel_for_simd:
10194 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +000010195 case OMPD_declare_variant:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010196 case OMPD_declare_target:
10197 case OMPD_end_declare_target:
10198 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +000010199 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010200 case OMPD_taskloop:
10201 case OMPD_taskloop_simd:
Alexey Bataev60e51c42019-10-10 20:13:02 +000010202 case OMPD_master_taskloop:
Alexey Bataevb8552ab2019-10-18 16:47:35 +000010203 case OMPD_master_taskloop_simd:
Alexey Bataev5bbcead2019-10-14 17:17:41 +000010204 case OMPD_parallel_master_taskloop:
Alexey Bataev14a388f2019-10-25 10:27:13 -040010205 case OMPD_parallel_master_taskloop_simd:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010206 case OMPD_target:
10207 case OMPD_target_simd:
10208 case OMPD_target_teams_distribute:
10209 case OMPD_target_teams_distribute_simd:
10210 case OMPD_target_teams_distribute_parallel_for:
10211 case OMPD_target_teams_distribute_parallel_for_simd:
10212 case OMPD_target_teams:
10213 case OMPD_target_parallel:
10214 case OMPD_target_parallel_for:
10215 case OMPD_target_parallel_for_simd:
Kelvin Li1408f912018-09-26 04:28:39 +000010216 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010217 case OMPD_unknown:
10218 llvm_unreachable("Unexpected standalone target data directive.");
10219 break;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010220 }
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010221 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010222 };
10223
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010224 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray](
10225 CodeGenFunction &CGF, PrePostActionTy &) {
10226 // Fill up the arrays with all the mapped variables.
10227 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
10228 MappableExprsHandler::MapValuesArrayTy Pointers;
10229 MappableExprsHandler::MapValuesArrayTy Sizes;
10230 MappableExprsHandler::MapFlagsArrayTy MapTypes;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010231
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010232 // Get map clause information.
10233 MappableExprsHandler MEHandler(D, CGF);
10234 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
10235
10236 TargetDataInfo Info;
10237 // Fill up the arrays and create the arguments.
10238 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
10239 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
10240 Info.PointersArray, Info.SizesArray,
10241 Info.MapTypesArray, Info);
10242 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
10243 InputInfo.BasePointersArray =
10244 Address(Info.BasePointersArray, CGM.getPointerAlign());
10245 InputInfo.PointersArray =
10246 Address(Info.PointersArray, CGM.getPointerAlign());
10247 InputInfo.SizesArray =
10248 Address(Info.SizesArray, CGM.getPointerAlign());
10249 MapTypesArray = Info.MapTypesArray;
10250 if (D.hasClausesOfKind<OMPDependClause>())
10251 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
10252 else
Alexey Bataev768f1f22018-01-09 19:59:25 +000010253 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010254 };
10255
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010256 if (IfCond) {
Alexey Bataev1d943ae2019-11-19 12:12:23 -050010257 emitIfClause(CGF, IfCond, TargetThenGen,
10258 [](CodeGenFunction &CGF, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010259 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010260 RegionCodeGenTy ThenRCG(TargetThenGen);
10261 ThenRCG(CGF);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010262 }
10263}
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010264
10265namespace {
10266 /// Kind of parameter in a function with 'declare simd' directive.
10267 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector };
10268 /// Attribute set of the parameter.
10269 struct ParamAttrTy {
10270 ParamKindTy Kind = Vector;
10271 llvm::APSInt StrideOrArg;
10272 llvm::APSInt Alignment;
10273 };
10274} // namespace
10275
10276static unsigned evaluateCDTSize(const FunctionDecl *FD,
10277 ArrayRef<ParamAttrTy> ParamAttrs) {
10278 // Every vector variant of a SIMD-enabled function has a vector length (VLEN).
10279 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument
10280 // of that clause. The VLEN value must be power of 2.
10281 // In other case the notion of the function`s "characteristic data type" (CDT)
10282 // is used to compute the vector length.
10283 // CDT is defined in the following order:
10284 // a) For non-void function, the CDT is the return type.
10285 // b) If the function has any non-uniform, non-linear parameters, then the
10286 // CDT is the type of the first such parameter.
10287 // c) If the CDT determined by a) or b) above is struct, union, or class
10288 // type which is pass-by-value (except for the type that maps to the
10289 // built-in complex data type), the characteristic data type is int.
10290 // d) If none of the above three cases is applicable, the CDT is int.
10291 // The VLEN is then determined based on the CDT and the size of vector
10292 // register of that ISA for which current vector version is generated. The
10293 // VLEN is computed using the formula below:
10294 // VLEN = sizeof(vector_register) / sizeof(CDT),
10295 // where vector register size specified in section 3.2.1 Registers and the
10296 // Stack Frame of original AMD64 ABI document.
10297 QualType RetType = FD->getReturnType();
10298 if (RetType.isNull())
10299 return 0;
10300 ASTContext &C = FD->getASTContext();
10301 QualType CDT;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010302 if (!RetType.isNull() && !RetType->isVoidType()) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010303 CDT = RetType;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010304 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010305 unsigned Offset = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010306 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010307 if (ParamAttrs[Offset].Kind == Vector)
10308 CDT = C.getPointerType(C.getRecordType(MD->getParent()));
10309 ++Offset;
10310 }
10311 if (CDT.isNull()) {
10312 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10313 if (ParamAttrs[I + Offset].Kind == Vector) {
10314 CDT = FD->getParamDecl(I)->getType();
10315 break;
10316 }
10317 }
10318 }
10319 }
10320 if (CDT.isNull())
10321 CDT = C.IntTy;
10322 CDT = CDT->getCanonicalTypeUnqualified();
10323 if (CDT->isRecordType() || CDT->isUnionType())
10324 CDT = C.IntTy;
10325 return C.getTypeSize(CDT);
10326}
10327
10328static void
10329emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
Benjamin Kramer81cb4b72016-11-24 16:01:20 +000010330 const llvm::APSInt &VLENVal,
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010331 ArrayRef<ParamAttrTy> ParamAttrs,
10332 OMPDeclareSimdDeclAttr::BranchStateTy State) {
10333 struct ISADataTy {
10334 char ISA;
10335 unsigned VecRegSize;
10336 };
10337 ISADataTy ISAData[] = {
10338 {
10339 'b', 128
10340 }, // SSE
10341 {
10342 'c', 256
10343 }, // AVX
10344 {
10345 'd', 256
10346 }, // AVX2
10347 {
10348 'e', 512
10349 }, // AVX512
10350 };
10351 llvm::SmallVector<char, 2> Masked;
10352 switch (State) {
10353 case OMPDeclareSimdDeclAttr::BS_Undefined:
10354 Masked.push_back('N');
10355 Masked.push_back('M');
10356 break;
10357 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10358 Masked.push_back('N');
10359 break;
10360 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10361 Masked.push_back('M');
10362 break;
10363 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010364 for (char Mask : Masked) {
10365 for (const ISADataTy &Data : ISAData) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010366 SmallString<256> Buffer;
10367 llvm::raw_svector_ostream Out(Buffer);
10368 Out << "_ZGV" << Data.ISA << Mask;
10369 if (!VLENVal) {
Simon Pilgrim823a99c2019-05-22 13:02:19 +000010370 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs);
10371 assert(NumElts && "Non-zero simdlen/cdtsize expected");
10372 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010373 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010374 Out << VLENVal;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010375 }
10376 for (const ParamAttrTy &ParamAttr : ParamAttrs) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010377 switch (ParamAttr.Kind){
10378 case LinearWithVarStride:
10379 Out << 's' << ParamAttr.StrideOrArg;
10380 break;
10381 case Linear:
10382 Out << 'l';
10383 if (!!ParamAttr.StrideOrArg)
10384 Out << ParamAttr.StrideOrArg;
10385 break;
10386 case Uniform:
10387 Out << 'u';
10388 break;
10389 case Vector:
10390 Out << 'v';
10391 break;
10392 }
10393 if (!!ParamAttr.Alignment)
10394 Out << 'a' << ParamAttr.Alignment;
10395 }
10396 Out << '_' << Fn->getName();
10397 Fn->addFnAttr(Out.str());
10398 }
10399 }
10400}
10401
Alexey Bataeva0a22642019-04-16 13:56:21 +000010402// This are the Functions that are needed to mangle the name of the
10403// vector functions generated by the compiler, according to the rules
10404// defined in the "Vector Function ABI specifications for AArch64",
10405// available at
10406// https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi.
10407
10408/// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI.
10409///
10410/// TODO: Need to implement the behavior for reference marked with a
10411/// var or no linear modifiers (1.b in the section). For this, we
10412/// need to extend ParamKindTy to support the linear modifiers.
10413static bool getAArch64MTV(QualType QT, ParamKindTy Kind) {
10414 QT = QT.getCanonicalType();
10415
10416 if (QT->isVoidType())
10417 return false;
10418
10419 if (Kind == ParamKindTy::Uniform)
10420 return false;
10421
10422 if (Kind == ParamKindTy::Linear)
10423 return false;
10424
10425 // TODO: Handle linear references with modifiers
10426
10427 if (Kind == ParamKindTy::LinearWithVarStride)
10428 return false;
10429
10430 return true;
10431}
10432
10433/// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
10434static bool getAArch64PBV(QualType QT, ASTContext &C) {
10435 QT = QT.getCanonicalType();
10436 unsigned Size = C.getTypeSize(QT);
10437
10438 // Only scalars and complex within 16 bytes wide set PVB to true.
10439 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
10440 return false;
10441
10442 if (QT->isFloatingType())
10443 return true;
10444
10445 if (QT->isIntegerType())
10446 return true;
10447
10448 if (QT->isPointerType())
10449 return true;
10450
10451 // TODO: Add support for complex types (section 3.1.2, item 2).
10452
10453 return false;
10454}
10455
10456/// Computes the lane size (LS) of a return type or of an input parameter,
10457/// as defined by `LS(P)` in 3.2.1 of the AAVFABI.
10458/// TODO: Add support for references, section 3.2.1, item 1.
10459static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) {
10460 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) {
10461 QualType PTy = QT.getCanonicalType()->getPointeeType();
10462 if (getAArch64PBV(PTy, C))
10463 return C.getTypeSize(PTy);
10464 }
10465 if (getAArch64PBV(QT, C))
10466 return C.getTypeSize(QT);
10467
10468 return C.getTypeSize(C.getUIntPtrType());
10469}
10470
10471// Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the
10472// signature of the scalar function, as defined in 3.2.2 of the
10473// AAVFABI.
10474static std::tuple<unsigned, unsigned, bool>
10475getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) {
10476 QualType RetType = FD->getReturnType().getCanonicalType();
10477
10478 ASTContext &C = FD->getASTContext();
10479
10480 bool OutputBecomesInput = false;
10481
10482 llvm::SmallVector<unsigned, 8> Sizes;
10483 if (!RetType->isVoidType()) {
10484 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C));
10485 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {}))
10486 OutputBecomesInput = true;
10487 }
10488 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10489 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType();
10490 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C));
10491 }
10492
10493 assert(!Sizes.empty() && "Unable to determine NDS and WDS.");
10494 // The LS of a function parameter / return value can only be a power
10495 // of 2, starting from 8 bits, up to 128.
10496 assert(std::all_of(Sizes.begin(), Sizes.end(),
10497 [](unsigned Size) {
10498 return Size == 8 || Size == 16 || Size == 32 ||
10499 Size == 64 || Size == 128;
10500 }) &&
10501 "Invalid size");
10502
10503 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)),
10504 *std::max_element(std::begin(Sizes), std::end(Sizes)),
10505 OutputBecomesInput);
10506}
10507
10508/// Mangle the parameter part of the vector function name according to
10509/// their OpenMP classification. The mangling function is defined in
10510/// section 3.5 of the AAVFABI.
10511static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) {
10512 SmallString<256> Buffer;
10513 llvm::raw_svector_ostream Out(Buffer);
10514 for (const auto &ParamAttr : ParamAttrs) {
10515 switch (ParamAttr.Kind) {
10516 case LinearWithVarStride:
10517 Out << "ls" << ParamAttr.StrideOrArg;
10518 break;
10519 case Linear:
10520 Out << 'l';
10521 // Don't print the step value if it is not present or if it is
10522 // equal to 1.
10523 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1)
10524 Out << ParamAttr.StrideOrArg;
10525 break;
10526 case Uniform:
10527 Out << 'u';
10528 break;
10529 case Vector:
10530 Out << 'v';
10531 break;
10532 }
10533
10534 if (!!ParamAttr.Alignment)
10535 Out << 'a' << ParamAttr.Alignment;
10536 }
10537
Benjamin Krameradcd0262020-01-28 20:23:46 +010010538 return std::string(Out.str());
Alexey Bataeva0a22642019-04-16 13:56:21 +000010539}
10540
10541// Function used to add the attribute. The parameter `VLEN` is
10542// templated to allow the use of "x" when targeting scalable functions
10543// for SVE.
10544template <typename T>
10545static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix,
10546 char ISA, StringRef ParSeq,
10547 StringRef MangledName, bool OutputBecomesInput,
10548 llvm::Function *Fn) {
10549 SmallString<256> Buffer;
10550 llvm::raw_svector_ostream Out(Buffer);
10551 Out << Prefix << ISA << LMask << VLEN;
10552 if (OutputBecomesInput)
10553 Out << "v";
10554 Out << ParSeq << "_" << MangledName;
10555 Fn->addFnAttr(Out.str());
10556}
10557
10558// Helper function to generate the Advanced SIMD names depending on
10559// the value of the NDS when simdlen is not present.
10560static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask,
10561 StringRef Prefix, char ISA,
10562 StringRef ParSeq, StringRef MangledName,
10563 bool OutputBecomesInput,
10564 llvm::Function *Fn) {
10565 switch (NDS) {
10566 case 8:
10567 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10568 OutputBecomesInput, Fn);
10569 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName,
10570 OutputBecomesInput, Fn);
10571 break;
10572 case 16:
10573 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10574 OutputBecomesInput, Fn);
10575 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10576 OutputBecomesInput, Fn);
10577 break;
10578 case 32:
10579 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10580 OutputBecomesInput, Fn);
10581 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10582 OutputBecomesInput, Fn);
10583 break;
10584 case 64:
10585 case 128:
10586 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10587 OutputBecomesInput, Fn);
10588 break;
10589 default:
10590 llvm_unreachable("Scalar type is too wide.");
10591 }
10592}
10593
10594/// Emit vector function attributes for AArch64, as defined in the AAVFABI.
10595static void emitAArch64DeclareSimdFunction(
10596 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN,
10597 ArrayRef<ParamAttrTy> ParamAttrs,
10598 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
10599 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) {
10600
10601 // Get basic data for building the vector signature.
10602 const auto Data = getNDSWDS(FD, ParamAttrs);
10603 const unsigned NDS = std::get<0>(Data);
10604 const unsigned WDS = std::get<1>(Data);
10605 const bool OutputBecomesInput = std::get<2>(Data);
10606
10607 // Check the values provided via `simdlen` by the user.
10608 // 1. A `simdlen(1)` doesn't produce vector signatures,
10609 if (UserVLEN == 1) {
10610 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10611 DiagnosticsEngine::Warning,
10612 "The clause simdlen(1) has no effect when targeting aarch64.");
10613 CGM.getDiags().Report(SLoc, DiagID);
10614 return;
10615 }
10616
10617 // 2. Section 3.3.1, item 1: user input must be a power of 2 for
10618 // Advanced SIMD output.
10619 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
10620 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10621 DiagnosticsEngine::Warning, "The value specified in simdlen must be a "
10622 "power of 2 when targeting Advanced SIMD.");
10623 CGM.getDiags().Report(SLoc, DiagID);
10624 return;
10625 }
10626
10627 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural
10628 // limits.
10629 if (ISA == 's' && UserVLEN != 0) {
10630 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
10631 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10632 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit "
10633 "lanes in the architectural constraints "
10634 "for SVE (min is 128-bit, max is "
10635 "2048-bit, by steps of 128-bit)");
10636 CGM.getDiags().Report(SLoc, DiagID) << WDS;
10637 return;
10638 }
10639 }
10640
10641 // Sort out parameter sequence.
10642 const std::string ParSeq = mangleVectorParameters(ParamAttrs);
10643 StringRef Prefix = "_ZGV";
10644 // Generate simdlen from user input (if any).
10645 if (UserVLEN) {
10646 if (ISA == 's') {
10647 // SVE generates only a masked function.
10648 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10649 OutputBecomesInput, Fn);
10650 } else {
10651 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10652 // Advanced SIMD generates one or two functions, depending on
10653 // the `[not]inbranch` clause.
10654 switch (State) {
10655 case OMPDeclareSimdDeclAttr::BS_Undefined:
10656 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10657 OutputBecomesInput, Fn);
10658 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10659 OutputBecomesInput, Fn);
10660 break;
10661 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10662 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10663 OutputBecomesInput, Fn);
10664 break;
10665 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10666 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10667 OutputBecomesInput, Fn);
10668 break;
10669 }
10670 }
10671 } else {
10672 // If no user simdlen is provided, follow the AAVFABI rules for
10673 // generating the vector length.
10674 if (ISA == 's') {
10675 // SVE, section 3.4.1, item 1.
10676 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName,
10677 OutputBecomesInput, Fn);
10678 } else {
10679 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10680 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or
10681 // two vector names depending on the use of the clause
10682 // `[not]inbranch`.
10683 switch (State) {
10684 case OMPDeclareSimdDeclAttr::BS_Undefined:
10685 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10686 OutputBecomesInput, Fn);
10687 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10688 OutputBecomesInput, Fn);
10689 break;
10690 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10691 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10692 OutputBecomesInput, Fn);
10693 break;
10694 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10695 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10696 OutputBecomesInput, Fn);
10697 break;
10698 }
10699 }
10700 }
10701}
10702
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010703void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
10704 llvm::Function *Fn) {
10705 ASTContext &C = CGM.getContext();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010706 FD = FD->getMostRecentDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010707 // Map params to their positions in function decl.
10708 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
10709 if (isa<CXXMethodDecl>(FD))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010710 ParamPositions.try_emplace(FD, 0);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010711 unsigned ParamPos = ParamPositions.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010712 for (const ParmVarDecl *P : FD->parameters()) {
10713 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010714 ++ParamPos;
10715 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010716 while (FD) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010717 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010718 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
10719 // Mark uniform parameters.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010720 for (const Expr *E : Attr->uniforms()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010721 E = E->IgnoreParenImpCasts();
10722 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010723 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010724 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010725 } else {
10726 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10727 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010728 Pos = ParamPositions[PVD];
10729 }
10730 ParamAttrs[Pos].Kind = Uniform;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010731 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010732 // Get alignment info.
10733 auto NI = Attr->alignments_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010734 for (const Expr *E : Attr->aligneds()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010735 E = E->IgnoreParenImpCasts();
10736 unsigned Pos;
10737 QualType ParmTy;
10738 if (isa<CXXThisExpr>(E)) {
10739 Pos = ParamPositions[FD];
10740 ParmTy = E->getType();
10741 } else {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010742 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10743 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010744 Pos = ParamPositions[PVD];
10745 ParmTy = PVD->getType();
10746 }
10747 ParamAttrs[Pos].Alignment =
10748 (*NI)
10749 ? (*NI)->EvaluateKnownConstInt(C)
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010750 : llvm::APSInt::getUnsigned(
10751 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy))
10752 .getQuantity());
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010753 ++NI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010754 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010755 // Mark linear parameters.
10756 auto SI = Attr->steps_begin();
10757 auto MI = Attr->modifiers_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010758 for (const Expr *E : Attr->linears()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010759 E = E->IgnoreParenImpCasts();
10760 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010761 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010762 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010763 } else {
10764 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10765 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010766 Pos = ParamPositions[PVD];
10767 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010768 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010769 ParamAttr.Kind = Linear;
10770 if (*SI) {
Fangrui Song407659a2018-11-30 23:41:18 +000010771 Expr::EvalResult Result;
10772 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010773 if (const auto *DRE =
10774 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
10775 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010776 ParamAttr.Kind = LinearWithVarStride;
10777 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(
10778 ParamPositions[StridePVD->getCanonicalDecl()]);
10779 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010780 }
Fangrui Song407659a2018-11-30 23:41:18 +000010781 } else {
10782 ParamAttr.StrideOrArg = Result.Val.getInt();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010783 }
10784 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010785 ++SI;
10786 ++MI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010787 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010788 llvm::APSInt VLENVal;
Alexey Bataeva0a22642019-04-16 13:56:21 +000010789 SourceLocation ExprLoc;
10790 const Expr *VLENExpr = Attr->getSimdlen();
10791 if (VLENExpr) {
10792 VLENVal = VLENExpr->EvaluateKnownConstInt(C);
10793 ExprLoc = VLENExpr->getExprLoc();
10794 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010795 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
Jim Linab1bcda2020-01-07 17:32:39 +080010796 if (CGM.getTriple().isX86()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010797 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
Alexey Bataeva0a22642019-04-16 13:56:21 +000010798 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) {
10799 unsigned VLEN = VLENVal.getExtValue();
10800 StringRef MangledName = Fn->getName();
10801 if (CGM.getTarget().hasFeature("sve"))
10802 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10803 MangledName, 's', 128, Fn, ExprLoc);
10804 if (CGM.getTarget().hasFeature("neon"))
10805 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10806 MangledName, 'n', 128, Fn, ExprLoc);
10807 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010808 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010809 FD = FD->getPreviousDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010810 }
10811}
Alexey Bataev8b427062016-05-25 12:36:08 +000010812
10813namespace {
10814/// Cleanup action for doacross support.
10815class DoacrossCleanupTy final : public EHScopeStack::Cleanup {
10816public:
10817 static const int DoacrossFinArgs = 2;
10818
10819private:
James Y Knight9871db02019-02-05 16:42:33 +000010820 llvm::FunctionCallee RTLFn;
Alexey Bataev8b427062016-05-25 12:36:08 +000010821 llvm::Value *Args[DoacrossFinArgs];
10822
10823public:
James Y Knight9871db02019-02-05 16:42:33 +000010824 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
10825 ArrayRef<llvm::Value *> CallArgs)
Alexey Bataev8b427062016-05-25 12:36:08 +000010826 : RTLFn(RTLFn) {
10827 assert(CallArgs.size() == DoacrossFinArgs);
10828 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10829 }
10830 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10831 if (!CGF.HaveInsertPoint())
10832 return;
10833 CGF.EmitRuntimeCall(RTLFn, Args);
10834 }
10835};
10836} // namespace
10837
10838void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000010839 const OMPLoopDirective &D,
10840 ArrayRef<Expr *> NumIterations) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010841 if (!CGF.HaveInsertPoint())
10842 return;
10843
10844 ASTContext &C = CGM.getContext();
10845 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
10846 RecordDecl *RD;
10847 if (KmpDimTy.isNull()) {
10848 // Build struct kmp_dim { // loop bounds info casted to kmp_int64
10849 // kmp_int64 lo; // lower
10850 // kmp_int64 up; // upper
10851 // kmp_int64 st; // stride
10852 // };
10853 RD = C.buildImplicitRecord("kmp_dim");
10854 RD->startDefinition();
10855 addFieldToRecordDecl(C, RD, Int64Ty);
10856 addFieldToRecordDecl(C, RD, Int64Ty);
10857 addFieldToRecordDecl(C, RD, Int64Ty);
10858 RD->completeDefinition();
10859 KmpDimTy = C.getRecordType(RD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010860 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010861 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010862 }
Alexey Bataevf138fda2018-08-13 19:04:24 +000010863 llvm::APInt Size(/*numBits=*/32, NumIterations.size());
10864 QualType ArrayTy =
Richard Smith772e2662019-10-04 01:25:59 +000010865 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0);
Alexey Bataev8b427062016-05-25 12:36:08 +000010866
Alexey Bataevf138fda2018-08-13 19:04:24 +000010867 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
10868 CGF.EmitNullInitialization(DimsAddr, ArrayTy);
Alexey Bataev8b427062016-05-25 12:36:08 +000010869 enum { LowerFD = 0, UpperFD, StrideFD };
10870 // Fill dims with data.
Alexey Bataevf138fda2018-08-13 19:04:24 +000010871 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +000010872 LValue DimsLVal = CGF.MakeAddrLValue(
10873 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010874 // dims.upper = num_iterations;
10875 LValue UpperLVal = CGF.EmitLValueForField(
10876 DimsLVal, *std::next(RD->field_begin(), UpperFD));
10877 llvm::Value *NumIterVal =
10878 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]),
10879 D.getNumIterations()->getType(), Int64Ty,
10880 D.getNumIterations()->getExprLoc());
10881 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
10882 // dims.stride = 1;
10883 LValue StrideLVal = CGF.EmitLValueForField(
10884 DimsLVal, *std::next(RD->field_begin(), StrideFD));
10885 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
10886 StrideLVal);
10887 }
Alexey Bataev8b427062016-05-25 12:36:08 +000010888
10889 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
10890 // kmp_int32 num_dims, struct kmp_dim * dims);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010891 llvm::Value *Args[] = {
10892 emitUpdateLocation(CGF, D.getBeginLoc()),
10893 getThreadID(CGF, D.getBeginLoc()),
10894 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()),
10895 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knight751fe282019-02-09 22:22:28 +000010896 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(),
Alexey Bataevf138fda2018-08-13 19:04:24 +000010897 CGM.VoidPtrTy)};
Alexey Bataev8b427062016-05-25 12:36:08 +000010898
James Y Knight9871db02019-02-05 16:42:33 +000010899 llvm::FunctionCallee RTLFn =
10900 createRuntimeFunction(OMPRTL__kmpc_doacross_init);
Alexey Bataev8b427062016-05-25 12:36:08 +000010901 CGF.EmitRuntimeCall(RTLFn, Args);
10902 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
Stephen Kelly1c301dc2018-08-09 21:09:38 +000010903 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())};
James Y Knight9871db02019-02-05 16:42:33 +000010904 llvm::FunctionCallee FiniRTLFn =
10905 createRuntimeFunction(OMPRTL__kmpc_doacross_fini);
Alexey Bataev8b427062016-05-25 12:36:08 +000010906 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
10907 llvm::makeArrayRef(FiniArgs));
10908}
10909
10910void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
10911 const OMPDependClause *C) {
10912 QualType Int64Ty =
10913 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010914 llvm::APInt Size(/*numBits=*/32, C->getNumLoops());
10915 QualType ArrayTy = CGM.getContext().getConstantArrayType(
Richard Smith772e2662019-10-04 01:25:59 +000010916 Int64Ty, Size, nullptr, ArrayType::Normal, 0);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010917 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr");
10918 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) {
10919 const Expr *CounterVal = C->getLoopData(I);
10920 assert(CounterVal);
10921 llvm::Value *CntVal = CGF.EmitScalarConversion(
10922 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
10923 CounterVal->getExprLoc());
James Y Knight751fe282019-02-09 22:22:28 +000010924 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I),
10925 /*Volatile=*/false, Int64Ty);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010926 }
10927 llvm::Value *Args[] = {
10928 emitUpdateLocation(CGF, C->getBeginLoc()),
10929 getThreadID(CGF, C->getBeginLoc()),
James Y Knight751fe282019-02-09 22:22:28 +000010930 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()};
James Y Knight9871db02019-02-05 16:42:33 +000010931 llvm::FunctionCallee RTLFn;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010932 if (C->getDependencyKind() == OMPC_DEPEND_source) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010933 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010934 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010935 assert(C->getDependencyKind() == OMPC_DEPEND_sink);
10936 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait);
10937 }
10938 CGF.EmitRuntimeCall(RTLFn, Args);
10939}
10940
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010941void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000010942 llvm::FunctionCallee Callee,
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010943 ArrayRef<llvm::Value *> Args) const {
10944 assert(Loc.isValid() && "Outlined function call location must be valid.");
Alexey Bataev3c595a62017-08-14 15:01:03 +000010945 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
10946
James Y Knight9871db02019-02-05 16:42:33 +000010947 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010948 if (Fn->doesNotThrow()) {
Alexey Bataev3c595a62017-08-14 15:01:03 +000010949 CGF.EmitNounwindRuntimeCall(Fn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010950 return;
10951 }
10952 }
Alexey Bataev3c595a62017-08-14 15:01:03 +000010953 CGF.EmitRuntimeCall(Callee, Args);
10954}
10955
10956void CGOpenMPRuntime::emitOutlinedFunctionCall(
James Y Knight9871db02019-02-05 16:42:33 +000010957 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn,
Alexey Bataev3c595a62017-08-14 15:01:03 +000010958 ArrayRef<llvm::Value *> Args) const {
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010959 emitCall(CGF, Loc, OutlinedFn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010960}
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010961
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +000010962void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) {
10963 if (const auto *FD = dyn_cast<FunctionDecl>(D))
10964 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
10965 HasEmittedDeclareTargetRegion = true;
10966}
10967
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010968Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
10969 const VarDecl *NativeParam,
10970 const VarDecl *TargetParam) const {
10971 return CGF.GetAddrOfLocalVar(NativeParam);
10972}
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010973
Alexey Bataev4f680db2019-03-19 16:41:16 +000010974namespace {
10975/// Cleanup action for allocate support.
10976class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup {
10977public:
10978 static const int CleanupArgs = 3;
10979
10980private:
10981 llvm::FunctionCallee RTLFn;
10982 llvm::Value *Args[CleanupArgs];
10983
10984public:
10985 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
10986 ArrayRef<llvm::Value *> CallArgs)
10987 : RTLFn(RTLFn) {
10988 assert(CallArgs.size() == CleanupArgs &&
10989 "Size of arguments does not match.");
10990 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10991 }
10992 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10993 if (!CGF.HaveInsertPoint())
10994 return;
10995 CGF.EmitRuntimeCall(RTLFn, Args);
10996 }
10997};
10998} // namespace
10999
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000011000Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF,
11001 const VarDecl *VD) {
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011002 if (!VD)
11003 return Address::invalid();
Alexey Bataev4f680db2019-03-19 16:41:16 +000011004 const VarDecl *CVD = VD->getCanonicalDecl();
11005 if (!CVD->hasAttr<OMPAllocateDeclAttr>())
11006 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011007 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
11008 // Use the default allocation.
Alexey Bataev0fd3c682019-04-02 19:44:46 +000011009 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
11010 !AA->getAllocator())
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011011 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011012 llvm::Value *Size;
11013 CharUnits Align = CGM.getContext().getDeclAlign(CVD);
11014 if (CVD->getType()->isVariablyModifiedType()) {
11015 Size = CGF.getTypeSize(CVD->getType());
Alexey Bataev9c397812019-04-03 17:57:06 +000011016 // Align the size: ((size + align - 1) / align) * align
11017 Size = CGF.Builder.CreateNUWAdd(
11018 Size, CGM.getSize(Align - CharUnits::fromQuantity(1)));
11019 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align));
11020 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align));
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011021 } else {
11022 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType());
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011023 Size = CGM.getSize(Sz.alignTo(Align));
Alexey Bataev4f680db2019-03-19 16:41:16 +000011024 }
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011025 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc());
11026 assert(AA->getAllocator() &&
11027 "Expected allocator expression for non-default allocator.");
11028 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator());
Alexey Bataev6cf7b712019-04-08 19:06:42 +000011029 // According to the standard, the original allocator type is a enum (integer).
11030 // Convert to pointer type, if required.
11031 if (Allocator->getType()->isIntegerTy())
11032 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy);
11033 else if (Allocator->getType()->isPointerTy())
11034 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator,
11035 CGM.VoidPtrTy);
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011036 llvm::Value *Args[] = {ThreadID, Size, Allocator};
11037
11038 llvm::Value *Addr =
11039 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args,
Alexey Bataev8b321922020-01-16 15:46:34 -050011040 getName({CVD->getName(), ".void.addr"}));
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011041 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr,
11042 Allocator};
11043 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free);
11044
11045 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
11046 llvm::makeArrayRef(FiniArgs));
11047 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11048 Addr,
11049 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())),
Alexey Bataev8b321922020-01-16 15:46:34 -050011050 getName({CVD->getName(), ".addr"}));
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011051 return Address(Addr, Align);
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000011052}
11053
Alexey Bataevfde11e92019-11-07 11:03:10 -050011054namespace {
11055using OMPContextSelectorData =
Alexey Bataevf8ff3d72019-11-21 16:36:49 -050011056 OpenMPCtxSelectorData<ArrayRef<StringRef>, llvm::APSInt>;
Alexey Bataevfde11e92019-11-07 11:03:10 -050011057using CompleteOMPContextSelectorData = SmallVector<OMPContextSelectorData, 4>;
11058} // anonymous namespace
11059
Alexey Bataev2df5f122019-10-01 20:18:32 +000011060/// Checks current context and returns true if it matches the context selector.
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011061template <OpenMPContextSelectorSetKind CtxSet, OpenMPContextSelectorKind Ctx,
11062 typename... Arguments>
11063static bool checkContext(const OMPContextSelectorData &Data,
11064 Arguments... Params) {
Alexey Bataevfde11e92019-11-07 11:03:10 -050011065 assert(Data.CtxSet != OMP_CTX_SET_unknown && Data.Ctx != OMP_CTX_unknown &&
Alexey Bataev2df5f122019-10-01 20:18:32 +000011066 "Unknown context selector or context selector set.");
11067 return false;
11068}
11069
11070/// Checks for implementation={vendor(<vendor>)} context selector.
11071/// \returns true iff <vendor>="llvm", false otherwise.
11072template <>
Alexey Bataevfde11e92019-11-07 11:03:10 -050011073bool checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(
11074 const OMPContextSelectorData &Data) {
11075 return llvm::all_of(Data.Names,
Alexey Bataev303657a2019-10-08 19:44:16 +000011076 [](StringRef S) { return !S.compare_lower("llvm"); });
Alexey Bataev2df5f122019-10-01 20:18:32 +000011077}
11078
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011079/// Checks for device={kind(<kind>)} context selector.
11080/// \returns true if <kind>="host" and compilation is for host.
11081/// true if <kind>="nohost" and compilation is for device.
11082/// true if <kind>="cpu" and compilation is for Arm, X86 or PPC CPU.
11083/// true if <kind>="gpu" and compilation is for NVPTX or AMDGCN.
11084/// false otherwise.
11085template <>
11086bool checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>(
11087 const OMPContextSelectorData &Data, CodeGenModule &CGM) {
11088 for (StringRef Name : Data.Names) {
11089 if (!Name.compare_lower("host")) {
11090 if (CGM.getLangOpts().OpenMPIsDevice)
11091 return false;
11092 continue;
11093 }
11094 if (!Name.compare_lower("nohost")) {
11095 if (!CGM.getLangOpts().OpenMPIsDevice)
11096 return false;
11097 continue;
11098 }
11099 switch (CGM.getTriple().getArch()) {
11100 case llvm::Triple::arm:
11101 case llvm::Triple::armeb:
11102 case llvm::Triple::aarch64:
11103 case llvm::Triple::aarch64_be:
11104 case llvm::Triple::aarch64_32:
11105 case llvm::Triple::ppc:
11106 case llvm::Triple::ppc64:
11107 case llvm::Triple::ppc64le:
11108 case llvm::Triple::x86:
11109 case llvm::Triple::x86_64:
11110 if (Name.compare_lower("cpu"))
11111 return false;
11112 break;
11113 case llvm::Triple::amdgcn:
11114 case llvm::Triple::nvptx:
11115 case llvm::Triple::nvptx64:
11116 if (Name.compare_lower("gpu"))
11117 return false;
11118 break;
11119 case llvm::Triple::UnknownArch:
11120 case llvm::Triple::arc:
11121 case llvm::Triple::avr:
11122 case llvm::Triple::bpfel:
11123 case llvm::Triple::bpfeb:
11124 case llvm::Triple::hexagon:
11125 case llvm::Triple::mips:
11126 case llvm::Triple::mipsel:
11127 case llvm::Triple::mips64:
11128 case llvm::Triple::mips64el:
11129 case llvm::Triple::msp430:
11130 case llvm::Triple::r600:
11131 case llvm::Triple::riscv32:
11132 case llvm::Triple::riscv64:
11133 case llvm::Triple::sparc:
11134 case llvm::Triple::sparcv9:
11135 case llvm::Triple::sparcel:
11136 case llvm::Triple::systemz:
11137 case llvm::Triple::tce:
11138 case llvm::Triple::tcele:
11139 case llvm::Triple::thumb:
11140 case llvm::Triple::thumbeb:
11141 case llvm::Triple::xcore:
11142 case llvm::Triple::le32:
11143 case llvm::Triple::le64:
11144 case llvm::Triple::amdil:
11145 case llvm::Triple::amdil64:
11146 case llvm::Triple::hsail:
11147 case llvm::Triple::hsail64:
11148 case llvm::Triple::spir:
11149 case llvm::Triple::spir64:
11150 case llvm::Triple::kalimba:
11151 case llvm::Triple::shave:
11152 case llvm::Triple::lanai:
11153 case llvm::Triple::wasm32:
11154 case llvm::Triple::wasm64:
11155 case llvm::Triple::renderscript32:
11156 case llvm::Triple::renderscript64:
Simon Pilgrim0d540792020-01-09 11:10:46 +000011157 case llvm::Triple::ve:
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011158 return false;
11159 }
11160 }
11161 return true;
11162}
11163
Benjamin Kramerdf186502020-01-14 14:06:12 +010011164static bool matchesContext(CodeGenModule &CGM,
11165 const CompleteOMPContextSelectorData &ContextData) {
Alexey Bataevfde11e92019-11-07 11:03:10 -050011166 for (const OMPContextSelectorData &Data : ContextData) {
Alexey Bataev5459a902019-11-22 11:42:08 -050011167 switch (Data.Ctx) {
11168 case OMP_CTX_vendor:
11169 assert(Data.CtxSet == OMP_CTX_SET_implementation &&
11170 "Expected implementation context selector set.");
11171 if (!checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(Data))
11172 return false;
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011173 break;
Alexey Bataev5459a902019-11-22 11:42:08 -050011174 case OMP_CTX_kind:
11175 assert(Data.CtxSet == OMP_CTX_SET_device &&
11176 "Expected device context selector set.");
11177 if (!checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>(Data,
11178 CGM))
11179 return false;
Alexey Bataevfde11e92019-11-07 11:03:10 -050011180 break;
Alexey Bataev5459a902019-11-22 11:42:08 -050011181 case OMP_CTX_unknown:
11182 llvm_unreachable("Unknown context selector kind.");
Alexey Bataevfde11e92019-11-07 11:03:10 -050011183 }
11184 }
11185 return true;
11186}
11187
11188static CompleteOMPContextSelectorData
11189translateAttrToContextSelectorData(ASTContext &C,
11190 const OMPDeclareVariantAttr *A) {
11191 CompleteOMPContextSelectorData Data;
11192 for (unsigned I = 0, E = A->scores_size(); I < E; ++I) {
11193 Data.emplace_back();
11194 auto CtxSet = static_cast<OpenMPContextSelectorSetKind>(
11195 *std::next(A->ctxSelectorSets_begin(), I));
11196 auto Ctx = static_cast<OpenMPContextSelectorKind>(
11197 *std::next(A->ctxSelectors_begin(), I));
11198 Data.back().CtxSet = CtxSet;
11199 Data.back().Ctx = Ctx;
11200 const Expr *Score = *std::next(A->scores_begin(), I);
11201 Data.back().Score = Score->EvaluateKnownConstInt(C);
Alexey Bataev5459a902019-11-22 11:42:08 -050011202 switch (Ctx) {
11203 case OMP_CTX_vendor:
11204 assert(CtxSet == OMP_CTX_SET_implementation &&
11205 "Expected implementation context selector set.");
11206 Data.back().Names =
11207 llvm::makeArrayRef(A->implVendors_begin(), A->implVendors_end());
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011208 break;
Alexey Bataev5459a902019-11-22 11:42:08 -050011209 case OMP_CTX_kind:
11210 assert(CtxSet == OMP_CTX_SET_device &&
11211 "Expected device context selector set.");
11212 Data.back().Names =
11213 llvm::makeArrayRef(A->deviceKinds_begin(), A->deviceKinds_end());
Alexey Bataevfde11e92019-11-07 11:03:10 -050011214 break;
Alexey Bataev5459a902019-11-22 11:42:08 -050011215 case OMP_CTX_unknown:
11216 llvm_unreachable("Unknown context selector kind.");
Alexey Bataevfde11e92019-11-07 11:03:10 -050011217 }
11218 }
11219 return Data;
11220}
11221
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011222static bool isStrictSubset(const CompleteOMPContextSelectorData &LHS,
11223 const CompleteOMPContextSelectorData &RHS) {
11224 llvm::SmallDenseMap<std::pair<int, int>, llvm::StringSet<>, 4> RHSData;
11225 for (const OMPContextSelectorData &D : RHS) {
11226 auto &Pair = RHSData.FindAndConstruct(std::make_pair(D.CtxSet, D.Ctx));
11227 Pair.getSecond().insert(D.Names.begin(), D.Names.end());
11228 }
11229 bool AllSetsAreEqual = true;
11230 for (const OMPContextSelectorData &D : LHS) {
11231 auto It = RHSData.find(std::make_pair(D.CtxSet, D.Ctx));
11232 if (It == RHSData.end())
11233 return false;
11234 if (D.Names.size() > It->getSecond().size())
11235 return false;
11236 if (llvm::set_union(It->getSecond(), D.Names))
11237 return false;
11238 AllSetsAreEqual =
11239 AllSetsAreEqual && (D.Names.size() == It->getSecond().size());
11240 }
11241
11242 return LHS.size() != RHS.size() || !AllSetsAreEqual;
11243}
11244
Alexey Bataevfde11e92019-11-07 11:03:10 -050011245static bool greaterCtxScore(const CompleteOMPContextSelectorData &LHS,
11246 const CompleteOMPContextSelectorData &RHS) {
11247 // Score is calculated as sum of all scores + 1.
11248 llvm::APSInt LHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false);
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011249 bool RHSIsSubsetOfLHS = isStrictSubset(RHS, LHS);
11250 if (RHSIsSubsetOfLHS) {
11251 LHSScore = llvm::APSInt::get(0);
11252 } else {
11253 for (const OMPContextSelectorData &Data : LHS) {
11254 if (Data.Score.getBitWidth() > LHSScore.getBitWidth()) {
11255 LHSScore = LHSScore.extend(Data.Score.getBitWidth()) + Data.Score;
11256 } else if (Data.Score.getBitWidth() < LHSScore.getBitWidth()) {
11257 LHSScore += Data.Score.extend(LHSScore.getBitWidth());
11258 } else {
11259 LHSScore += Data.Score;
11260 }
Alexey Bataevfde11e92019-11-07 11:03:10 -050011261 }
11262 }
11263 llvm::APSInt RHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false);
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011264 if (!RHSIsSubsetOfLHS && isStrictSubset(LHS, RHS)) {
11265 RHSScore = llvm::APSInt::get(0);
11266 } else {
11267 for (const OMPContextSelectorData &Data : RHS) {
11268 if (Data.Score.getBitWidth() > RHSScore.getBitWidth()) {
11269 RHSScore = RHSScore.extend(Data.Score.getBitWidth()) + Data.Score;
11270 } else if (Data.Score.getBitWidth() < RHSScore.getBitWidth()) {
11271 RHSScore += Data.Score.extend(RHSScore.getBitWidth());
11272 } else {
11273 RHSScore += Data.Score;
11274 }
Alexey Bataevfde11e92019-11-07 11:03:10 -050011275 }
11276 }
11277 return llvm::APSInt::compareValues(LHSScore, RHSScore) >= 0;
Alexey Bataev0364c762019-10-03 20:49:48 +000011278}
11279
Alexey Bataev2df5f122019-10-01 20:18:32 +000011280/// Finds the variant function that matches current context with its context
11281/// selector.
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011282static const FunctionDecl *getDeclareVariantFunction(CodeGenModule &CGM,
Alexey Bataev0364c762019-10-03 20:49:48 +000011283 const FunctionDecl *FD) {
Alexey Bataev2df5f122019-10-01 20:18:32 +000011284 if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>())
11285 return FD;
11286 // Iterate through all DeclareVariant attributes and check context selectors.
Alexey Bataev0364c762019-10-03 20:49:48 +000011287 const OMPDeclareVariantAttr *TopMostAttr = nullptr;
Alexey Bataevfde11e92019-11-07 11:03:10 -050011288 CompleteOMPContextSelectorData TopMostData;
Alexey Bataev0364c762019-10-03 20:49:48 +000011289 for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) {
Alexey Bataevfde11e92019-11-07 11:03:10 -050011290 CompleteOMPContextSelectorData Data =
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011291 translateAttrToContextSelectorData(CGM.getContext(), A);
11292 if (!matchesContext(CGM, Data))
Alexey Bataevfde11e92019-11-07 11:03:10 -050011293 continue;
Alexey Bataev0364c762019-10-03 20:49:48 +000011294 // If the attribute matches the context, find the attribute with the highest
11295 // score.
Alexey Bataevfde11e92019-11-07 11:03:10 -050011296 if (!TopMostAttr || !greaterCtxScore(TopMostData, Data)) {
11297 TopMostAttr = A;
11298 TopMostData.swap(Data);
11299 }
Alexey Bataev2df5f122019-10-01 20:18:32 +000011300 }
Alexey Bataev0364c762019-10-03 20:49:48 +000011301 if (!TopMostAttr)
Alexey Bataev2df5f122019-10-01 20:18:32 +000011302 return FD;
Alexey Bataev2df5f122019-10-01 20:18:32 +000011303 return cast<FunctionDecl>(
Alexey Bataev0364c762019-10-03 20:49:48 +000011304 cast<DeclRefExpr>(TopMostAttr->getVariantFuncRef()->IgnoreParenImpCasts())
Alexey Bataev2df5f122019-10-01 20:18:32 +000011305 ->getDecl());
11306}
11307
11308bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) {
11309 const auto *D = cast<FunctionDecl>(GD.getDecl());
11310 // If the original function is defined already, use its definition.
11311 StringRef MangledName = CGM.getMangledName(GD);
11312 llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName);
11313 if (Orig && !Orig->isDeclaration())
11314 return false;
Alexey Bataev4e8231b2019-11-05 15:13:30 -050011315 const FunctionDecl *NewFD = getDeclareVariantFunction(CGM, D);
Alexey Bataev2df5f122019-10-01 20:18:32 +000011316 // Emit original function if it does not have declare variant attribute or the
11317 // context does not match.
11318 if (NewFD == D)
11319 return false;
11320 GlobalDecl NewGD = GD.getWithDecl(NewFD);
Alexey Bataevc2cd2d42019-10-10 17:28:10 +000011321 if (tryEmitDeclareVariant(NewGD, GD, Orig, IsForDefinition)) {
Alexey Bataev2df5f122019-10-01 20:18:32 +000011322 DeferredVariantFunction.erase(D);
11323 return true;
11324 }
11325 DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD)));
11326 return true;
11327}
11328
Alexey Bataev0860db92019-12-19 10:01:10 -050011329CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII(
11330 CodeGenModule &CGM, const OMPLoopDirective &S)
11331 : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) {
11332 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode.");
11333 if (!NeedToPush)
11334 return;
11335 NontemporalDeclsSet &DS =
11336 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back();
11337 for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) {
11338 for (const Stmt *Ref : C->private_refs()) {
11339 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts();
11340 const ValueDecl *VD;
11341 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) {
11342 VD = DRE->getDecl();
11343 } else {
11344 const auto *ME = cast<MemberExpr>(SimpleRefExpr);
11345 assert((ME->isImplicitCXXThis() ||
11346 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) &&
11347 "Expected member of current class.");
11348 VD = ME->getMemberDecl();
11349 }
11350 DS.insert(VD);
11351 }
11352 }
11353}
11354
11355CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() {
11356 if (!NeedToPush)
11357 return;
11358 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back();
11359}
11360
11361bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const {
11362 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode.");
11363
11364 return llvm::any_of(
11365 CGM.getOpenMPRuntime().NontemporalDeclsStack,
11366 [VD](const NontemporalDeclsSet &Set) { return Set.count(VD) > 0; });
11367}
11368
Alexey Bataev46978742020-01-30 10:46:11 -050011369void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis(
11370 const OMPExecutableDirective &S,
11371 llvm::DenseSet<CanonicalDeclPtr<const Decl>> &NeedToAddForLPCsAsDisabled)
11372 const {
11373 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs;
11374 // Vars in target/task regions must be excluded completely.
11375 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()) ||
11376 isOpenMPTaskingDirective(S.getDirectiveKind())) {
11377 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
11378 getOpenMPCaptureRegions(CaptureRegions, S.getDirectiveKind());
11379 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front());
11380 for (const CapturedStmt::Capture &Cap : CS->captures()) {
11381 if (Cap.capturesVariable() || Cap.capturesVariableByCopy())
11382 NeedToCheckForLPCs.insert(Cap.getCapturedVar());
11383 }
11384 }
11385 // Exclude vars in private clauses.
11386 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) {
11387 for (const Expr *Ref : C->varlists()) {
11388 if (!Ref->getType()->isScalarType())
11389 continue;
11390 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11391 if (!DRE)
11392 continue;
11393 NeedToCheckForLPCs.insert(DRE->getDecl());
11394 }
11395 }
11396 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
11397 for (const Expr *Ref : C->varlists()) {
11398 if (!Ref->getType()->isScalarType())
11399 continue;
11400 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11401 if (!DRE)
11402 continue;
11403 NeedToCheckForLPCs.insert(DRE->getDecl());
11404 }
11405 }
11406 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
11407 for (const Expr *Ref : C->varlists()) {
11408 if (!Ref->getType()->isScalarType())
11409 continue;
11410 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11411 if (!DRE)
11412 continue;
11413 NeedToCheckForLPCs.insert(DRE->getDecl());
11414 }
11415 }
11416 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
11417 for (const Expr *Ref : C->varlists()) {
11418 if (!Ref->getType()->isScalarType())
11419 continue;
11420 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11421 if (!DRE)
11422 continue;
11423 NeedToCheckForLPCs.insert(DRE->getDecl());
11424 }
11425 }
11426 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) {
11427 for (const Expr *Ref : C->varlists()) {
11428 if (!Ref->getType()->isScalarType())
11429 continue;
11430 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
11431 if (!DRE)
11432 continue;
11433 NeedToCheckForLPCs.insert(DRE->getDecl());
11434 }
11435 }
11436 for (const Decl *VD : NeedToCheckForLPCs) {
11437 for (const LastprivateConditionalData &Data :
11438 llvm::reverse(CGM.getOpenMPRuntime().LastprivateConditionalStack)) {
11439 if (Data.DeclToUniqueName.count(VD) > 0) {
11440 if (!Data.Disabled)
11441 NeedToAddForLPCsAsDisabled.insert(VD);
11442 break;
11443 }
11444 }
11445 }
11446}
11447
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011448CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
11449 CodeGenFunction &CGF, const OMPExecutableDirective &S, LValue IVLVal)
11450 : CGM(CGF.CGM),
Alexey Bataev46978742020-01-30 10:46:11 -050011451 Action((CGM.getLangOpts().OpenMP >= 50 &&
11452 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(),
11453 [](const OMPLastprivateClause *C) {
11454 return C->getKind() ==
11455 OMPC_LASTPRIVATE_conditional;
11456 }))
11457 ? ActionToDo::PushAsLastprivateConditional
11458 : ActionToDo::DoNotPush) {
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011459 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode.");
Alexey Bataev46978742020-01-30 10:46:11 -050011460 if (CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush)
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011461 return;
Alexey Bataev46978742020-01-30 10:46:11 -050011462 assert(Action == ActionToDo::PushAsLastprivateConditional &&
11463 "Expected a push action.");
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011464 LastprivateConditionalData &Data =
11465 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
11466 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
11467 if (C->getKind() != OMPC_LASTPRIVATE_conditional)
11468 continue;
11469
11470 for (const Expr *Ref : C->varlists()) {
Alexey Bataev46978742020-01-30 10:46:11 -050011471 Data.DeclToUniqueName.insert(std::make_pair(
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011472 cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(),
Alexey Bataev46978742020-01-30 10:46:11 -050011473 SmallString<16>(generateUniqueName(CGM, "pl_cond", Ref))));
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011474 }
11475 }
11476 Data.IVLVal = IVLVal;
Alexey Bataev46978742020-01-30 10:46:11 -050011477 Data.Fn = CGF.CurFn;
11478}
11479
11480CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII(
11481 CodeGenFunction &CGF, const OMPExecutableDirective &S)
11482 : CGM(CGF.CGM), Action(ActionToDo::DoNotPush) {
11483 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode.");
11484 if (CGM.getLangOpts().OpenMP < 50)
11485 return;
11486 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled;
11487 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled);
11488 if (!NeedToAddForLPCsAsDisabled.empty()) {
11489 Action = ActionToDo::DisableLastprivateConditional;
11490 LastprivateConditionalData &Data =
11491 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back();
11492 for (const Decl *VD : NeedToAddForLPCsAsDisabled)
11493 Data.DeclToUniqueName.insert(std::make_pair(VD, SmallString<16>()));
11494 Data.Fn = CGF.CurFn;
11495 Data.Disabled = true;
11496 }
11497}
11498
11499CGOpenMPRuntime::LastprivateConditionalRAII
11500CGOpenMPRuntime::LastprivateConditionalRAII::disable(
11501 CodeGenFunction &CGF, const OMPExecutableDirective &S) {
11502 return LastprivateConditionalRAII(CGF, S);
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011503}
11504
11505CGOpenMPRuntime::LastprivateConditionalRAII::~LastprivateConditionalRAII() {
Alexey Bataev46978742020-01-30 10:46:11 -050011506 if (CGM.getLangOpts().OpenMP < 50)
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011507 return;
Alexey Bataev46978742020-01-30 10:46:11 -050011508 if (Action == ActionToDo::DisableLastprivateConditional) {
11509 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
11510 "Expected list of disabled private vars.");
11511 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
11512 }
11513 if (Action == ActionToDo::PushAsLastprivateConditional) {
11514 assert(
11515 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled &&
11516 "Expected list of lastprivate conditional vars.");
11517 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back();
11518 }
11519}
11520
11521Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF,
11522 const VarDecl *VD) {
11523 ASTContext &C = CGM.getContext();
11524 auto I = LastprivateConditionalToTypes.find(CGF.CurFn);
11525 if (I == LastprivateConditionalToTypes.end())
11526 I = LastprivateConditionalToTypes.try_emplace(CGF.CurFn).first;
11527 QualType NewType;
11528 const FieldDecl *VDField;
11529 const FieldDecl *FiredField;
11530 LValue BaseLVal;
11531 auto VI = I->getSecond().find(VD);
11532 if (VI == I->getSecond().end()) {
11533 RecordDecl *RD = C.buildImplicitRecord("lasprivate.conditional");
11534 RD->startDefinition();
11535 VDField = addFieldToRecordDecl(C, RD, VD->getType().getNonReferenceType());
11536 FiredField = addFieldToRecordDecl(C, RD, C.CharTy);
11537 RD->completeDefinition();
11538 NewType = C.getRecordType(RD);
11539 Address Addr = CGF.CreateMemTemp(NewType, C.getDeclAlign(VD), VD->getName());
11540 BaseLVal = CGF.MakeAddrLValue(Addr, NewType, AlignmentSource::Decl);
11541 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal);
11542 } else {
11543 NewType = std::get<0>(VI->getSecond());
11544 VDField = std::get<1>(VI->getSecond());
11545 FiredField = std::get<2>(VI->getSecond());
11546 BaseLVal = std::get<3>(VI->getSecond());
11547 }
11548 LValue FiredLVal =
11549 CGF.EmitLValueForField(BaseLVal, FiredField);
11550 CGF.EmitStoreOfScalar(
11551 llvm::ConstantInt::getNullValue(CGF.ConvertTypeForMem(C.CharTy)),
11552 FiredLVal);
11553 return CGF.EmitLValueForField(BaseLVal, VDField).getAddress(CGF);
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011554}
11555
11556namespace {
11557/// Checks if the lastprivate conditional variable is referenced in LHS.
11558class LastprivateConditionalRefChecker final
11559 : public ConstStmtVisitor<LastprivateConditionalRefChecker, bool> {
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011560 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM;
11561 const Expr *FoundE = nullptr;
11562 const Decl *FoundD = nullptr;
11563 StringRef UniqueDeclName;
11564 LValue IVLVal;
Alexey Bataev46978742020-01-30 10:46:11 -050011565 llvm::Function *FoundFn = nullptr;
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011566 SourceLocation Loc;
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011567
11568public:
11569 bool VisitDeclRefExpr(const DeclRefExpr *E) {
11570 for (const CGOpenMPRuntime::LastprivateConditionalData &D :
11571 llvm::reverse(LPM)) {
Alexey Bataev46978742020-01-30 10:46:11 -050011572 auto It = D.DeclToUniqueName.find(E->getDecl());
11573 if (It == D.DeclToUniqueName.end())
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011574 continue;
Alexey Bataev46978742020-01-30 10:46:11 -050011575 if (D.Disabled)
11576 return false;
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011577 FoundE = E;
11578 FoundD = E->getDecl()->getCanonicalDecl();
Alexey Bataev46978742020-01-30 10:46:11 -050011579 UniqueDeclName = It->second;
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011580 IVLVal = D.IVLVal;
Alexey Bataev46978742020-01-30 10:46:11 -050011581 FoundFn = D.Fn;
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011582 break;
11583 }
11584 return FoundE == E;
11585 }
11586 bool VisitMemberExpr(const MemberExpr *E) {
Alexey Bataev46978742020-01-30 10:46:11 -050011587 if (!CodeGenFunction::IsWrappedCXXThis(E->getBase()))
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011588 return false;
11589 for (const CGOpenMPRuntime::LastprivateConditionalData &D :
11590 llvm::reverse(LPM)) {
Alexey Bataev46978742020-01-30 10:46:11 -050011591 auto It = D.DeclToUniqueName.find(E->getMemberDecl());
11592 if (It == D.DeclToUniqueName.end())
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011593 continue;
Alexey Bataev46978742020-01-30 10:46:11 -050011594 if (D.Disabled)
11595 return false;
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011596 FoundE = E;
11597 FoundD = E->getMemberDecl()->getCanonicalDecl();
Alexey Bataev46978742020-01-30 10:46:11 -050011598 UniqueDeclName = It->second;
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011599 IVLVal = D.IVLVal;
Alexey Bataev46978742020-01-30 10:46:11 -050011600 FoundFn = D.Fn;
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011601 break;
11602 }
11603 return FoundE == E;
11604 }
11605 bool VisitStmt(const Stmt *S) {
11606 for (const Stmt *Child : S->children()) {
11607 if (!Child)
11608 continue;
11609 if (const auto *E = dyn_cast<Expr>(Child))
11610 if (!E->isGLValue())
11611 continue;
11612 if (Visit(Child))
11613 return true;
11614 }
11615 return false;
11616 }
11617 explicit LastprivateConditionalRefChecker(
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011618 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM)
Alexey Bataev46978742020-01-30 10:46:11 -050011619 : LPM(LPM) {}
11620 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *>
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011621 getFoundData() const {
Alexey Bataev46978742020-01-30 10:46:11 -050011622 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn);
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011623 }
11624};
11625} // namespace
11626
Alexey Bataev46978742020-01-30 10:46:11 -050011627void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF,
11628 LValue IVLVal,
11629 StringRef UniqueDeclName,
11630 LValue LVal,
11631 SourceLocation Loc) {
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011632 // Last updated loop counter for the lastprivate conditional var.
11633 // int<xx> last_iv = 0;
11634 llvm::Type *LLIVTy = CGF.ConvertTypeForMem(IVLVal.getType());
11635 llvm::Constant *LastIV =
Alexey Bataev8b321922020-01-16 15:46:34 -050011636 getOrCreateInternalVariable(LLIVTy, getName({UniqueDeclName, "iv"}));
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011637 cast<llvm::GlobalVariable>(LastIV)->setAlignment(
11638 IVLVal.getAlignment().getAsAlign());
11639 LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType());
11640
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011641 // Last value of the lastprivate conditional.
11642 // decltype(priv_a) last_a;
11643 llvm::Constant *Last = getOrCreateInternalVariable(
Alexey Bataev46978742020-01-30 10:46:11 -050011644 CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName);
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011645 cast<llvm::GlobalVariable>(Last)->setAlignment(
11646 LVal.getAlignment().getAsAlign());
11647 LValue LastLVal =
11648 CGF.MakeAddrLValue(Last, LVal.getType(), LVal.getAlignment());
11649
11650 // Global loop counter. Required to handle inner parallel-for regions.
Alexey Bataev46978742020-01-30 10:46:11 -050011651 // iv
11652 llvm::Value *IVVal = CGF.EmitLoadOfScalar(IVLVal, Loc);
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011653
11654 // #pragma omp critical(a)
11655 // if (last_iv <= iv) {
11656 // last_iv = iv;
11657 // last_a = priv_a;
11658 // }
11659 auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal,
Alexey Bataev46978742020-01-30 10:46:11 -050011660 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011661 Action.Enter(CGF);
Alexey Bataev46978742020-01-30 10:46:11 -050011662 llvm::Value *LastIVVal = CGF.EmitLoadOfScalar(LastIVLVal, Loc);
11663 // (last_iv <= iv) ? Check if the variable is updated and store new
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011664 // value in global var.
11665 llvm::Value *CmpRes;
11666 if (IVLVal.getType()->isSignedIntegerType()) {
11667 CmpRes = CGF.Builder.CreateICmpSLE(LastIVVal, IVVal);
11668 } else {
11669 assert(IVLVal.getType()->isUnsignedIntegerType() &&
11670 "Loop iteration variable must be integer.");
11671 CmpRes = CGF.Builder.CreateICmpULE(LastIVVal, IVVal);
11672 }
11673 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lp_cond_then");
11674 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("lp_cond_exit");
11675 CGF.Builder.CreateCondBr(CmpRes, ThenBB, ExitBB);
11676 // {
11677 CGF.EmitBlock(ThenBB);
11678
Alexey Bataev46978742020-01-30 10:46:11 -050011679 // last_iv = iv;
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011680 CGF.EmitStoreOfScalar(IVVal, LastIVLVal);
11681
11682 // last_a = priv_a;
11683 switch (CGF.getEvaluationKind(LVal.getType())) {
11684 case TEK_Scalar: {
Alexey Bataev46978742020-01-30 10:46:11 -050011685 llvm::Value *PrivVal = CGF.EmitLoadOfScalar(LVal, Loc);
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011686 CGF.EmitStoreOfScalar(PrivVal, LastLVal);
11687 break;
11688 }
11689 case TEK_Complex: {
Alexey Bataev46978742020-01-30 10:46:11 -050011690 CodeGenFunction::ComplexPairTy PrivVal = CGF.EmitLoadOfComplex(LVal, Loc);
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011691 CGF.EmitStoreOfComplex(PrivVal, LastLVal, /*isInit=*/false);
11692 break;
11693 }
11694 case TEK_Aggregate:
11695 llvm_unreachable(
11696 "Aggregates are not supported in lastprivate conditional.");
11697 }
11698 // }
11699 CGF.EmitBranch(ExitBB);
11700 // There is no need to emit line number for unconditional branch.
11701 (void)ApplyDebugLocation::CreateEmpty(CGF);
11702 CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
11703 };
11704
11705 if (CGM.getLangOpts().OpenMPSimd) {
11706 // Do not emit as a critical region as no parallel region could be emitted.
11707 RegionCodeGenTy ThenRCG(CodeGen);
11708 ThenRCG(CGF);
11709 } else {
Alexey Bataev46978742020-01-30 10:46:11 -050011710 emitCriticalRegion(CGF, UniqueDeclName, CodeGen, Loc);
11711 }
11712}
11713
11714void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF,
11715 const Expr *LHS) {
11716 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty())
11717 return;
11718 LastprivateConditionalRefChecker Checker(LastprivateConditionalStack);
11719 if (!Checker.Visit(LHS))
11720 return;
11721 const Expr *FoundE;
11722 const Decl *FoundD;
11723 StringRef UniqueDeclName;
11724 LValue IVLVal;
11725 llvm::Function *FoundFn;
11726 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) =
11727 Checker.getFoundData();
11728 if (FoundFn != CGF.CurFn) {
11729 // Special codegen for inner parallel regions.
11730 // ((struct.lastprivate.conditional*)&priv_a)->Fired = 1;
11731 auto It = LastprivateConditionalToTypes[FoundFn].find(FoundD);
11732 assert(It != LastprivateConditionalToTypes[FoundFn].end() &&
11733 "Lastprivate conditional is not found in outer region.");
11734 QualType StructTy = std::get<0>(It->getSecond());
11735 const FieldDecl* FiredDecl = std::get<2>(It->getSecond());
11736 LValue PrivLVal = CGF.EmitLValue(FoundE);
11737 Address StructAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11738 PrivLVal.getAddress(CGF),
11739 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(StructTy)));
11740 LValue BaseLVal =
11741 CGF.MakeAddrLValue(StructAddr, StructTy, AlignmentSource::Decl);
11742 LValue FiredLVal = CGF.EmitLValueForField(BaseLVal, FiredDecl);
11743 CGF.EmitAtomicStore(RValue::get(llvm::ConstantInt::get(
11744 CGF.ConvertTypeForMem(FiredDecl->getType()), 1)),
11745 FiredLVal, llvm::AtomicOrdering::Unordered,
11746 /*IsVolatile=*/true, /*isInit=*/false);
11747 return;
11748 }
11749
11750 // Private address of the lastprivate conditional in the current context.
11751 // priv_a
11752 LValue LVal = CGF.EmitLValue(FoundE);
11753 emitLastprivateConditionalUpdate(CGF, IVLVal, UniqueDeclName, LVal,
11754 FoundE->getExprLoc());
11755}
11756
11757void CGOpenMPRuntime::checkAndEmitSharedLastprivateConditional(
11758 CodeGenFunction &CGF, const OMPExecutableDirective &D,
11759 const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls) {
11760 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty())
11761 return;
11762 auto Range = llvm::reverse(LastprivateConditionalStack);
11763 auto It = llvm::find_if(
11764 Range, [](const LastprivateConditionalData &D) { return !D.Disabled; });
11765 if (It == Range.end() || It->Fn != CGF.CurFn)
11766 return;
11767 auto LPCI = LastprivateConditionalToTypes.find(It->Fn);
11768 assert(LPCI != LastprivateConditionalToTypes.end() &&
11769 "Lastprivates must be registered already.");
11770 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
11771 getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind());
11772 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back());
11773 for (const auto &Pair : It->DeclToUniqueName) {
11774 const auto *VD = cast<VarDecl>(Pair.first->getCanonicalDecl());
11775 if (!CS->capturesVariable(VD) || IgnoredDecls.count(VD) > 0)
11776 continue;
11777 auto I = LPCI->getSecond().find(Pair.first);
11778 assert(I != LPCI->getSecond().end() &&
11779 "Lastprivate must be rehistered already.");
11780 // bool Cmp = priv_a.Fired != 0;
11781 LValue BaseLVal = std::get<3>(I->getSecond());
11782 LValue FiredLVal =
11783 CGF.EmitLValueForField(BaseLVal, std::get<2>(I->getSecond()));
11784 llvm::Value *Res = CGF.EmitLoadOfScalar(FiredLVal, D.getBeginLoc());
11785 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Res);
11786 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lpc.then");
11787 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("lpc.done");
11788 // if (Cmp) {
11789 CGF.Builder.CreateCondBr(Cmp, ThenBB, DoneBB);
11790 CGF.EmitBlock(ThenBB);
11791 Address Addr = CGF.GetAddrOfLocalVar(VD);
11792 LValue LVal;
11793 if (VD->getType()->isReferenceType())
11794 LVal = CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(),
11795 AlignmentSource::Decl);
11796 else
11797 LVal = CGF.MakeAddrLValue(Addr, VD->getType().getNonReferenceType(),
11798 AlignmentSource::Decl);
11799 emitLastprivateConditionalUpdate(CGF, It->IVLVal, Pair.second, LVal,
11800 D.getBeginLoc());
11801 auto AL = ApplyDebugLocation::CreateArtificial(CGF);
11802 CGF.EmitBlock(DoneBB, /*IsFinal=*/true);
11803 // }
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011804 }
11805}
11806
11807void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate(
11808 CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD,
11809 SourceLocation Loc) {
11810 if (CGF.getLangOpts().OpenMP < 50)
11811 return;
Alexey Bataev46978742020-01-30 10:46:11 -050011812 auto It = LastprivateConditionalStack.back().DeclToUniqueName.find(VD);
11813 assert(It != LastprivateConditionalStack.back().DeclToUniqueName.end() &&
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011814 "Unknown lastprivate conditional variable.");
Alexey Bataev46978742020-01-30 10:46:11 -050011815 StringRef UniqueName = It->second;
Alexey Bataeva58da1a2019-12-27 09:44:43 -050011816 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(UniqueName);
11817 // The variable was not updated in the region - exit.
11818 if (!GV)
11819 return;
11820 LValue LPLVal = CGF.MakeAddrLValue(
11821 GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment());
11822 llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc);
11823 CGF.EmitStoreOfScalar(Res, PrivLVal);
11824}
11825
James Y Knight9871db02019-02-05 16:42:33 +000011826llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011827 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11828 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11829 llvm_unreachable("Not supported in SIMD-only mode");
11830}
11831
James Y Knight9871db02019-02-05 16:42:33 +000011832llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011833 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11834 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11835 llvm_unreachable("Not supported in SIMD-only mode");
11836}
11837
James Y Knight9871db02019-02-05 16:42:33 +000011838llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011839 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11840 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
11841 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
11842 bool Tied, unsigned &NumberOfParts) {
11843 llvm_unreachable("Not supported in SIMD-only mode");
11844}
11845
11846void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF,
11847 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000011848 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011849 ArrayRef<llvm::Value *> CapturedVars,
11850 const Expr *IfCond) {
11851 llvm_unreachable("Not supported in SIMD-only mode");
11852}
11853
11854void CGOpenMPSIMDRuntime::emitCriticalRegion(
11855 CodeGenFunction &CGF, StringRef CriticalName,
11856 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
11857 const Expr *Hint) {
11858 llvm_unreachable("Not supported in SIMD-only mode");
11859}
11860
11861void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF,
11862 const RegionCodeGenTy &MasterOpGen,
11863 SourceLocation Loc) {
11864 llvm_unreachable("Not supported in SIMD-only mode");
11865}
11866
11867void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
11868 SourceLocation Loc) {
11869 llvm_unreachable("Not supported in SIMD-only mode");
11870}
11871
11872void CGOpenMPSIMDRuntime::emitTaskgroupRegion(
11873 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen,
11874 SourceLocation Loc) {
11875 llvm_unreachable("Not supported in SIMD-only mode");
11876}
11877
11878void CGOpenMPSIMDRuntime::emitSingleRegion(
11879 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen,
11880 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars,
11881 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs,
11882 ArrayRef<const Expr *> AssignmentOps) {
11883 llvm_unreachable("Not supported in SIMD-only mode");
11884}
11885
11886void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF,
11887 const RegionCodeGenTy &OrderedOpGen,
11888 SourceLocation Loc,
11889 bool IsThreads) {
11890 llvm_unreachable("Not supported in SIMD-only mode");
11891}
11892
11893void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF,
11894 SourceLocation Loc,
11895 OpenMPDirectiveKind Kind,
11896 bool EmitChecks,
11897 bool ForceSimpleCall) {
11898 llvm_unreachable("Not supported in SIMD-only mode");
11899}
11900
11901void CGOpenMPSIMDRuntime::emitForDispatchInit(
11902 CodeGenFunction &CGF, SourceLocation Loc,
11903 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
11904 bool Ordered, const DispatchRTInput &DispatchValues) {
11905 llvm_unreachable("Not supported in SIMD-only mode");
11906}
11907
11908void CGOpenMPSIMDRuntime::emitForStaticInit(
11909 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind,
11910 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) {
11911 llvm_unreachable("Not supported in SIMD-only mode");
11912}
11913
11914void CGOpenMPSIMDRuntime::emitDistributeStaticInit(
11915 CodeGenFunction &CGF, SourceLocation Loc,
11916 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) {
11917 llvm_unreachable("Not supported in SIMD-only mode");
11918}
11919
11920void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
11921 SourceLocation Loc,
11922 unsigned IVSize,
11923 bool IVSigned) {
11924 llvm_unreachable("Not supported in SIMD-only mode");
11925}
11926
11927void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF,
11928 SourceLocation Loc,
11929 OpenMPDirectiveKind DKind) {
11930 llvm_unreachable("Not supported in SIMD-only mode");
11931}
11932
11933llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF,
11934 SourceLocation Loc,
11935 unsigned IVSize, bool IVSigned,
11936 Address IL, Address LB,
11937 Address UB, Address ST) {
11938 llvm_unreachable("Not supported in SIMD-only mode");
11939}
11940
11941void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
11942 llvm::Value *NumThreads,
11943 SourceLocation Loc) {
11944 llvm_unreachable("Not supported in SIMD-only mode");
11945}
11946
11947void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF,
Johannes Doerfert6c5d1f402019-12-25 18:15:36 -060011948 ProcBindKind ProcBind,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011949 SourceLocation Loc) {
11950 llvm_unreachable("Not supported in SIMD-only mode");
11951}
11952
11953Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
11954 const VarDecl *VD,
11955 Address VDAddr,
11956 SourceLocation Loc) {
11957 llvm_unreachable("Not supported in SIMD-only mode");
11958}
11959
11960llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition(
11961 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit,
11962 CodeGenFunction *CGF) {
11963 llvm_unreachable("Not supported in SIMD-only mode");
11964}
11965
11966Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate(
11967 CodeGenFunction &CGF, QualType VarType, StringRef Name) {
11968 llvm_unreachable("Not supported in SIMD-only mode");
11969}
11970
11971void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF,
11972 ArrayRef<const Expr *> Vars,
Alexey Bataeve8e05de2020-02-07 12:22:23 -050011973 SourceLocation Loc,
11974 llvm::AtomicOrdering AO) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011975 llvm_unreachable("Not supported in SIMD-only mode");
11976}
11977
11978void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
11979 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000011980 llvm::Function *TaskFunction,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011981 QualType SharedsTy, Address Shareds,
11982 const Expr *IfCond,
11983 const OMPTaskDataTy &Data) {
11984 llvm_unreachable("Not supported in SIMD-only mode");
11985}
11986
11987void CGOpenMPSIMDRuntime::emitTaskLoopCall(
11988 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000011989 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011990 const Expr *IfCond, const OMPTaskDataTy &Data) {
11991 llvm_unreachable("Not supported in SIMD-only mode");
11992}
11993
11994void CGOpenMPSIMDRuntime::emitReduction(
11995 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates,
11996 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
11997 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) {
11998 assert(Options.SimpleReduction && "Only simple reduction is expected.");
11999 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
12000 ReductionOps, Options);
12001}
12002
12003llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit(
12004 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
12005 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
12006 llvm_unreachable("Not supported in SIMD-only mode");
12007}
12008
12009void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
12010 SourceLocation Loc,
12011 ReductionCodeGen &RCG,
12012 unsigned N) {
12013 llvm_unreachable("Not supported in SIMD-only mode");
12014}
12015
12016Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
12017 SourceLocation Loc,
12018 llvm::Value *ReductionsPtr,
12019 LValue SharedLVal) {
12020 llvm_unreachable("Not supported in SIMD-only mode");
12021}
12022
12023void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
12024 SourceLocation Loc) {
12025 llvm_unreachable("Not supported in SIMD-only mode");
12026}
12027
12028void CGOpenMPSIMDRuntime::emitCancellationPointCall(
12029 CodeGenFunction &CGF, SourceLocation Loc,
12030 OpenMPDirectiveKind CancelRegion) {
12031 llvm_unreachable("Not supported in SIMD-only mode");
12032}
12033
12034void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF,
12035 SourceLocation Loc, const Expr *IfCond,
12036 OpenMPDirectiveKind CancelRegion) {
12037 llvm_unreachable("Not supported in SIMD-only mode");
12038}
12039
12040void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction(
12041 const OMPExecutableDirective &D, StringRef ParentName,
12042 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
12043 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
12044 llvm_unreachable("Not supported in SIMD-only mode");
12045}
12046
Alexey Bataevec7946e2019-09-23 14:06:51 +000012047void CGOpenMPSIMDRuntime::emitTargetCall(
12048 CodeGenFunction &CGF, const OMPExecutableDirective &D,
12049 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
12050 const Expr *Device,
12051 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
12052 const OMPLoopDirective &D)>
12053 SizeEmitter) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000012054 llvm_unreachable("Not supported in SIMD-only mode");
12055}
12056
12057bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) {
12058 llvm_unreachable("Not supported in SIMD-only mode");
12059}
12060
12061bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
12062 llvm_unreachable("Not supported in SIMD-only mode");
12063}
12064
12065bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) {
12066 return false;
12067}
12068
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000012069void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF,
12070 const OMPExecutableDirective &D,
12071 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000012072 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000012073 ArrayRef<llvm::Value *> CapturedVars) {
12074 llvm_unreachable("Not supported in SIMD-only mode");
12075}
12076
12077void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
12078 const Expr *NumTeams,
12079 const Expr *ThreadLimit,
12080 SourceLocation Loc) {
12081 llvm_unreachable("Not supported in SIMD-only mode");
12082}
12083
12084void CGOpenMPSIMDRuntime::emitTargetDataCalls(
12085 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
12086 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
12087 llvm_unreachable("Not supported in SIMD-only mode");
12088}
12089
12090void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
12091 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
12092 const Expr *Device) {
12093 llvm_unreachable("Not supported in SIMD-only mode");
12094}
12095
12096void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000012097 const OMPLoopDirective &D,
12098 ArrayRef<Expr *> NumIterations) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000012099 llvm_unreachable("Not supported in SIMD-only mode");
12100}
12101
12102void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
12103 const OMPDependClause *C) {
12104 llvm_unreachable("Not supported in SIMD-only mode");
12105}
12106
12107const VarDecl *
12108CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD,
12109 const VarDecl *NativeParam) const {
12110 llvm_unreachable("Not supported in SIMD-only mode");
12111}
12112
12113Address
12114CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF,
12115 const VarDecl *NativeParam,
12116 const VarDecl *TargetParam) const {
12117 llvm_unreachable("Not supported in SIMD-only mode");
12118}