blob: e9cf692888539bdbf6891adb4a69747fde32ad1d [file] [log] [blame]
Alexey Bataev9959db52014-05-06 10:08:46 +00001//===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Alexey Bataev9959db52014-05-06 10:08:46 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This provides a class for OpenMP runtime code generation.
10//
11//===----------------------------------------------------------------------===//
12
Samuel Antaoee8fb302016-01-06 13:42:12 +000013#include "CGCXXABI.h"
14#include "CGCleanup.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000015#include "CGOpenMPRuntime.h"
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000016#include "CGRecordLayout.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000017#include "CodeGenFunction.h"
John McCall5ad74072017-03-02 20:04:19 +000018#include "clang/CodeGen/ConstantInitBuilder.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000019#include "clang/AST/Decl.h"
Chandler Carruth0d9593d2015-01-14 11:29:14 +000020#include "clang/AST/StmtOpenMP.h"
Richard Smithbf5bcf22018-06-26 23:20:26 +000021#include "clang/Basic/BitmaskEnum.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000022#include "llvm/ADT/ArrayRef.h"
Teresa Johnsonffc4e242016-11-11 05:35:12 +000023#include "llvm/Bitcode/BitcodeReader.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000024#include "llvm/IR/DerivedTypes.h"
25#include "llvm/IR/GlobalValue.h"
26#include "llvm/IR/Value.h"
Samuel Antaoee8fb302016-01-06 13:42:12 +000027#include "llvm/Support/Format.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000028#include "llvm/Support/raw_ostream.h"
Alexey Bataev23b69422014-06-18 07:08:49 +000029#include <cassert>
Alexey Bataev9959db52014-05-06 10:08:46 +000030
31using namespace clang;
32using namespace CodeGen;
33
Benjamin Kramerc52193f2014-10-10 13:57:57 +000034namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000035/// Base class for handling code generation inside OpenMP regions.
Alexey Bataev18095712014-10-10 12:19:54 +000036class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo {
37public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000038 /// Kinds of OpenMP regions used in codegen.
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000039 enum CGOpenMPRegionKind {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000040 /// Region with outlined function for standalone 'parallel'
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000041 /// directive.
42 ParallelOutlinedRegion,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000043 /// Region with outlined function for standalone 'task' directive.
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000044 TaskOutlinedRegion,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000045 /// Region for constructs that do not require function outlining,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000046 /// like 'for', 'sections', 'atomic' etc. directives.
47 InlinedRegion,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000048 /// Region with outlined function for standalone 'target' directive.
Samuel Antaobed3c462015-10-02 16:14:20 +000049 TargetRegion,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000050 };
Alexey Bataev18095712014-10-10 12:19:54 +000051
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000052 CGOpenMPRegionInfo(const CapturedStmt &CS,
53 const CGOpenMPRegionKind RegionKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +000054 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
55 bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000056 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind),
Alexey Bataev25e5b442015-09-15 12:52:43 +000057 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000058
59 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +000060 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind,
61 bool HasCancel)
Alexey Bataev81c7ea02015-07-03 09:56:58 +000062 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen),
Alexey Bataev25e5b442015-09-15 12:52:43 +000063 Kind(Kind), HasCancel(HasCancel) {}
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000064
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000065 /// Get a variable or parameter for storing global thread id
Alexey Bataev18095712014-10-10 12:19:54 +000066 /// inside OpenMP construct.
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000067 virtual const VarDecl *getThreadIDVariable() const = 0;
Alexey Bataev18095712014-10-10 12:19:54 +000068
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000069 /// Emit the captured statement body.
Hans Wennborg7eb54642015-09-10 17:07:54 +000070 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000071
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000072 /// Get an LValue for the current ThreadID variable.
Alexey Bataev62b63b12015-03-10 07:28:44 +000073 /// \return LValue for thread id variable. This LValue always has type int32*.
74 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF);
Alexey Bataev18095712014-10-10 12:19:54 +000075
Alexey Bataev48591dd2016-04-20 04:01:36 +000076 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {}
77
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000078 CGOpenMPRegionKind getRegionKind() const { return RegionKind; }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000079
Alexey Bataev81c7ea02015-07-03 09:56:58 +000080 OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
81
Alexey Bataev25e5b442015-09-15 12:52:43 +000082 bool hasCancel() const { return HasCancel; }
83
Alexey Bataev18095712014-10-10 12:19:54 +000084 static bool classof(const CGCapturedStmtInfo *Info) {
85 return Info->getKind() == CR_OpenMP;
86 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000087
Alexey Bataev48591dd2016-04-20 04:01:36 +000088 ~CGOpenMPRegionInfo() override = default;
89
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000090protected:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +000091 CGOpenMPRegionKind RegionKind;
Hans Wennborg45c74392016-01-12 20:54:36 +000092 RegionCodeGenTy CodeGen;
Alexey Bataev81c7ea02015-07-03 09:56:58 +000093 OpenMPDirectiveKind Kind;
Alexey Bataev25e5b442015-09-15 12:52:43 +000094 bool HasCancel;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000095};
Alexey Bataev18095712014-10-10 12:19:54 +000096
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000097/// API for captured statement code generation in OpenMP constructs.
Alexey Bataev48591dd2016-04-20 04:01:36 +000098class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +000099public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000100 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000101 const RegionCodeGenTy &CodeGen,
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +0000102 OpenMPDirectiveKind Kind, bool HasCancel,
103 StringRef HelperName)
Alexey Bataev25e5b442015-09-15 12:52:43 +0000104 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind,
105 HasCancel),
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +0000106 ThreadIDVar(ThreadIDVar), HelperName(HelperName) {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000107 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
108 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000109
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000110 /// Get a variable or parameter for storing global thread id
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000111 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000112 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000113
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000114 /// Get the name of the capture helper.
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +0000115 StringRef getHelperName() const override { return HelperName; }
Alexey Bataev18095712014-10-10 12:19:54 +0000116
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000117 static bool classof(const CGCapturedStmtInfo *Info) {
118 return CGOpenMPRegionInfo::classof(Info) &&
119 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
120 ParallelOutlinedRegion;
121 }
122
Alexey Bataev18095712014-10-10 12:19:54 +0000123private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000124 /// A variable or parameter storing global thread id for OpenMP
Alexey Bataev18095712014-10-10 12:19:54 +0000125 /// constructs.
126 const VarDecl *ThreadIDVar;
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +0000127 StringRef HelperName;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000128};
129
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000130/// API for captured statement code generation in OpenMP constructs.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000131class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000132public:
Alexey Bataev48591dd2016-04-20 04:01:36 +0000133 class UntiedTaskActionTy final : public PrePostActionTy {
134 bool Untied;
135 const VarDecl *PartIDVar;
136 const RegionCodeGenTy UntiedCodeGen;
137 llvm::SwitchInst *UntiedSwitch = nullptr;
138
139 public:
140 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar,
141 const RegionCodeGenTy &UntiedCodeGen)
142 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {}
143 void Enter(CodeGenFunction &CGF) override {
144 if (Untied) {
145 // Emit task switching point.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000146 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue(
Alexey Bataev48591dd2016-04-20 04:01:36 +0000147 CGF.GetAddrOfLocalVar(PartIDVar),
148 PartIDVar->getType()->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000149 llvm::Value *Res =
150 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation());
151 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done.");
Alexey Bataev48591dd2016-04-20 04:01:36 +0000152 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB);
153 CGF.EmitBlock(DoneBB);
154 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
155 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
156 UntiedSwitch->addCase(CGF.Builder.getInt32(0),
157 CGF.Builder.GetInsertBlock());
158 emitUntiedSwitch(CGF);
159 }
160 }
161 void emitUntiedSwitch(CodeGenFunction &CGF) const {
162 if (Untied) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000163 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue(
Alexey Bataev48591dd2016-04-20 04:01:36 +0000164 CGF.GetAddrOfLocalVar(PartIDVar),
165 PartIDVar->getType()->castAs<PointerType>());
166 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
167 PartIdLVal);
168 UntiedCodeGen(CGF);
169 CodeGenFunction::JumpDest CurPoint =
170 CGF.getJumpDestInCurrentScope(".untied.next.");
171 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
172 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp."));
173 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()),
174 CGF.Builder.GetInsertBlock());
175 CGF.EmitBranchThroughCleanup(CurPoint);
176 CGF.EmitBlock(CurPoint.getBlock());
177 }
178 }
179 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); }
180 };
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000181 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS,
Alexey Bataev62b63b12015-03-10 07:28:44 +0000182 const VarDecl *ThreadIDVar,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000183 const RegionCodeGenTy &CodeGen,
Alexey Bataev48591dd2016-04-20 04:01:36 +0000184 OpenMPDirectiveKind Kind, bool HasCancel,
185 const UntiedTaskActionTy &Action)
Alexey Bataev25e5b442015-09-15 12:52:43 +0000186 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel),
Alexey Bataev48591dd2016-04-20 04:01:36 +0000187 ThreadIDVar(ThreadIDVar), Action(Action) {
Alexey Bataev62b63b12015-03-10 07:28:44 +0000188 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region.");
189 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000190
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000191 /// Get a variable or parameter for storing global thread id
Alexey Bataev62b63b12015-03-10 07:28:44 +0000192 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000193 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000194
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000195 /// Get an LValue for the current ThreadID variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000196 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000197
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000198 /// Get the name of the capture helper.
Alexey Bataev62b63b12015-03-10 07:28:44 +0000199 StringRef getHelperName() const override { return ".omp_outlined."; }
200
Alexey Bataev48591dd2016-04-20 04:01:36 +0000201 void emitUntiedSwitch(CodeGenFunction &CGF) override {
202 Action.emitUntiedSwitch(CGF);
203 }
204
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000205 static bool classof(const CGCapturedStmtInfo *Info) {
206 return CGOpenMPRegionInfo::classof(Info) &&
207 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() ==
208 TaskOutlinedRegion;
209 }
210
Alexey Bataev62b63b12015-03-10 07:28:44 +0000211private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000212 /// A variable or parameter storing global thread id for OpenMP
Alexey Bataev62b63b12015-03-10 07:28:44 +0000213 /// constructs.
214 const VarDecl *ThreadIDVar;
Alexey Bataev48591dd2016-04-20 04:01:36 +0000215 /// Action for emitting code for untied tasks.
216 const UntiedTaskActionTy &Action;
Alexey Bataev62b63b12015-03-10 07:28:44 +0000217};
218
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000219/// API for inlined captured statement code generation in OpenMP
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000220/// constructs.
221class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo {
222public:
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000223 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI,
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000224 const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000225 OpenMPDirectiveKind Kind, bool HasCancel)
226 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel),
227 OldCSI(OldCSI),
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000228 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {}
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000229
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000230 // Retrieve the value of the context parameter.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000231 llvm::Value *getContextValue() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000232 if (OuterRegionInfo)
233 return OuterRegionInfo->getContextValue();
234 llvm_unreachable("No context value for inlined OpenMP region");
235 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000236
Hans Wennborg7eb54642015-09-10 17:07:54 +0000237 void setContextValue(llvm::Value *V) override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000238 if (OuterRegionInfo) {
239 OuterRegionInfo->setContextValue(V);
240 return;
241 }
242 llvm_unreachable("No context value for inlined OpenMP region");
243 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000244
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000245 /// Lookup the captured field decl for a variable.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000246 const FieldDecl *lookup(const VarDecl *VD) const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000247 if (OuterRegionInfo)
248 return OuterRegionInfo->lookup(VD);
Alexey Bataev69c62a92015-04-15 04:52:20 +0000249 // If there is no outer outlined region,no need to lookup in a list of
250 // captured variables, we can use the original one.
251 return nullptr;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000252 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000253
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000254 FieldDecl *getThisFieldDecl() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000255 if (OuterRegionInfo)
256 return OuterRegionInfo->getThisFieldDecl();
257 return nullptr;
258 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000259
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000260 /// Get a variable or parameter for storing global thread id
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000261 /// inside OpenMP construct.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000262 const VarDecl *getThreadIDVariable() const override {
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000263 if (OuterRegionInfo)
264 return OuterRegionInfo->getThreadIDVariable();
265 return nullptr;
266 }
Alexey Bataev62b63b12015-03-10 07:28:44 +0000267
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000268 /// Get an LValue for the current ThreadID variable.
Alexey Bataev311a9282017-10-12 13:51:32 +0000269 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override {
270 if (OuterRegionInfo)
271 return OuterRegionInfo->getThreadIDVariableLValue(CGF);
272 llvm_unreachable("No LValue for inlined OpenMP construct");
273 }
274
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000275 /// Get the name of the capture helper.
Alexander Kornienko34eb2072015-04-11 02:00:23 +0000276 StringRef getHelperName() const override {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000277 if (auto *OuterRegionInfo = getOldCSI())
278 return OuterRegionInfo->getHelperName();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000279 llvm_unreachable("No helper name for inlined OpenMP construct");
280 }
281
Alexey Bataev48591dd2016-04-20 04:01:36 +0000282 void emitUntiedSwitch(CodeGenFunction &CGF) override {
283 if (OuterRegionInfo)
284 OuterRegionInfo->emitUntiedSwitch(CGF);
285 }
286
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000287 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; }
288
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000289 static bool classof(const CGCapturedStmtInfo *Info) {
290 return CGOpenMPRegionInfo::classof(Info) &&
291 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion;
292 }
293
Alexey Bataev48591dd2016-04-20 04:01:36 +0000294 ~CGOpenMPInlinedRegionInfo() override = default;
295
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000296private:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000297 /// CodeGen info about outer OpenMP region.
Alexey Bataev8cbe0a62015-02-26 10:27:34 +0000298 CodeGenFunction::CGCapturedStmtInfo *OldCSI;
299 CGOpenMPRegionInfo *OuterRegionInfo;
Alexey Bataev18095712014-10-10 12:19:54 +0000300};
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000301
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000302/// API for captured statement code generation in OpenMP target
Samuel Antaobed3c462015-10-02 16:14:20 +0000303/// constructs. For this captures, implicit parameters are used instead of the
Samuel Antaoee8fb302016-01-06 13:42:12 +0000304/// captured fields. The name of the target region has to be unique in a given
305/// application so it is provided by the client, because only the client has
306/// the information to generate that.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000307class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo {
Samuel Antaobed3c462015-10-02 16:14:20 +0000308public:
309 CGOpenMPTargetRegionInfo(const CapturedStmt &CS,
Samuel Antaoee8fb302016-01-06 13:42:12 +0000310 const RegionCodeGenTy &CodeGen, StringRef HelperName)
Samuel Antaobed3c462015-10-02 16:14:20 +0000311 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target,
Samuel Antaoee8fb302016-01-06 13:42:12 +0000312 /*HasCancel=*/false),
313 HelperName(HelperName) {}
Samuel Antaobed3c462015-10-02 16:14:20 +0000314
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000315 /// This is unused for target regions because each starts executing
Samuel Antaobed3c462015-10-02 16:14:20 +0000316 /// with a single thread.
317 const VarDecl *getThreadIDVariable() const override { return nullptr; }
318
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000319 /// Get the name of the capture helper.
Samuel Antaoee8fb302016-01-06 13:42:12 +0000320 StringRef getHelperName() const override { return HelperName; }
Samuel Antaobed3c462015-10-02 16:14:20 +0000321
322 static bool classof(const CGCapturedStmtInfo *Info) {
323 return CGOpenMPRegionInfo::classof(Info) &&
324 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion;
325 }
Samuel Antaoee8fb302016-01-06 13:42:12 +0000326
327private:
328 StringRef HelperName;
Samuel Antaobed3c462015-10-02 16:14:20 +0000329};
330
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000331static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000332 llvm_unreachable("No codegen for expressions");
333}
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000334/// API for generation of expressions captured in a innermost OpenMP
Samuel Antaob68e2db2016-03-03 16:20:23 +0000335/// region.
Alexey Bataev48591dd2016-04-20 04:01:36 +0000336class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000337public:
338 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS)
339 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen,
340 OMPD_unknown,
341 /*HasCancel=*/false),
342 PrivScope(CGF) {
343 // Make sure the globals captured in the provided statement are local by
344 // using the privatization logic. We assume the same variable is not
345 // captured more than once.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000346 for (const auto &C : CS.captures()) {
Samuel Antaob68e2db2016-03-03 16:20:23 +0000347 if (!C.capturesVariable() && !C.capturesVariableByCopy())
348 continue;
349
350 const VarDecl *VD = C.getCapturedVar();
351 if (VD->isLocalVarDeclOrParm())
352 continue;
353
Bruno Ricci5fc4db72018-12-21 14:10:18 +0000354 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
Samuel Antaob68e2db2016-03-03 16:20:23 +0000355 /*RefersToEnclosingVariableOrCapture=*/false,
356 VD->getType().getNonReferenceType(), VK_LValue,
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000357 C.getLocation());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000358 PrivScope.addPrivate(
359 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(); });
Samuel Antaob68e2db2016-03-03 16:20:23 +0000360 }
361 (void)PrivScope.Privatize();
362 }
363
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000364 /// Lookup the captured field decl for a variable.
Samuel Antaob68e2db2016-03-03 16:20:23 +0000365 const FieldDecl *lookup(const VarDecl *VD) const override {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000366 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD))
Samuel Antaob68e2db2016-03-03 16:20:23 +0000367 return FD;
368 return nullptr;
369 }
370
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000371 /// Emit the captured statement body.
Samuel Antaob68e2db2016-03-03 16:20:23 +0000372 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override {
373 llvm_unreachable("No body for expressions");
374 }
375
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000376 /// Get a variable or parameter for storing global thread id
Samuel Antaob68e2db2016-03-03 16:20:23 +0000377 /// inside OpenMP construct.
378 const VarDecl *getThreadIDVariable() const override {
379 llvm_unreachable("No thread id for expressions");
380 }
381
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000382 /// Get the name of the capture helper.
Samuel Antaob68e2db2016-03-03 16:20:23 +0000383 StringRef getHelperName() const override {
384 llvm_unreachable("No helper name for expressions");
385 }
386
387 static bool classof(const CGCapturedStmtInfo *Info) { return false; }
388
389private:
390 /// Private scope to capture global variables.
391 CodeGenFunction::OMPPrivateScope PrivScope;
392};
393
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000394/// RAII for emitting code of OpenMP constructs.
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000395class InlinedOpenMPRegionRAII {
396 CodeGenFunction &CGF;
Alexey Bataev4ba78a42016-04-27 07:56:03 +0000397 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields;
398 FieldDecl *LambdaThisCaptureField = nullptr;
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000399 const CodeGen::CGBlockInfo *BlockInfo = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000400
401public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000402 /// Constructs region for combined constructs.
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000403 /// \param CodeGen Code generation sequence for combined directives. Includes
404 /// a list of functions used for code generation of implicitly inlined
405 /// regions.
Alexey Bataev81c7ea02015-07-03 09:56:58 +0000406 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen,
Alexey Bataev25e5b442015-09-15 12:52:43 +0000407 OpenMPDirectiveKind Kind, bool HasCancel)
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000408 : CGF(CGF) {
409 // Start emission for the construct.
Alexey Bataev25e5b442015-09-15 12:52:43 +0000410 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo(
411 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel);
Alexey Bataev4ba78a42016-04-27 07:56:03 +0000412 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
413 LambdaThisCaptureField = CGF.LambdaThisCaptureField;
414 CGF.LambdaThisCaptureField = nullptr;
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000415 BlockInfo = CGF.BlockInfo;
416 CGF.BlockInfo = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000417 }
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +0000418
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000419 ~InlinedOpenMPRegionRAII() {
420 // Restore original CapturedStmtInfo only if we're done with code emission.
421 auto *OldCSI =
422 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI();
423 delete CGF.CapturedStmtInfo;
424 CGF.CapturedStmtInfo = OldCSI;
Alexey Bataev4ba78a42016-04-27 07:56:03 +0000425 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields);
426 CGF.LambdaThisCaptureField = LambdaThisCaptureField;
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000427 CGF.BlockInfo = BlockInfo;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +0000428 }
429};
430
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000431/// Values for bit flags used in the ident_t to describe the fields.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000432/// All enumeric elements are named and described in accordance with the code
James Y Knight5d71fc52019-01-29 16:37:27 +0000433/// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h
Alexey Bataev0f87dbe2017-08-14 17:56:13 +0000434enum OpenMPLocationFlags : unsigned {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000435 /// Use trampoline for internal microtask.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000436 OMP_IDENT_IMD = 0x01,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000437 /// Use c-style ident structure.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000438 OMP_IDENT_KMPC = 0x02,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000439 /// Atomic reduction option for kmpc_reduce.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000440 OMP_ATOMIC_REDUCE = 0x10,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000441 /// Explicit 'barrier' directive.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000442 OMP_IDENT_BARRIER_EXPL = 0x20,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000443 /// Implicit barrier in code.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000444 OMP_IDENT_BARRIER_IMPL = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000445 /// Implicit barrier in 'for' directive.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000446 OMP_IDENT_BARRIER_IMPL_FOR = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000447 /// Implicit barrier in 'sections' directive.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000448 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000449 /// Implicit barrier in 'single' directive.
Alexey Bataev0f87dbe2017-08-14 17:56:13 +0000450 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140,
451 /// Call of __kmp_for_static_init for static loop.
452 OMP_IDENT_WORK_LOOP = 0x200,
453 /// Call of __kmp_for_static_init for sections.
454 OMP_IDENT_WORK_SECTIONS = 0x400,
455 /// Call of __kmp_for_static_init for distribute.
456 OMP_IDENT_WORK_DISTRIBUTE = 0x800,
457 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE)
Alexey Bataev50b3c952016-02-19 10:38:26 +0000458};
459
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +0000460namespace {
461LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
462/// Values for bit flags for marking which requires clauses have been used.
463enum OpenMPOffloadingRequiresDirFlags : int64_t {
464 /// flag undefined.
465 OMP_REQ_UNDEFINED = 0x000,
466 /// no requires clause present.
467 OMP_REQ_NONE = 0x001,
468 /// reverse_offload clause.
469 OMP_REQ_REVERSE_OFFLOAD = 0x002,
470 /// unified_address clause.
471 OMP_REQ_UNIFIED_ADDRESS = 0x004,
472 /// unified_shared_memory clause.
473 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008,
474 /// dynamic_allocators clause.
475 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010,
476 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS)
477};
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +0000478
479enum OpenMPOffloadingReservedDeviceIDs {
480 /// Device ID if the device was not defined, runtime should get it
481 /// from environment variables in the spec.
482 OMP_DEVICEID_UNDEF = -1,
483};
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +0000484} // anonymous namespace
485
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000486/// Describes ident structure that describes a source location.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000487/// All descriptions are taken from
James Y Knight5d71fc52019-01-29 16:37:27 +0000488/// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h
Alexey Bataev50b3c952016-02-19 10:38:26 +0000489/// Original structure:
490/// typedef struct ident {
491/// kmp_int32 reserved_1; /**< might be used in Fortran;
492/// see above */
493/// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags;
494/// KMP_IDENT_KMPC identifies this union
495/// member */
496/// kmp_int32 reserved_2; /**< not really used in Fortran any more;
497/// see above */
498///#if USE_ITT_BUILD
499/// /* but currently used for storing
500/// region-specific ITT */
501/// /* contextual information. */
502///#endif /* USE_ITT_BUILD */
503/// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for
504/// C++ */
505/// char const *psource; /**< String describing the source location.
506/// The string is composed of semi-colon separated
507// fields which describe the source file,
508/// the function and a pair of line numbers that
509/// delimit the construct.
510/// */
511/// } ident_t;
512enum IdentFieldIndex {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000513 /// might be used in Fortran
Alexey Bataev50b3c952016-02-19 10:38:26 +0000514 IdentField_Reserved_1,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000515 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000516 IdentField_Flags,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000517 /// Not really used in Fortran any more
Alexey Bataev50b3c952016-02-19 10:38:26 +0000518 IdentField_Reserved_2,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000519 /// Source[4] in Fortran, do not use for C++
Alexey Bataev50b3c952016-02-19 10:38:26 +0000520 IdentField_Reserved_3,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000521 /// String describing the source location. The string is composed of
Alexey Bataev50b3c952016-02-19 10:38:26 +0000522 /// semi-colon separated fields which describe the source file, the function
523 /// and a pair of line numbers that delimit the construct.
524 IdentField_PSource
525};
526
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000527/// Schedule types for 'omp for' loops (these enumerators are taken from
Alexey Bataev50b3c952016-02-19 10:38:26 +0000528/// the enum sched_type in kmp.h).
529enum OpenMPSchedType {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000530 /// Lower bound for default (unordered) versions.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000531 OMP_sch_lower = 32,
532 OMP_sch_static_chunked = 33,
533 OMP_sch_static = 34,
534 OMP_sch_dynamic_chunked = 35,
535 OMP_sch_guided_chunked = 36,
536 OMP_sch_runtime = 37,
537 OMP_sch_auto = 38,
Alexey Bataev6cff6242016-05-30 13:05:14 +0000538 /// static with chunk adjustment (e.g., simd)
Samuel Antao4c8035b2016-12-12 18:00:20 +0000539 OMP_sch_static_balanced_chunked = 45,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000540 /// Lower bound for 'ordered' versions.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000541 OMP_ord_lower = 64,
542 OMP_ord_static_chunked = 65,
543 OMP_ord_static = 66,
544 OMP_ord_dynamic_chunked = 67,
545 OMP_ord_guided_chunked = 68,
546 OMP_ord_runtime = 69,
547 OMP_ord_auto = 70,
548 OMP_sch_default = OMP_sch_static,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000549 /// dist_schedule types
Carlo Bertollifc35ad22016-03-07 16:04:49 +0000550 OMP_dist_sch_static_chunked = 91,
551 OMP_dist_sch_static = 92,
Alexey Bataev9ebd7422016-05-10 09:57:36 +0000552 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers.
553 /// Set if the monotonic schedule modifier was present.
554 OMP_sch_modifier_monotonic = (1 << 29),
555 /// Set if the nonmonotonic schedule modifier was present.
556 OMP_sch_modifier_nonmonotonic = (1 << 30),
Alexey Bataev50b3c952016-02-19 10:38:26 +0000557};
558
559enum OpenMPRTLFunction {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000560 /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000561 /// kmpc_micro microtask, ...);
562 OMPRTL__kmpc_fork_call,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000563 /// Call to void *__kmpc_threadprivate_cached(ident_t *loc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000564 /// kmp_int32 global_tid, void *data, size_t size, void ***cache);
565 OMPRTL__kmpc_threadprivate_cached,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000566 /// Call to void __kmpc_threadprivate_register( ident_t *,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000567 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
568 OMPRTL__kmpc_threadprivate_register,
569 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc);
570 OMPRTL__kmpc_global_thread_num,
571 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
572 // kmp_critical_name *crit);
573 OMPRTL__kmpc_critical,
574 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32
575 // global_tid, kmp_critical_name *crit, uintptr_t hint);
576 OMPRTL__kmpc_critical_with_hint,
577 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
578 // kmp_critical_name *crit);
579 OMPRTL__kmpc_end_critical,
580 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
581 // global_tid);
582 OMPRTL__kmpc_cancel_barrier,
583 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
584 OMPRTL__kmpc_barrier,
585 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
586 OMPRTL__kmpc_for_static_fini,
587 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
588 // global_tid);
589 OMPRTL__kmpc_serialized_parallel,
590 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
591 // global_tid);
592 OMPRTL__kmpc_end_serialized_parallel,
593 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
594 // kmp_int32 num_threads);
595 OMPRTL__kmpc_push_num_threads,
596 // Call to void __kmpc_flush(ident_t *loc);
597 OMPRTL__kmpc_flush,
598 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid);
599 OMPRTL__kmpc_master,
600 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid);
601 OMPRTL__kmpc_end_master,
602 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
603 // int end_part);
604 OMPRTL__kmpc_omp_taskyield,
605 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid);
606 OMPRTL__kmpc_single,
607 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid);
608 OMPRTL__kmpc_end_single,
609 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
610 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
611 // kmp_routine_entry_t *task_entry);
612 OMPRTL__kmpc_omp_task_alloc,
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +0000613 // Call to kmp_task_t * __kmpc_omp_target_task_alloc(ident_t *,
614 // kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t,
615 // size_t sizeof_shareds, kmp_routine_entry_t *task_entry,
616 // kmp_int64 device_id);
617 OMPRTL__kmpc_omp_target_task_alloc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000618 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *
619 // new_task);
620 OMPRTL__kmpc_omp_task,
621 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
622 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
623 // kmp_int32 didit);
624 OMPRTL__kmpc_copyprivate,
625 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
626 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
627 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
628 OMPRTL__kmpc_reduce,
629 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
630 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
631 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
632 // *lck);
633 OMPRTL__kmpc_reduce_nowait,
634 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
635 // kmp_critical_name *lck);
636 OMPRTL__kmpc_end_reduce,
637 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
638 // kmp_critical_name *lck);
639 OMPRTL__kmpc_end_reduce_nowait,
640 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
641 // kmp_task_t * new_task);
642 OMPRTL__kmpc_omp_task_begin_if0,
643 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
644 // kmp_task_t * new_task);
645 OMPRTL__kmpc_omp_task_complete_if0,
646 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
647 OMPRTL__kmpc_ordered,
648 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
649 OMPRTL__kmpc_end_ordered,
650 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
651 // global_tid);
652 OMPRTL__kmpc_omp_taskwait,
653 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
654 OMPRTL__kmpc_taskgroup,
655 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
656 OMPRTL__kmpc_end_taskgroup,
657 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
658 // int proc_bind);
659 OMPRTL__kmpc_push_proc_bind,
660 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32
661 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t
662 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
663 OMPRTL__kmpc_omp_task_with_deps,
664 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32
665 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
666 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
667 OMPRTL__kmpc_omp_wait_deps,
668 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
669 // global_tid, kmp_int32 cncl_kind);
670 OMPRTL__kmpc_cancellationpoint,
671 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
672 // kmp_int32 cncl_kind);
673 OMPRTL__kmpc_cancel,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000674 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid,
675 // kmp_int32 num_teams, kmp_int32 thread_limit);
676 OMPRTL__kmpc_push_num_teams,
Alexey Bataev7292c292016-04-25 12:22:29 +0000677 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
678 // microtask, ...);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000679 OMPRTL__kmpc_fork_teams,
Alexey Bataev7292c292016-04-25 12:22:29 +0000680 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
681 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
682 // sched, kmp_uint64 grainsize, void *task_dup);
683 OMPRTL__kmpc_taskloop,
Alexey Bataev8b427062016-05-25 12:36:08 +0000684 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32
685 // num_dims, struct kmp_dim *dims);
686 OMPRTL__kmpc_doacross_init,
687 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid);
688 OMPRTL__kmpc_doacross_fini,
689 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64
690 // *vec);
691 OMPRTL__kmpc_doacross_post,
692 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64
693 // *vec);
694 OMPRTL__kmpc_doacross_wait,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000695 // Call to void *__kmpc_task_reduction_init(int gtid, int num_data, void
696 // *data);
697 OMPRTL__kmpc_task_reduction_init,
698 // Call to void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
699 // *d);
700 OMPRTL__kmpc_task_reduction_get_th_data,
Alexey Bataev6cf7b712019-04-08 19:06:42 +0000701 // Call to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al);
Alexey Bataev4f680db2019-03-19 16:41:16 +0000702 OMPRTL__kmpc_alloc,
Alexey Bataev6cf7b712019-04-08 19:06:42 +0000703 // Call to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al);
Alexey Bataev4f680db2019-03-19 16:41:16 +0000704 OMPRTL__kmpc_free,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000705
706 //
707 // Offloading related calls
708 //
Alexey Bataev7bb33532019-01-07 21:30:43 +0000709 // Call to void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64
710 // size);
711 OMPRTL__kmpc_push_target_tripcount,
George Rokos63bc9d62017-11-21 18:25:12 +0000712 // Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +0000713 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev50b3c952016-02-19 10:38:26 +0000714 // *arg_types);
715 OMPRTL__tgt_target,
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000716 // Call to int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +0000717 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000718 // *arg_types);
719 OMPRTL__tgt_target_nowait,
George Rokos63bc9d62017-11-21 18:25:12 +0000720 // Call to int32_t __tgt_target_teams(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +0000721 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
George Rokos63bc9d62017-11-21 18:25:12 +0000722 // *arg_types, int32_t num_teams, int32_t thread_limit);
Samuel Antaob68e2db2016-03-03 16:20:23 +0000723 OMPRTL__tgt_target_teams,
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000724 // Call to int32_t __tgt_target_teams_nowait(int64_t device_id, void
Alexey Bataeva90fc662019-06-25 16:00:43 +0000725 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000726 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
727 OMPRTL__tgt_target_teams_nowait,
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +0000728 // Call to void __tgt_register_requires(int64_t flags);
729 OMPRTL__tgt_register_requires,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000730 // Call to void __tgt_register_lib(__tgt_bin_desc *desc);
731 OMPRTL__tgt_register_lib,
732 // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc);
733 OMPRTL__tgt_unregister_lib,
George Rokos63bc9d62017-11-21 18:25:12 +0000734 // Call to void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +0000735 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
Samuel Antaodf158d52016-04-27 22:58:19 +0000736 OMPRTL__tgt_target_data_begin,
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000737 // Call to void __tgt_target_data_begin_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +0000738 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000739 // *arg_types);
740 OMPRTL__tgt_target_data_begin_nowait,
George Rokos63bc9d62017-11-21 18:25:12 +0000741 // Call to void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
742 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types);
Samuel Antaodf158d52016-04-27 22:58:19 +0000743 OMPRTL__tgt_target_data_end,
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000744 // Call to void __tgt_target_data_end_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +0000745 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000746 // *arg_types);
747 OMPRTL__tgt_target_data_end_nowait,
George Rokos63bc9d62017-11-21 18:25:12 +0000748 // Call to void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +0000749 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
Samuel Antao8d2d7302016-05-26 18:30:22 +0000750 OMPRTL__tgt_target_data_update,
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000751 // Call to void __tgt_target_data_update_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +0000752 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000753 // *arg_types);
754 OMPRTL__tgt_target_data_update_nowait,
Michael Krused47b9432019-08-05 18:43:21 +0000755 // Call to int64_t __tgt_mapper_num_components(void *rt_mapper_handle);
756 OMPRTL__tgt_mapper_num_components,
757 // Call to void __tgt_push_mapper_component(void *rt_mapper_handle, void
758 // *base, void *begin, int64_t size, int64_t type);
759 OMPRTL__tgt_push_mapper_component,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000760};
761
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000762/// A basic class for pre|post-action for advanced codegen sequence for OpenMP
763/// region.
764class CleanupTy final : public EHScopeStack::Cleanup {
765 PrePostActionTy *Action;
766
767public:
768 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
769 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
770 if (!CGF.HaveInsertPoint())
771 return;
772 Action->Exit(CGF);
773 }
774};
775
Hans Wennborg7eb54642015-09-10 17:07:54 +0000776} // anonymous namespace
Alexey Bataev18095712014-10-10 12:19:54 +0000777
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000778void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const {
779 CodeGenFunction::RunCleanupsScope Scope(CGF);
780 if (PrePostAction) {
781 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction);
782 Callback(CodeGen, CGF, *PrePostAction);
783 } else {
784 PrePostActionTy Action;
785 Callback(CodeGen, CGF, Action);
786 }
787}
788
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000789/// Check if the combiner is a call to UDR combiner and if it is so return the
790/// UDR decl used for reduction.
791static const OMPDeclareReductionDecl *
792getReductionInit(const Expr *ReductionOp) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000793 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
794 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
795 if (const auto *DRE =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000796 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000797 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000798 return DRD;
799 return nullptr;
800}
801
802static void emitInitWithReductionInitializer(CodeGenFunction &CGF,
803 const OMPDeclareReductionDecl *DRD,
804 const Expr *InitOp,
805 Address Private, Address Original,
806 QualType Ty) {
807 if (DRD->getInitializer()) {
808 std::pair<llvm::Function *, llvm::Function *> Reduction =
809 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000810 const auto *CE = cast<CallExpr>(InitOp);
811 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000812 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
813 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000814 const auto *LHSDRE =
815 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr());
816 const auto *RHSDRE =
817 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000818 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
819 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000820 [=]() { return Private; });
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000821 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000822 [=]() { return Original; });
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000823 (void)PrivateScope.Privatize();
824 RValue Func = RValue::get(Reduction.second);
825 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
826 CGF.EmitIgnoredExpr(InitOp);
827 } else {
828 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty);
Alexey Bataev18fa2322018-05-02 14:20:50 +0000829 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"});
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000830 auto *GV = new llvm::GlobalVariable(
831 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,
Alexey Bataev18fa2322018-05-02 14:20:50 +0000832 llvm::GlobalValue::PrivateLinkage, Init, Name);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000833 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty);
834 RValue InitRVal;
835 switch (CGF.getEvaluationKind(Ty)) {
836 case TEK_Scalar:
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000837 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000838 break;
839 case TEK_Complex:
840 InitRVal =
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000841 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation()));
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000842 break;
843 case TEK_Aggregate:
844 InitRVal = RValue::getAggregate(LV.getAddress());
845 break;
846 }
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000847 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000848 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal);
849 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(),
850 /*IsInitializer=*/false);
851 }
852}
853
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000854/// Emit initialization of arrays of complex types.
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000855/// \param DestAddr Address of the array.
856/// \param Type Type of array.
857/// \param Init Initial expression of array.
858/// \param SrcAddr Address of the original array.
859static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
Alexey Bataeva7b19152017-10-12 20:03:39 +0000860 QualType Type, bool EmitDeclareReductionInit,
861 const Expr *Init,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000862 const OMPDeclareReductionDecl *DRD,
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000863 Address SrcAddr = Address::invalid()) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000864 // Perform element-by-element initialization.
865 QualType ElementTy;
866
867 // Drill down to the base element type on both arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000868 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
869 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000870 DestAddr =
871 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType());
872 if (DRD)
873 SrcAddr =
874 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType());
875
876 llvm::Value *SrcBegin = nullptr;
877 if (DRD)
878 SrcBegin = SrcAddr.getPointer();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000879 llvm::Value *DestBegin = DestAddr.getPointer();
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000880 // Cast from pointer to array type to pointer to single element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000881 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000882 // The basic structure here is a while-do loop.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000883 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body");
884 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done");
885 llvm::Value *IsEmpty =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000886 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty");
887 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
888
889 // Enter the loop body, making that address the current address.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000890 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000891 CGF.EmitBlock(BodyBB);
892
893 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
894
895 llvm::PHINode *SrcElementPHI = nullptr;
896 Address SrcElementCurrent = Address::invalid();
897 if (DRD) {
898 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2,
899 "omp.arraycpy.srcElementPast");
900 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
901 SrcElementCurrent =
902 Address(SrcElementPHI,
903 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
904 }
905 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI(
906 DestBegin->getType(), 2, "omp.arraycpy.destElementPast");
907 DestElementPHI->addIncoming(DestBegin, EntryBB);
908 Address DestElementCurrent =
909 Address(DestElementPHI,
910 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize));
911
912 // Emit copy.
913 {
914 CodeGenFunction::RunCleanupsScope InitScope(CGF);
Alexey Bataeva7b19152017-10-12 20:03:39 +0000915 if (EmitDeclareReductionInit) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000916 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent,
917 SrcElementCurrent, ElementTy);
918 } else
919 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(),
920 /*IsInitializer=*/false);
921 }
922
923 if (DRD) {
924 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000925 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000926 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
927 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock());
928 }
929
930 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000931 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000932 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
933 // Check whether we've reached the end.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000934 llvm::Value *Done =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000935 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
936 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
937 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock());
938
939 // Done.
940 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
941}
942
943LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) {
Alexey Bataevf47c4b42017-09-26 13:47:31 +0000944 return CGF.EmitOMPSharedLValue(E);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000945}
946
947LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF,
948 const Expr *E) {
949 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E))
950 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false);
951 return LValue();
952}
953
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000954void ReductionCodeGen::emitAggregateInitialization(
955 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal,
956 const OMPDeclareReductionDecl *DRD) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000957 // Emit VarDecl with copy init for arrays.
958 // Get the address of the original variable captured in current
959 // captured region.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000960 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000961 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
Alexey Bataeva7b19152017-10-12 20:03:39 +0000962 bool EmitDeclareReductionInit =
963 DRD && (DRD->getInitializer() || !PrivateVD->hasInit());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000964 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(),
Alexey Bataeva7b19152017-10-12 20:03:39 +0000965 EmitDeclareReductionInit,
966 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
967 : PrivateVD->getInit(),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000968 DRD, SharedLVal.getAddress());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000969}
970
971ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds,
972 ArrayRef<const Expr *> Privates,
973 ArrayRef<const Expr *> ReductionOps) {
974 ClausesData.reserve(Shareds.size());
975 SharedAddresses.reserve(Shareds.size());
976 Sizes.reserve(Shareds.size());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000977 BaseDecls.reserve(Shareds.size());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000978 auto IPriv = Privates.begin();
979 auto IRed = ReductionOps.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000980 for (const Expr *Ref : Shareds) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000981 ClausesData.emplace_back(Ref, *IPriv, *IRed);
982 std::advance(IPriv, 1);
983 std::advance(IRed, 1);
984 }
985}
986
987void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) {
988 assert(SharedAddresses.size() == N &&
989 "Number of generated lvalues must be exactly N.");
Jonas Hahnfeld4525c822017-10-23 19:01:35 +0000990 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
991 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
992 SharedAddresses.emplace_back(First, Second);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000993}
994
995void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000996 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000997 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
998 QualType PrivateType = PrivateVD->getType();
999 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref);
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001000 if (!PrivateType->isVariablyModifiedType()) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001001 Sizes.emplace_back(
1002 CGF.getTypeSize(
1003 SharedAddresses[N].first.getType().getNonReferenceType()),
1004 nullptr);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001005 return;
1006 }
1007 llvm::Value *Size;
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001008 llvm::Value *SizeInChars;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001009 auto *ElemType =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001010 cast<llvm::PointerType>(SharedAddresses[N].first.getPointer()->getType())
1011 ->getElementType();
1012 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001013 if (AsArraySection) {
1014 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(),
1015 SharedAddresses[N].first.getPointer());
1016 Size = CGF.Builder.CreateNUWAdd(
1017 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001018 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001019 } else {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001020 SizeInChars = CGF.getTypeSize(
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001021 SharedAddresses[N].first.getType().getNonReferenceType());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001022 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001023 }
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001024 Sizes.emplace_back(SizeInChars, Size);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001025 CodeGenFunction::OpaqueValueMapping OpaqueMap(
1026 CGF,
1027 cast<OpaqueValueExpr>(
1028 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),
1029 RValue::get(Size));
1030 CGF.EmitVariablyModifiedType(PrivateType);
1031}
1032
1033void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N,
1034 llvm::Value *Size) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001035 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001036 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1037 QualType PrivateType = PrivateVD->getType();
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001038 if (!PrivateType->isVariablyModifiedType()) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001039 assert(!Size && !Sizes[N].second &&
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001040 "Size should be nullptr for non-variably modified reduction "
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001041 "items.");
1042 return;
1043 }
1044 CodeGenFunction::OpaqueValueMapping OpaqueMap(
1045 CGF,
1046 cast<OpaqueValueExpr>(
1047 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),
1048 RValue::get(Size));
1049 CGF.EmitVariablyModifiedType(PrivateType);
1050}
1051
1052void ReductionCodeGen::emitInitialization(
1053 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal,
1054 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) {
1055 assert(SharedAddresses.size() > N && "No variable was generated");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001056 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001057 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001058 const OMPDeclareReductionDecl *DRD =
1059 getReductionInit(ClausesData[N].ReductionOp);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001060 QualType PrivateType = PrivateVD->getType();
1061 PrivateAddr = CGF.Builder.CreateElementBitCast(
1062 PrivateAddr, CGF.ConvertTypeForMem(PrivateType));
1063 QualType SharedType = SharedAddresses[N].first.getType();
1064 SharedLVal = CGF.MakeAddrLValue(
1065 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(),
1066 CGF.ConvertTypeForMem(SharedType)),
Ivan A. Kosarevf5f20462017-10-12 11:29:46 +00001067 SharedType, SharedAddresses[N].first.getBaseInfo(),
Ivan A. Kosarevb9c59f32017-10-31 11:05:34 +00001068 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType));
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001069 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001070 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001071 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) {
1072 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp,
1073 PrivateAddr, SharedLVal.getAddress(),
1074 SharedLVal.getType());
1075 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
1076 !CGF.isTrivialInitializer(PrivateVD->getInit())) {
1077 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr,
1078 PrivateVD->getType().getQualifiers(),
1079 /*IsInitializer=*/false);
1080 }
1081}
1082
1083bool ReductionCodeGen::needCleanups(unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001084 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001085 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1086 QualType PrivateType = PrivateVD->getType();
1087 QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
1088 return DTorKind != QualType::DK_none;
1089}
1090
1091void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N,
1092 Address PrivateAddr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001093 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001094 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1095 QualType PrivateType = PrivateVD->getType();
1096 QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
1097 if (needCleanups(N)) {
1098 PrivateAddr = CGF.Builder.CreateElementBitCast(
1099 PrivateAddr, CGF.ConvertTypeForMem(PrivateType));
1100 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType);
1101 }
1102}
1103
1104static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
1105 LValue BaseLV) {
1106 BaseTy = BaseTy.getNonReferenceType();
1107 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
1108 !CGF.getContext().hasSameType(BaseTy, ElTy)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001109 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001110 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(), PtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001111 } else {
Ivan A. Kosarev9f9d1572017-10-30 11:49:31 +00001112 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(), BaseTy);
1113 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001114 }
1115 BaseTy = BaseTy->getPointeeType();
1116 }
1117 return CGF.MakeAddrLValue(
1118 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(),
1119 CGF.ConvertTypeForMem(ElTy)),
Ivan A. Kosarevf5f20462017-10-12 11:29:46 +00001120 BaseLV.getType(), BaseLV.getBaseInfo(),
Ivan A. Kosarevb9c59f32017-10-31 11:05:34 +00001121 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType()));
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001122}
1123
1124static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
1125 llvm::Type *BaseLVType, CharUnits BaseLVAlignment,
1126 llvm::Value *Addr) {
1127 Address Tmp = Address::invalid();
1128 Address TopTmp = Address::invalid();
1129 Address MostTopTmp = Address::invalid();
1130 BaseTy = BaseTy.getNonReferenceType();
1131 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
1132 !CGF.getContext().hasSameType(BaseTy, ElTy)) {
1133 Tmp = CGF.CreateMemTemp(BaseTy);
1134 if (TopTmp.isValid())
1135 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp);
1136 else
1137 MostTopTmp = Tmp;
1138 TopTmp = Tmp;
1139 BaseTy = BaseTy->getPointeeType();
1140 }
1141 llvm::Type *Ty = BaseLVType;
1142 if (Tmp.isValid())
1143 Ty = Tmp.getElementType();
1144 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty);
1145 if (Tmp.isValid()) {
1146 CGF.Builder.CreateStore(Addr, Tmp);
1147 return MostTopTmp;
1148 }
1149 return Address(Addr, BaseLVAlignment);
1150}
1151
Alexey Bataev1c44e152018-03-06 18:59:43 +00001152static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001153 const VarDecl *OrigVD = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001154 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) {
1155 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
1156 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001157 Base = TempOASE->getBase()->IgnoreParenImpCasts();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001158 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001159 Base = TempASE->getBase()->IgnoreParenImpCasts();
1160 DE = cast<DeclRefExpr>(Base);
1161 OrigVD = cast<VarDecl>(DE->getDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001162 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
1163 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
1164 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001165 Base = TempASE->getBase()->IgnoreParenImpCasts();
1166 DE = cast<DeclRefExpr>(Base);
1167 OrigVD = cast<VarDecl>(DE->getDecl());
1168 }
Alexey Bataev1c44e152018-03-06 18:59:43 +00001169 return OrigVD;
1170}
1171
1172Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N,
1173 Address PrivateAddr) {
1174 const DeclRefExpr *DE;
1175 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001176 BaseDecls.emplace_back(OrigVD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001177 LValue OriginalBaseLValue = CGF.EmitLValue(DE);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001178 LValue BaseLValue =
1179 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
1180 OriginalBaseLValue);
1181 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff(
1182 BaseLValue.getPointer(), SharedAddresses[N].first.getPointer());
Jonas Hahnfeld273d2612017-12-06 19:15:28 +00001183 llvm::Value *PrivatePointer =
1184 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1185 PrivateAddr.getPointer(),
1186 SharedAddresses[N].first.getAddress().getType());
1187 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001188 return castToBase(CGF, OrigVD->getType(),
1189 SharedAddresses[N].first.getType(),
Jonas Hahnfeld273d2612017-12-06 19:15:28 +00001190 OriginalBaseLValue.getAddress().getType(),
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001191 OriginalBaseLValue.getAlignment(), Ptr);
1192 }
1193 BaseDecls.emplace_back(
1194 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl()));
1195 return PrivateAddr;
1196}
1197
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001198bool ReductionCodeGen::usesReductionInitializer(unsigned N) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001199 const OMPDeclareReductionDecl *DRD =
1200 getReductionInit(ClausesData[N].ReductionOp);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001201 return DRD && DRD->getInitializer();
1202}
1203
Alexey Bataev18095712014-10-10 12:19:54 +00001204LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
Alexey Bataev31300ed2016-02-04 11:27:03 +00001205 return CGF.EmitLoadOfPointerLValue(
1206 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
1207 getThreadIDVariable()->getType()->castAs<PointerType>());
Alexey Bataev18095712014-10-10 12:19:54 +00001208}
1209
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001210void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001211 if (!CGF.HaveInsertPoint())
1212 return;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001213 // 1.2.2 OpenMP Language Terminology
1214 // Structured block - An executable statement with a single entry at the
1215 // top and a single exit at the bottom.
1216 // The point of exit cannot be a branch out of the structured block.
1217 // longjmp() and throw() must not violate the entry/exit criteria.
1218 CGF.EHStack.pushTerminate();
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001219 CodeGen(CGF);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001220 CGF.EHStack.popTerminate();
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001221}
1222
Alexey Bataev62b63b12015-03-10 07:28:44 +00001223LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1224 CodeGenFunction &CGF) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00001225 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()),
1226 getThreadIDVariable()->getType(),
Ivan A. Kosarev5f8c0ca2017-10-10 09:39:32 +00001227 AlignmentSource::Decl);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001228}
1229
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001230static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
1231 QualType FieldTy) {
1232 auto *Field = FieldDecl::Create(
1233 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
1234 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
1235 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
1236 Field->setAccess(AS_public);
1237 DC->addDecl(Field);
1238 return Field;
1239}
1240
Alexey Bataev18fa2322018-05-02 14:20:50 +00001241CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator,
1242 StringRef Separator)
1243 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator),
1244 OffloadEntriesInfoManager(CGM) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001245 ASTContext &C = CGM.getContext();
1246 RecordDecl *RD = C.buildImplicitRecord("ident_t");
1247 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
1248 RD->startDefinition();
1249 // reserved_1
1250 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1251 // flags
1252 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1253 // reserved_2
1254 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1255 // reserved_3
1256 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1257 // psource
1258 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
1259 RD->completeDefinition();
1260 IdentQTy = C.getRecordType(RD);
1261 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001262 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
Samuel Antaoee8fb302016-01-06 13:42:12 +00001263
1264 loadOffloadInfoMetadata();
Alexey Bataev9959db52014-05-06 10:08:46 +00001265}
1266
Alexey Bataev2df5f122019-10-01 20:18:32 +00001267static bool tryEmitAlias(CodeGenModule &CGM, const GlobalDecl &NewGD,
1268 const GlobalDecl &OldGD, llvm::GlobalValue *OrigAddr,
1269 bool IsForDefinition) {
1270 // Emit at least a definition for the aliasee if the the address of the
1271 // original function is requested.
1272 if (IsForDefinition || OrigAddr)
1273 (void)CGM.GetAddrOfGlobal(NewGD);
1274 StringRef NewMangledName = CGM.getMangledName(NewGD);
1275 llvm::GlobalValue *Addr = CGM.GetGlobalValue(NewMangledName);
1276 if (Addr && !Addr->isDeclaration()) {
1277 const auto *D = cast<FunctionDecl>(OldGD.getDecl());
1278 const CGFunctionInfo &FI = CGM.getTypes().arrangeGlobalDeclaration(OldGD);
1279 llvm::Type *DeclTy = CGM.getTypes().GetFunctionType(FI);
1280
1281 // Create a reference to the named value. This ensures that it is emitted
1282 // if a deferred decl.
1283 llvm::GlobalValue::LinkageTypes LT = CGM.getFunctionLinkage(OldGD);
1284
1285 // Create the new alias itself, but don't set a name yet.
1286 auto *GA =
1287 llvm::GlobalAlias::create(DeclTy, 0, LT, "", Addr, &CGM.getModule());
1288
1289 if (OrigAddr) {
1290 assert(OrigAddr->isDeclaration() && "Expected declaration");
1291
1292 GA->takeName(OrigAddr);
1293 OrigAddr->replaceAllUsesWith(
1294 llvm::ConstantExpr::getBitCast(GA, OrigAddr->getType()));
1295 OrigAddr->eraseFromParent();
1296 } else {
1297 GA->setName(CGM.getMangledName(OldGD));
1298 }
1299
1300 // Set attributes which are particular to an alias; this is a
1301 // specialization of the attributes which may be set on a global function.
1302 if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakRefAttr>() ||
1303 D->isWeakImported())
1304 GA->setLinkage(llvm::Function::WeakAnyLinkage);
1305
1306 CGM.SetCommonAttributes(OldGD, GA);
1307 return true;
1308 }
1309 return false;
1310}
1311
Alexey Bataev91797552015-03-18 04:13:55 +00001312void CGOpenMPRuntime::clear() {
1313 InternalVars.clear();
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00001314 // Clean non-target variable declarations possibly used only in debug info.
1315 for (const auto &Data : EmittedNonTargetVariables) {
1316 if (!Data.getValue().pointsToAliveValue())
1317 continue;
1318 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue());
1319 if (!GV)
1320 continue;
1321 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1322 continue;
1323 GV->eraseFromParent();
1324 }
Alexey Bataev2df5f122019-10-01 20:18:32 +00001325 // Emit aliases for the deferred aliasees.
1326 for (const auto &Pair : DeferredVariantFunction) {
1327 StringRef MangledName = CGM.getMangledName(Pair.second.second);
1328 llvm::GlobalValue *Addr = CGM.GetGlobalValue(MangledName);
1329 // If not able to emit alias, just emit original declaration.
1330 (void)tryEmitAlias(CGM, Pair.second.first, Pair.second.second, Addr,
1331 /*IsForDefinition=*/false);
1332 }
Alexey Bataev91797552015-03-18 04:13:55 +00001333}
1334
Alexey Bataev18fa2322018-05-02 14:20:50 +00001335std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const {
1336 SmallString<128> Buffer;
1337 llvm::raw_svector_ostream OS(Buffer);
1338 StringRef Sep = FirstSeparator;
1339 for (StringRef Part : Parts) {
1340 OS << Sep << Part;
1341 Sep = Separator;
1342 }
1343 return OS.str();
1344}
1345
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001346static llvm::Function *
1347emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
1348 const Expr *CombinerInitializer, const VarDecl *In,
1349 const VarDecl *Out, bool IsCombiner) {
1350 // void .omp_combiner.(Ty *in, Ty *out);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001351 ASTContext &C = CGM.getContext();
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001352 QualType PtrTy = C.getPointerType(Ty).withRestrict();
1353 FunctionArgList Args;
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001354 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(),
Alexey Bataev56223232017-06-09 13:40:18 +00001355 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001356 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(),
Alexey Bataev56223232017-06-09 13:40:18 +00001357 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001358 Args.push_back(&OmpOutParm);
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001359 Args.push_back(&OmpInParm);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001360 const CGFunctionInfo &FnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00001361 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001362 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00001363 std::string Name = CGM.getOpenMPRuntime().getName(
1364 {IsCombiner ? "omp_combiner" : "omp_initializer", ""});
1365 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1366 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00001367 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataev8c5555c2019-05-21 15:11:58 +00001368 if (CGM.getLangOpts().Optimize) {
1369 Fn->removeFnAttr(llvm::Attribute::NoInline);
1370 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
1371 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
1372 }
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001373 CodeGenFunction CGF(CGM);
1374 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
1375 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions.
Alexey Bataev7cae94e2018-01-04 19:45:16 +00001376 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(),
1377 Out->getLocation());
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001378 CodeGenFunction::OMPPrivateScope Scope(CGF);
1379 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001380 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() {
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001381 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>())
1382 .getAddress();
1383 });
1384 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001385 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() {
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001386 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>())
1387 .getAddress();
1388 });
1389 (void)Scope.Privatize();
Alexey Bataev070f43a2017-09-06 14:49:58 +00001390 if (!IsCombiner && Out->hasInit() &&
1391 !CGF.isTrivialInitializer(Out->getInit())) {
1392 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out),
1393 Out->getType().getQualifiers(),
1394 /*IsInitializer=*/true);
1395 }
1396 if (CombinerInitializer)
1397 CGF.EmitIgnoredExpr(CombinerInitializer);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001398 Scope.ForceCleanup();
1399 CGF.FinishFunction();
1400 return Fn;
1401}
1402
1403void CGOpenMPRuntime::emitUserDefinedReduction(
1404 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) {
1405 if (UDRMap.count(D) > 0)
1406 return;
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001407 llvm::Function *Combiner = emitCombinerOrInitializer(
Alexey Bataeve6aa4692018-09-13 16:54:05 +00001408 CGM, D->getType(), D->getCombiner(),
1409 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()),
1410 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()),
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001411 /*IsCombiner=*/true);
1412 llvm::Function *Initializer = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001413 if (const Expr *Init = D->getInitializer()) {
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001414 Initializer = emitCombinerOrInitializer(
Alexey Bataev070f43a2017-09-06 14:49:58 +00001415 CGM, D->getType(),
1416 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init
1417 : nullptr,
Alexey Bataeve6aa4692018-09-13 16:54:05 +00001418 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()),
1419 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()),
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001420 /*IsCombiner=*/false);
1421 }
Alexey Bataev43a919f2018-04-13 17:48:43 +00001422 UDRMap.try_emplace(D, Combiner, Initializer);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001423 if (CGF) {
1424 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn);
1425 Decls.second.push_back(D);
1426 }
1427}
1428
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001429std::pair<llvm::Function *, llvm::Function *>
1430CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) {
1431 auto I = UDRMap.find(D);
1432 if (I != UDRMap.end())
1433 return I->second;
1434 emitUserDefinedReduction(/*CGF=*/nullptr, D);
1435 return UDRMap.lookup(D);
1436}
1437
James Y Knight9871db02019-02-05 16:42:33 +00001438static llvm::Function *emitParallelOrTeamsOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001439 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS,
1440 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind,
1441 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00001442 assert(ThreadIDVar->getType()->isPointerType() &&
1443 "thread id variable must be of type kmp_int32 *");
Alexey Bataev18095712014-10-10 12:19:54 +00001444 CodeGenFunction CGF(CGM, true);
Alexey Bataev25e5b442015-09-15 12:52:43 +00001445 bool HasCancel = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001446 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001447 HasCancel = OPD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001448 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001449 HasCancel = OPSD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001450 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001451 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001452 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
Alexey Bataev2139ed62017-11-16 18:20:21 +00001453 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001454 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
Alexey Bataev10a54312017-11-27 16:54:08 +00001455 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001456 else if (const auto *OPFD =
1457 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
Alexey Bataev10a54312017-11-27 16:54:08 +00001458 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001459 else if (const auto *OPFD =
Alexey Bataev10a54312017-11-27 16:54:08 +00001460 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1461 HasCancel = OPFD->hasCancel();
Alexey Bataev25e5b442015-09-15 12:52:43 +00001462 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001463 HasCancel, OutlinedHelperName);
Alexey Bataevd157d472015-06-24 03:35:38 +00001464 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev2377fe92015-09-10 08:12:02 +00001465 return CGF.GenerateOpenMPCapturedStmtFunction(*CS);
Alexey Bataev18095712014-10-10 12:19:54 +00001466}
1467
James Y Knight9871db02019-02-05 16:42:33 +00001468llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001469 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1470 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1471 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1472 return emitParallelOrTeamsOutlinedFunction(
1473 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1474}
1475
James Y Knight9871db02019-02-05 16:42:33 +00001476llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001477 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1478 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1479 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1480 return emitParallelOrTeamsOutlinedFunction(
1481 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1482}
1483
James Y Knight9871db02019-02-05 16:42:33 +00001484llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001485 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
Alexey Bataev48591dd2016-04-20 04:01:36 +00001486 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
1487 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
1488 bool Tied, unsigned &NumberOfParts) {
1489 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF,
1490 PrePostActionTy &) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00001491 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc());
1492 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc());
Alexey Bataev48591dd2016-04-20 04:01:36 +00001493 llvm::Value *TaskArgs[] = {
1494 UpLoc, ThreadID,
1495 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1496 TaskTVar->getType()->castAs<PointerType>())
1497 .getPointer()};
1498 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs);
1499 };
1500 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1501 UntiedCodeGen);
1502 CodeGen.setAction(Action);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001503 assert(!ThreadIDVar->getType()->isPointerType() &&
1504 "thread id variable must be of type kmp_int32 for tasks");
Alexey Bataev475a7442018-01-12 19:39:11 +00001505 const OpenMPDirectiveKind Region =
1506 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop
1507 : OMPD_task;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001508 const CapturedStmt *CS = D.getCapturedStmt(Region);
1509 const auto *TD = dyn_cast<OMPTaskDirective>(&D);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001510 CodeGenFunction CGF(CGM, true);
Alexey Bataev7292c292016-04-25 12:22:29 +00001511 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
1512 InnermostKind,
1513 TD ? TD->hasCancel() : false, Action);
Alexey Bataevd157d472015-06-24 03:35:38 +00001514 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
James Y Knight9871db02019-02-05 16:42:33 +00001515 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
Alexey Bataev48591dd2016-04-20 04:01:36 +00001516 if (!Tied)
1517 NumberOfParts = Action.getNumberOfParts();
1518 return Res;
Alexey Bataev62b63b12015-03-10 07:28:44 +00001519}
1520
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001521static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM,
1522 const RecordDecl *RD, const CGRecordLayout &RL,
1523 ArrayRef<llvm::Constant *> Data) {
1524 llvm::StructType *StructTy = RL.getLLVMType();
1525 unsigned PrevIdx = 0;
1526 ConstantInitBuilder CIBuilder(CGM);
1527 auto DI = Data.begin();
1528 for (const FieldDecl *FD : RD->fields()) {
1529 unsigned Idx = RL.getLLVMFieldNo(FD);
1530 // Fill the alignment.
1531 for (unsigned I = PrevIdx; I < Idx; ++I)
1532 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I)));
1533 PrevIdx = Idx + 1;
1534 Fields.add(*DI);
1535 ++DI;
1536 }
1537}
1538
1539template <class... As>
1540static llvm::GlobalVariable *
Mike Ricee1ca7b62018-08-29 15:45:11 +00001541createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant,
1542 ArrayRef<llvm::Constant *> Data, const Twine &Name,
1543 As &&... Args) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001544 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1545 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1546 ConstantInitBuilder CIBuilder(CGM);
1547 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType());
1548 buildStructValue(Fields, CGM, RD, RL, Data);
1549 return Fields.finishAndCreateGlobal(
Mike Ricee1ca7b62018-08-29 15:45:11 +00001550 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant,
1551 std::forward<As>(Args)...);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001552}
1553
1554template <typename T>
Benjamin Kramer651d0bf2018-05-15 21:26:47 +00001555static void
1556createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty,
1557 ArrayRef<llvm::Constant *> Data,
1558 T &Parent) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001559 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1560 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1561 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType());
1562 buildStructValue(Fields, CGM, RD, RL, Data);
1563 Fields.finishAndAddTo(Parent);
1564}
1565
Alexey Bataev50b3c952016-02-19 10:38:26 +00001566Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001567 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy);
Alexey Bataevceeaa482018-11-21 21:04:34 +00001568 unsigned Reserved2Flags = getDefaultLocationReserved2Flags();
1569 FlagsTy FlagsKey(Flags, Reserved2Flags);
1570 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey);
Alexey Bataev9959db52014-05-06 10:08:46 +00001571 if (!Entry) {
1572 if (!DefaultOpenMPPSource) {
1573 // Initialize default location for psource field of ident_t structure of
1574 // all ident_t objects. Format is ";file;function;line;column;;".
1575 // Taken from
James Y Knight5d71fc52019-01-29 16:37:27 +00001576 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp
Alexey Bataev9959db52014-05-06 10:08:46 +00001577 DefaultOpenMPPSource =
John McCall7f416cc2015-09-08 08:05:57 +00001578 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001579 DefaultOpenMPPSource =
1580 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
1581 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001582
Alexey Bataevceeaa482018-11-21 21:04:34 +00001583 llvm::Constant *Data[] = {
1584 llvm::ConstantInt::getNullValue(CGM.Int32Ty),
1585 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
1586 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags),
1587 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource};
Mike Ricee1ca7b62018-08-29 15:45:11 +00001588 llvm::GlobalValue *DefaultOpenMPLocation =
Alexey Bataevceeaa482018-11-21 21:04:34 +00001589 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "",
Mike Ricee1ca7b62018-08-29 15:45:11 +00001590 llvm::GlobalValue::PrivateLinkage);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001591 DefaultOpenMPLocation->setUnnamedAddr(
1592 llvm::GlobalValue::UnnamedAddr::Global);
John McCall6c9f1fdb2016-11-19 08:17:24 +00001593
Alexey Bataevceeaa482018-11-21 21:04:34 +00001594 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation;
Alexey Bataev9959db52014-05-06 10:08:46 +00001595 }
John McCall7f416cc2015-09-08 08:05:57 +00001596 return Address(Entry, Align);
Alexey Bataev9959db52014-05-06 10:08:46 +00001597}
1598
Alexey Bataevfd006c42018-10-05 15:08:53 +00001599void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF,
1600 bool AtCurrentPoint) {
1601 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1602 assert(!Elem.second.ServiceInsertPt && "Insert point is set already.");
1603
1604 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty);
1605 if (AtCurrentPoint) {
1606 Elem.second.ServiceInsertPt = new llvm::BitCastInst(
1607 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock());
1608 } else {
1609 Elem.second.ServiceInsertPt =
1610 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt");
1611 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt);
1612 }
1613}
1614
1615void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) {
1616 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1617 if (Elem.second.ServiceInsertPt) {
1618 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt;
1619 Elem.second.ServiceInsertPt = nullptr;
1620 Ptr->eraseFromParent();
1621 }
1622}
1623
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001624llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
1625 SourceLocation Loc,
Alexey Bataev50b3c952016-02-19 10:38:26 +00001626 unsigned Flags) {
1627 Flags |= OMP_IDENT_KMPC;
Alexey Bataev9959db52014-05-06 10:08:46 +00001628 // If no debug info is generated - return global default location.
Benjamin Kramer8c305922016-02-02 11:06:51 +00001629 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo ||
Alexey Bataev9959db52014-05-06 10:08:46 +00001630 Loc.isInvalid())
John McCall7f416cc2015-09-08 08:05:57 +00001631 return getOrCreateDefaultLocation(Flags).getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001632
1633 assert(CGF.CurFn && "No function in current CodeGenFunction.");
1634
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001635 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy);
John McCall7f416cc2015-09-08 08:05:57 +00001636 Address LocValue = Address::invalid();
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001637 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
1638 if (I != OpenMPLocThreadIDMap.end())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001639 LocValue = Address(I->second.DebugLoc, Align);
John McCall7f416cc2015-09-08 08:05:57 +00001640
Alexander Musmanc6388682014-12-15 07:07:06 +00001641 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
1642 // GetOpenMPThreadID was called before this routine.
John McCall7f416cc2015-09-08 08:05:57 +00001643 if (!LocValue.isValid()) {
Alexey Bataev15007ba2014-05-07 06:18:01 +00001644 // Generate "ident_t .kmpc_loc.addr;"
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001645 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr");
Alexey Bataev18095712014-10-10 12:19:54 +00001646 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
John McCall7f416cc2015-09-08 08:05:57 +00001647 Elem.second.DebugLoc = AI.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001648 LocValue = AI;
1649
Alexey Bataevfd006c42018-10-05 15:08:53 +00001650 if (!Elem.second.ServiceInsertPt)
1651 setLocThreadIdInsertPt(CGF);
Alexey Bataev9959db52014-05-06 10:08:46 +00001652 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001653 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001654 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001655 CGF.getTypeSize(IdentQTy));
Alexey Bataev9959db52014-05-06 10:08:46 +00001656 }
1657
1658 // char **psource = &.kmpc_loc_<flags>.addr.psource;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001659 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy);
1660 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin();
1661 LValue PSource =
1662 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource));
Alexey Bataev9959db52014-05-06 10:08:46 +00001663
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001664 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
Alexey Bataevf002aca2014-05-30 05:48:40 +00001665 if (OMPDebugLoc == nullptr) {
1666 SmallString<128> Buffer2;
1667 llvm::raw_svector_ostream OS2(Buffer2);
1668 // Build debug location
1669 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
1670 OS2 << ";" << PLoc.getFilename() << ";";
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001671 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl))
Alexey Bataevf002aca2014-05-30 05:48:40 +00001672 OS2 << FD->getQualifiedNameAsString();
Alexey Bataevf002aca2014-05-30 05:48:40 +00001673 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
1674 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
1675 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
Alexey Bataev9959db52014-05-06 10:08:46 +00001676 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001677 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001678 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource);
Alexey Bataevf002aca2014-05-30 05:48:40 +00001679
John McCall7f416cc2015-09-08 08:05:57 +00001680 // Our callers always pass this to a runtime function, so for
1681 // convenience, go ahead and return a naked pointer.
1682 return LocValue.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001683}
1684
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001685llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
1686 SourceLocation Loc) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001687 assert(CGF.CurFn && "No function in current CodeGenFunction.");
1688
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001689 llvm::Value *ThreadID = nullptr;
Alexey Bataev18095712014-10-10 12:19:54 +00001690 // Check whether we've already cached a load of the thread id in this
1691 // function.
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001692 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
Alexey Bataev18095712014-10-10 12:19:54 +00001693 if (I != OpenMPLocThreadIDMap.end()) {
1694 ThreadID = I->second.ThreadID;
Alexey Bataev03b340a2014-10-21 03:16:40 +00001695 if (ThreadID != nullptr)
1696 return ThreadID;
1697 }
Alexey Bataevaee18552017-08-16 14:01:00 +00001698 // If exceptions are enabled, do not use parameter to avoid possible crash.
Alexey Bataev5d2c9a42017-11-02 18:55:05 +00001699 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions ||
1700 !CGF.getLangOpts().CXXExceptions ||
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001701 CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
Alexey Bataevaee18552017-08-16 14:01:00 +00001702 if (auto *OMPRegionInfo =
1703 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
1704 if (OMPRegionInfo->getThreadIDVariable()) {
1705 // Check if this an outlined function with thread id passed as argument.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001706 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
Alexey Bataev1e491372018-01-23 18:44:14 +00001707 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc);
Alexey Bataevaee18552017-08-16 14:01:00 +00001708 // If value loaded in entry block, cache it and use it everywhere in
1709 // function.
1710 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
1711 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1712 Elem.second.ThreadID = ThreadID;
1713 }
1714 return ThreadID;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001715 }
Alexey Bataevd6c57552014-07-25 07:55:17 +00001716 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001717 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001718
1719 // This is not an outlined function region - need to call __kmpc_int32
1720 // kmpc_global_thread_num(ident_t *loc).
1721 // Generate thread id value and cache this value for use across the
1722 // function.
Alexey Bataevfd006c42018-10-05 15:08:53 +00001723 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1724 if (!Elem.second.ServiceInsertPt)
1725 setLocThreadIdInsertPt(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001726 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001727 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001728 llvm::CallInst *Call = CGF.Builder.CreateCall(
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001729 createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
1730 emitUpdateLocation(CGF, Loc));
1731 Call->setCallingConv(CGF.getRuntimeCC());
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001732 Elem.second.ThreadID = Call;
1733 return Call;
Alexey Bataev9959db52014-05-06 10:08:46 +00001734}
1735
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001736void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001737 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataevfd006c42018-10-05 15:08:53 +00001738 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) {
1739 clearLocThreadIdInsertPt(CGF);
Alexey Bataev03b340a2014-10-21 03:16:40 +00001740 OpenMPLocThreadIDMap.erase(CGF.CurFn);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001741 }
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001742 if (FunctionUDRMap.count(CGF.CurFn) > 0) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001743 for(auto *D : FunctionUDRMap[CGF.CurFn])
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001744 UDRMap.erase(D);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001745 FunctionUDRMap.erase(CGF.CurFn);
1746 }
Michael Krused47b9432019-08-05 18:43:21 +00001747 auto I = FunctionUDMMap.find(CGF.CurFn);
1748 if (I != FunctionUDMMap.end()) {
1749 for(auto *D : I->second)
1750 UDMMap.erase(D);
1751 FunctionUDMMap.erase(I);
1752 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001753}
1754
1755llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001756 return IdentTy->getPointerTo();
Alexey Bataev9959db52014-05-06 10:08:46 +00001757}
1758
1759llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001760 if (!Kmpc_MicroTy) {
1761 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
1762 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
1763 llvm::PointerType::getUnqual(CGM.Int32Ty)};
1764 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
1765 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001766 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
1767}
1768
James Y Knight9871db02019-02-05 16:42:33 +00001769llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
1770 llvm::FunctionCallee RTLFn = nullptr;
Alexey Bataev50b3c952016-02-19 10:38:26 +00001771 switch (static_cast<OpenMPRTLFunction>(Function)) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001772 case OMPRTL__kmpc_fork_call: {
1773 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
1774 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +00001775 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1776 getKmpc_MicroPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001777 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001778 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
Alexey Bataev9959db52014-05-06 10:08:46 +00001779 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
James Y Knight9871db02019-02-05 16:42:33 +00001780 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) {
Johannes Doerfertac991bb2019-01-19 05:36:54 +00001781 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
1782 llvm::LLVMContext &Ctx = F->getContext();
1783 llvm::MDBuilder MDB(Ctx);
1784 // Annotate the callback behavior of the __kmpc_fork_call:
1785 // - The callback callee is argument number 2 (microtask).
1786 // - The first two arguments of the callback callee are unknown (-1).
1787 // - All variadic arguments to the __kmpc_fork_call are passed to the
1788 // callback callee.
1789 F->addMetadata(
1790 llvm::LLVMContext::MD_callback,
1791 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
1792 2, {-1, -1},
1793 /* VarArgsArePassed */ true)}));
1794 }
1795 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001796 break;
1797 }
1798 case OMPRTL__kmpc_global_thread_num: {
1799 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +00001800 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001801 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001802 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
Alexey Bataev9959db52014-05-06 10:08:46 +00001803 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
1804 break;
1805 }
Alexey Bataev97720002014-11-11 04:05:39 +00001806 case OMPRTL__kmpc_threadprivate_cached: {
1807 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
1808 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
1809 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1810 CGM.VoidPtrTy, CGM.SizeTy,
1811 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001812 auto *FnTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001813 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
1814 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
1815 break;
1816 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001817 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001818 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
1819 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001820 llvm::Type *TypeParams[] = {
1821 getIdentTyPointerTy(), CGM.Int32Ty,
1822 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001823 auto *FnTy =
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001824 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1825 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
1826 break;
1827 }
Alexey Bataevfc57d162015-12-15 10:55:09 +00001828 case OMPRTL__kmpc_critical_with_hint: {
1829 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid,
1830 // kmp_critical_name *crit, uintptr_t hint);
1831 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1832 llvm::PointerType::getUnqual(KmpCriticalNameTy),
1833 CGM.IntPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001834 auto *FnTy =
Alexey Bataevfc57d162015-12-15 10:55:09 +00001835 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1836 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint");
1837 break;
1838 }
Alexey Bataev97720002014-11-11 04:05:39 +00001839 case OMPRTL__kmpc_threadprivate_register: {
1840 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
1841 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
1842 // typedef void *(*kmpc_ctor)(void *);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001843 auto *KmpcCtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001844 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1845 /*isVarArg*/ false)->getPointerTo();
1846 // typedef void *(*kmpc_cctor)(void *, void *);
1847 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001848 auto *KmpcCopyCtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001849 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001850 /*isVarArg*/ false)
1851 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00001852 // typedef void (*kmpc_dtor)(void *);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001853 auto *KmpcDtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001854 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
1855 ->getPointerTo();
1856 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
1857 KmpcCopyCtorTy, KmpcDtorTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001858 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
Alexey Bataev97720002014-11-11 04:05:39 +00001859 /*isVarArg*/ false);
1860 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
1861 break;
1862 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001863 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001864 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
1865 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001866 llvm::Type *TypeParams[] = {
1867 getIdentTyPointerTy(), CGM.Int32Ty,
1868 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001869 auto *FnTy =
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001870 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1871 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
1872 break;
1873 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001874 case OMPRTL__kmpc_cancel_barrier: {
1875 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
1876 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001877 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001878 auto *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001879 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1880 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001881 break;
1882 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001883 case OMPRTL__kmpc_barrier: {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001884 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001885 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001886 auto *FnTy =
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001887 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1888 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
1889 break;
1890 }
Alexander Musmanc6388682014-12-15 07:07:06 +00001891 case OMPRTL__kmpc_for_static_fini: {
1892 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
1893 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001894 auto *FnTy =
Alexander Musmanc6388682014-12-15 07:07:06 +00001895 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1896 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
1897 break;
1898 }
Alexey Bataevb2059782014-10-13 08:23:51 +00001899 case OMPRTL__kmpc_push_num_threads: {
1900 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
1901 // kmp_int32 num_threads)
1902 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1903 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001904 auto *FnTy =
Alexey Bataevb2059782014-10-13 08:23:51 +00001905 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1906 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
1907 break;
1908 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001909 case OMPRTL__kmpc_serialized_parallel: {
1910 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
1911 // global_tid);
1912 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001913 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001914 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1915 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
1916 break;
1917 }
1918 case OMPRTL__kmpc_end_serialized_parallel: {
1919 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
1920 // global_tid);
1921 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001922 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001923 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1924 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
1925 break;
1926 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001927 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001928 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001929 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001930 auto *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001931 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001932 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
1933 break;
1934 }
Alexey Bataev8d690652014-12-04 07:23:53 +00001935 case OMPRTL__kmpc_master: {
1936 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
1937 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001938 auto *FnTy =
Alexey Bataev8d690652014-12-04 07:23:53 +00001939 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1940 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
1941 break;
1942 }
1943 case OMPRTL__kmpc_end_master: {
1944 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
1945 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001946 auto *FnTy =
Alexey Bataev8d690652014-12-04 07:23:53 +00001947 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1948 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
1949 break;
1950 }
Alexey Bataev9f797f32015-02-05 05:57:51 +00001951 case OMPRTL__kmpc_omp_taskyield: {
1952 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
1953 // int end_part);
1954 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001955 auto *FnTy =
Alexey Bataev9f797f32015-02-05 05:57:51 +00001956 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1957 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
1958 break;
1959 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001960 case OMPRTL__kmpc_single: {
1961 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
1962 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001963 auto *FnTy =
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001964 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1965 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
1966 break;
1967 }
1968 case OMPRTL__kmpc_end_single: {
1969 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
1970 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001971 auto *FnTy =
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001972 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1973 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
1974 break;
1975 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00001976 case OMPRTL__kmpc_omp_task_alloc: {
1977 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
1978 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
1979 // kmp_routine_entry_t *task_entry);
1980 assert(KmpRoutineEntryPtrTy != nullptr &&
1981 "Type kmp_routine_entry_t must be created.");
1982 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1983 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
1984 // Return void * and then cast to particular kmp_task_t type.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001985 auto *FnTy =
Alexey Bataev62b63b12015-03-10 07:28:44 +00001986 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
1987 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
1988 break;
1989 }
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00001990 case OMPRTL__kmpc_omp_target_task_alloc: {
1991 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid,
1992 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
1993 // kmp_routine_entry_t *task_entry, kmp_int64 device_id);
1994 assert(KmpRoutineEntryPtrTy != nullptr &&
1995 "Type kmp_routine_entry_t must be created.");
1996 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1997 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy,
1998 CGM.Int64Ty};
1999 // Return void * and then cast to particular kmp_task_t type.
2000 auto *FnTy =
2001 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2002 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc");
2003 break;
2004 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00002005 case OMPRTL__kmpc_omp_task: {
2006 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2007 // *new_task);
2008 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2009 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002010 auto *FnTy =
Alexey Bataev62b63b12015-03-10 07:28:44 +00002011 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2012 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
2013 break;
2014 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00002015 case OMPRTL__kmpc_copyprivate: {
2016 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
Alexey Bataev66beaa92015-04-30 03:47:32 +00002017 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
Alexey Bataeva63048e2015-03-23 06:18:07 +00002018 // kmp_int32 didit);
2019 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2020 auto *CpyFnTy =
2021 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
Alexey Bataev66beaa92015-04-30 03:47:32 +00002022 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
Alexey Bataeva63048e2015-03-23 06:18:07 +00002023 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
2024 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002025 auto *FnTy =
Alexey Bataeva63048e2015-03-23 06:18:07 +00002026 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2027 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
2028 break;
2029 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002030 case OMPRTL__kmpc_reduce: {
2031 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
2032 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
2033 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
2034 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2035 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
2036 /*isVarArg=*/false);
2037 llvm::Type *TypeParams[] = {
2038 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
2039 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
2040 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002041 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002042 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2043 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
2044 break;
2045 }
2046 case OMPRTL__kmpc_reduce_nowait: {
2047 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
2048 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
2049 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
2050 // *lck);
2051 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
2052 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
2053 /*isVarArg=*/false);
2054 llvm::Type *TypeParams[] = {
2055 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
2056 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
2057 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002058 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002059 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2060 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
2061 break;
2062 }
2063 case OMPRTL__kmpc_end_reduce: {
2064 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
2065 // kmp_critical_name *lck);
2066 llvm::Type *TypeParams[] = {
2067 getIdentTyPointerTy(), CGM.Int32Ty,
2068 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002069 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002070 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2071 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
2072 break;
2073 }
2074 case OMPRTL__kmpc_end_reduce_nowait: {
2075 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
2076 // kmp_critical_name *lck);
2077 llvm::Type *TypeParams[] = {
2078 getIdentTyPointerTy(), CGM.Int32Ty,
2079 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002080 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00002081 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2082 RTLFn =
2083 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
2084 break;
2085 }
Alexey Bataev1d677132015-04-22 13:57:31 +00002086 case OMPRTL__kmpc_omp_task_begin_if0: {
2087 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2088 // *new_task);
2089 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2090 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002091 auto *FnTy =
Alexey Bataev1d677132015-04-22 13:57:31 +00002092 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2093 RTLFn =
2094 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
2095 break;
2096 }
2097 case OMPRTL__kmpc_omp_task_complete_if0: {
2098 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
2099 // *new_task);
2100 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2101 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002102 auto *FnTy =
Alexey Bataev1d677132015-04-22 13:57:31 +00002103 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2104 RTLFn = CGM.CreateRuntimeFunction(FnTy,
2105 /*Name=*/"__kmpc_omp_task_complete_if0");
2106 break;
2107 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002108 case OMPRTL__kmpc_ordered: {
2109 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
2110 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002111 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002112 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2113 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
2114 break;
2115 }
2116 case OMPRTL__kmpc_end_ordered: {
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002117 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002118 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002119 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002120 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2121 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
2122 break;
2123 }
Alexey Bataev8b8e2022015-04-27 05:22:09 +00002124 case OMPRTL__kmpc_omp_taskwait: {
2125 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
2126 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002127 auto *FnTy =
Alexey Bataev8b8e2022015-04-27 05:22:09 +00002128 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2129 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
2130 break;
2131 }
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002132 case OMPRTL__kmpc_taskgroup: {
2133 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
2134 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002135 auto *FnTy =
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002136 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2137 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
2138 break;
2139 }
2140 case OMPRTL__kmpc_end_taskgroup: {
2141 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
2142 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002143 auto *FnTy =
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002144 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2145 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
2146 break;
2147 }
Alexey Bataev7f210c62015-06-18 13:40:03 +00002148 case OMPRTL__kmpc_push_proc_bind: {
2149 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
2150 // int proc_bind)
2151 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002152 auto *FnTy =
Alexey Bataev7f210c62015-06-18 13:40:03 +00002153 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2154 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
2155 break;
2156 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002157 case OMPRTL__kmpc_omp_task_with_deps: {
2158 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
2159 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
2160 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
2161 llvm::Type *TypeParams[] = {
2162 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
2163 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002164 auto *FnTy =
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002165 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2166 RTLFn =
2167 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
2168 break;
2169 }
2170 case OMPRTL__kmpc_omp_wait_deps: {
2171 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
2172 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
2173 // kmp_depend_info_t *noalias_dep_list);
2174 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2175 CGM.Int32Ty, CGM.VoidPtrTy,
2176 CGM.Int32Ty, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002177 auto *FnTy =
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002178 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2179 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
2180 break;
2181 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00002182 case OMPRTL__kmpc_cancellationpoint: {
2183 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
2184 // global_tid, kmp_int32 cncl_kind)
2185 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002186 auto *FnTy =
Alexey Bataev0f34da12015-07-02 04:17:07 +00002187 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2188 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
2189 break;
2190 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002191 case OMPRTL__kmpc_cancel: {
2192 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
2193 // kmp_int32 cncl_kind)
2194 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002195 auto *FnTy =
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002196 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2197 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
2198 break;
2199 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002200 case OMPRTL__kmpc_push_num_teams: {
2201 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid,
2202 // kmp_int32 num_teams, kmp_int32 num_threads)
2203 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
2204 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002205 auto *FnTy =
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002206 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2207 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams");
2208 break;
2209 }
2210 case OMPRTL__kmpc_fork_teams: {
2211 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
2212 // microtask, ...);
2213 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2214 getKmpc_MicroPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002215 auto *FnTy =
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002216 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
2217 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams");
James Y Knight9871db02019-02-05 16:42:33 +00002218 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) {
Johannes Doerfertac991bb2019-01-19 05:36:54 +00002219 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
2220 llvm::LLVMContext &Ctx = F->getContext();
2221 llvm::MDBuilder MDB(Ctx);
2222 // Annotate the callback behavior of the __kmpc_fork_teams:
2223 // - The callback callee is argument number 2 (microtask).
2224 // - The first two arguments of the callback callee are unknown (-1).
2225 // - All variadic arguments to the __kmpc_fork_teams are passed to the
2226 // callback callee.
2227 F->addMetadata(
2228 llvm::LLVMContext::MD_callback,
2229 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
2230 2, {-1, -1},
2231 /* VarArgsArePassed */ true)}));
2232 }
2233 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002234 break;
2235 }
Alexey Bataev7292c292016-04-25 12:22:29 +00002236 case OMPRTL__kmpc_taskloop: {
2237 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
2238 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
2239 // sched, kmp_uint64 grainsize, void *task_dup);
2240 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
2241 CGM.IntTy,
2242 CGM.VoidPtrTy,
2243 CGM.IntTy,
2244 CGM.Int64Ty->getPointerTo(),
2245 CGM.Int64Ty->getPointerTo(),
2246 CGM.Int64Ty,
2247 CGM.IntTy,
2248 CGM.IntTy,
2249 CGM.Int64Ty,
2250 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002251 auto *FnTy =
Alexey Bataev7292c292016-04-25 12:22:29 +00002252 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2253 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop");
2254 break;
2255 }
Alexey Bataev8b427062016-05-25 12:36:08 +00002256 case OMPRTL__kmpc_doacross_init: {
2257 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32
2258 // num_dims, struct kmp_dim *dims);
2259 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
2260 CGM.Int32Ty,
2261 CGM.Int32Ty,
2262 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002263 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002264 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2265 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init");
2266 break;
2267 }
2268 case OMPRTL__kmpc_doacross_fini: {
2269 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid);
2270 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002271 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002272 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2273 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini");
2274 break;
2275 }
2276 case OMPRTL__kmpc_doacross_post: {
2277 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64
2278 // *vec);
2279 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2280 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002281 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002282 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2283 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post");
2284 break;
2285 }
2286 case OMPRTL__kmpc_doacross_wait: {
2287 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64
2288 // *vec);
2289 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2290 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002291 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002292 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2293 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait");
2294 break;
2295 }
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002296 case OMPRTL__kmpc_task_reduction_init: {
2297 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void
2298 // *data);
2299 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002300 auto *FnTy =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002301 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2302 RTLFn =
2303 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init");
2304 break;
2305 }
2306 case OMPRTL__kmpc_task_reduction_get_th_data: {
2307 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
2308 // *d);
2309 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002310 auto *FnTy =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002311 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2312 RTLFn = CGM.CreateRuntimeFunction(
2313 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data");
2314 break;
2315 }
Alexey Bataev4f680db2019-03-19 16:41:16 +00002316 case OMPRTL__kmpc_alloc: {
Alexey Bataev6cf7b712019-04-08 19:06:42 +00002317 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t
2318 // al); omp_allocator_handle_t type is void *.
2319 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy};
Alexey Bataev4f680db2019-03-19 16:41:16 +00002320 auto *FnTy =
2321 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2322 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc");
2323 break;
2324 }
2325 case OMPRTL__kmpc_free: {
Alexey Bataev6cf7b712019-04-08 19:06:42 +00002326 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t
2327 // al); omp_allocator_handle_t type is void *.
2328 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataev4f680db2019-03-19 16:41:16 +00002329 auto *FnTy =
2330 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2331 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free");
2332 break;
2333 }
Alexey Bataev7bb33532019-01-07 21:30:43 +00002334 case OMPRTL__kmpc_push_target_tripcount: {
2335 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64
2336 // size);
2337 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty};
2338 llvm::FunctionType *FnTy =
2339 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2340 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount");
2341 break;
2342 }
Samuel Antaobed3c462015-10-02 16:14:20 +00002343 case OMPRTL__tgt_target: {
George Rokos63bc9d62017-11-21 18:25:12 +00002344 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002345 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Samuel Antaobed3c462015-10-02 16:14:20 +00002346 // *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002347 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaobed3c462015-10-02 16:14:20 +00002348 CGM.VoidPtrTy,
2349 CGM.Int32Ty,
2350 CGM.VoidPtrPtrTy,
2351 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002352 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002353 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002354 auto *FnTy =
Samuel Antaobed3c462015-10-02 16:14:20 +00002355 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2356 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
2357 break;
2358 }
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002359 case OMPRTL__tgt_target_nowait: {
2360 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002361 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes,
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002362 // int64_t *arg_types);
2363 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2364 CGM.VoidPtrTy,
2365 CGM.Int32Ty,
2366 CGM.VoidPtrPtrTy,
2367 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002368 CGM.Int64Ty->getPointerTo(),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002369 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002370 auto *FnTy =
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002371 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2372 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait");
2373 break;
2374 }
Samuel Antaob68e2db2016-03-03 16:20:23 +00002375 case OMPRTL__tgt_target_teams: {
George Rokos63bc9d62017-11-21 18:25:12 +00002376 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002377 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes,
George Rokos63bc9d62017-11-21 18:25:12 +00002378 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
2379 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaob68e2db2016-03-03 16:20:23 +00002380 CGM.VoidPtrTy,
2381 CGM.Int32Ty,
2382 CGM.VoidPtrPtrTy,
2383 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002384 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002385 CGM.Int64Ty->getPointerTo(),
Samuel Antaob68e2db2016-03-03 16:20:23 +00002386 CGM.Int32Ty,
2387 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002388 auto *FnTy =
Samuel Antaob68e2db2016-03-03 16:20:23 +00002389 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2390 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams");
2391 break;
2392 }
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002393 case OMPRTL__tgt_target_teams_nowait: {
2394 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void
Alexey Bataeva90fc662019-06-25 16:00:43 +00002395 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002396 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
2397 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2398 CGM.VoidPtrTy,
2399 CGM.Int32Ty,
2400 CGM.VoidPtrPtrTy,
2401 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002402 CGM.Int64Ty->getPointerTo(),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002403 CGM.Int64Ty->getPointerTo(),
2404 CGM.Int32Ty,
2405 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002406 auto *FnTy =
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002407 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2408 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait");
2409 break;
2410 }
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00002411 case OMPRTL__tgt_register_requires: {
2412 // Build void __tgt_register_requires(int64_t flags);
2413 llvm::Type *TypeParams[] = {CGM.Int64Ty};
2414 auto *FnTy =
2415 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2416 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires");
2417 break;
2418 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00002419 case OMPRTL__tgt_register_lib: {
2420 // Build void __tgt_register_lib(__tgt_bin_desc *desc);
2421 QualType ParamTy =
2422 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
2423 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002424 auto *FnTy =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002425 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2426 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib");
2427 break;
2428 }
2429 case OMPRTL__tgt_unregister_lib: {
2430 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc);
2431 QualType ParamTy =
2432 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
2433 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002434 auto *FnTy =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002435 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2436 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib");
2437 break;
2438 }
Samuel Antaodf158d52016-04-27 22:58:19 +00002439 case OMPRTL__tgt_target_data_begin: {
George Rokos63bc9d62017-11-21 18:25:12 +00002440 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002441 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002442 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaodf158d52016-04-27 22:58:19 +00002443 CGM.Int32Ty,
2444 CGM.VoidPtrPtrTy,
2445 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002446 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002447 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002448 auto *FnTy =
Samuel Antaodf158d52016-04-27 22:58:19 +00002449 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2450 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin");
2451 break;
2452 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002453 case OMPRTL__tgt_target_data_begin_nowait: {
2454 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002455 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002456 // *arg_types);
2457 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2458 CGM.Int32Ty,
2459 CGM.VoidPtrPtrTy,
2460 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002461 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002462 CGM.Int64Ty->getPointerTo()};
2463 auto *FnTy =
2464 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2465 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait");
2466 break;
2467 }
Samuel Antaodf158d52016-04-27 22:58:19 +00002468 case OMPRTL__tgt_target_data_end: {
George Rokos63bc9d62017-11-21 18:25:12 +00002469 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002470 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002471 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaodf158d52016-04-27 22:58:19 +00002472 CGM.Int32Ty,
2473 CGM.VoidPtrPtrTy,
2474 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002475 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002476 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002477 auto *FnTy =
Samuel Antaodf158d52016-04-27 22:58:19 +00002478 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2479 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end");
2480 break;
2481 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002482 case OMPRTL__tgt_target_data_end_nowait: {
2483 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002484 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002485 // *arg_types);
2486 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2487 CGM.Int32Ty,
2488 CGM.VoidPtrPtrTy,
2489 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002490 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002491 CGM.Int64Ty->getPointerTo()};
2492 auto *FnTy =
2493 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2494 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait");
2495 break;
2496 }
Samuel Antao8d2d7302016-05-26 18:30:22 +00002497 case OMPRTL__tgt_target_data_update: {
George Rokos63bc9d62017-11-21 18:25:12 +00002498 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002499 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002500 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antao8d2d7302016-05-26 18:30:22 +00002501 CGM.Int32Ty,
2502 CGM.VoidPtrPtrTy,
2503 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002504 CGM.Int64Ty->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002505 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002506 auto *FnTy =
Samuel Antao8d2d7302016-05-26 18:30:22 +00002507 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2508 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update");
2509 break;
2510 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002511 case OMPRTL__tgt_target_data_update_nowait: {
2512 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t
Alexey Bataeva90fc662019-06-25 16:00:43 +00002513 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002514 // *arg_types);
2515 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2516 CGM.Int32Ty,
2517 CGM.VoidPtrPtrTy,
2518 CGM.VoidPtrPtrTy,
Alexey Bataeva90fc662019-06-25 16:00:43 +00002519 CGM.Int64Ty->getPointerTo(),
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002520 CGM.Int64Ty->getPointerTo()};
2521 auto *FnTy =
2522 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2523 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait");
2524 break;
2525 }
Michael Krused47b9432019-08-05 18:43:21 +00002526 case OMPRTL__tgt_mapper_num_components: {
2527 // Build int64_t __tgt_mapper_num_components(void *rt_mapper_handle);
2528 llvm::Type *TypeParams[] = {CGM.VoidPtrTy};
2529 auto *FnTy =
2530 llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false);
2531 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_mapper_num_components");
2532 break;
2533 }
2534 case OMPRTL__tgt_push_mapper_component: {
2535 // Build void __tgt_push_mapper_component(void *rt_mapper_handle, void
2536 // *base, void *begin, int64_t size, int64_t type);
2537 llvm::Type *TypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.VoidPtrTy,
2538 CGM.Int64Ty, CGM.Int64Ty};
2539 auto *FnTy =
2540 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2541 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_push_mapper_component");
2542 break;
2543 }
Alexey Bataev9959db52014-05-06 10:08:46 +00002544 }
Alexey Bataev50b3c952016-02-19 10:38:26 +00002545 assert(RTLFn && "Unable to find OpenMP runtime function");
Alexey Bataev9959db52014-05-06 10:08:46 +00002546 return RTLFn;
2547}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00002548
James Y Knight9871db02019-02-05 16:42:33 +00002549llvm::FunctionCallee
2550CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman21212e42015-03-13 10:38:23 +00002551 assert((IVSize == 32 || IVSize == 64) &&
2552 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002553 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
2554 : "__kmpc_for_static_init_4u")
2555 : (IVSigned ? "__kmpc_for_static_init_8"
2556 : "__kmpc_for_static_init_8u");
2557 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
2558 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
Alexander Musman21212e42015-03-13 10:38:23 +00002559 llvm::Type *TypeParams[] = {
2560 getIdentTyPointerTy(), // loc
2561 CGM.Int32Ty, // tid
2562 CGM.Int32Ty, // schedtype
2563 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
2564 PtrTy, // p_lower
2565 PtrTy, // p_upper
2566 PtrTy, // p_stride
2567 ITy, // incr
2568 ITy // chunk
2569 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002570 auto *FnTy =
Alexander Musman21212e42015-03-13 10:38:23 +00002571 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2572 return CGM.CreateRuntimeFunction(FnTy, Name);
2573}
2574
James Y Knight9871db02019-02-05 16:42:33 +00002575llvm::FunctionCallee
2576CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002577 assert((IVSize == 32 || IVSize == 64) &&
2578 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002579 StringRef Name =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002580 IVSize == 32
2581 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
2582 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002583 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
Alexander Musman92bdaab2015-03-12 13:37:50 +00002584 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
2585 CGM.Int32Ty, // tid
2586 CGM.Int32Ty, // schedtype
2587 ITy, // lower
2588 ITy, // upper
2589 ITy, // stride
2590 ITy // chunk
2591 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002592 auto *FnTy =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002593 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2594 return CGM.CreateRuntimeFunction(FnTy, Name);
2595}
2596
James Y Knight9871db02019-02-05 16:42:33 +00002597llvm::FunctionCallee
2598CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002599 assert((IVSize == 32 || IVSize == 64) &&
2600 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002601 StringRef Name =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002602 IVSize == 32
2603 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
2604 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
2605 llvm::Type *TypeParams[] = {
2606 getIdentTyPointerTy(), // loc
2607 CGM.Int32Ty, // tid
2608 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002609 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002610 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2611 return CGM.CreateRuntimeFunction(FnTy, Name);
2612}
2613
James Y Knight9871db02019-02-05 16:42:33 +00002614llvm::FunctionCallee
2615CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002616 assert((IVSize == 32 || IVSize == 64) &&
2617 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002618 StringRef Name =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002619 IVSize == 32
2620 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
2621 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002622 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
2623 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002624 llvm::Type *TypeParams[] = {
2625 getIdentTyPointerTy(), // loc
2626 CGM.Int32Ty, // tid
2627 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
2628 PtrTy, // p_lower
2629 PtrTy, // p_upper
2630 PtrTy // p_stride
2631 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002632 auto *FnTy =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002633 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2634 return CGM.CreateRuntimeFunction(FnTy, Name);
2635}
2636
Gheorghe-Teodor Bercea625f59d2019-08-01 21:15:58 +00002637/// Obtain information that uniquely identifies a target entry. This
2638/// consists of the file and device IDs as well as line number associated with
2639/// the relevant entry source location.
2640static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
2641 unsigned &DeviceID, unsigned &FileID,
2642 unsigned &LineNum) {
2643 SourceManager &SM = C.getSourceManager();
2644
2645 // The loc should be always valid and have a file ID (the user cannot use
2646 // #pragma directives in macros)
2647
2648 assert(Loc.isValid() && "Source location is expected to be always valid.");
2649
2650 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
2651 assert(PLoc.isValid() && "Source location is expected to be always valid.");
2652
2653 llvm::sys::fs::UniqueID ID;
2654 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
2655 SM.getDiagnostics().Report(diag::err_cannot_open_file)
2656 << PLoc.getFilename() << EC.message();
2657
2658 DeviceID = ID.getDevice();
2659 FileID = ID.getFile();
2660 LineNum = PLoc.getLine();
2661}
2662
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002663Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) {
Alexey Bataev03f270c2018-03-30 18:31:07 +00002664 if (CGM.getLangOpts().OpenMPSimd)
2665 return Address::invalid();
Alexey Bataev92327c52018-03-26 16:40:55 +00002666 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00002667 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002668 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link ||
2669 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
2670 HasRequiresUnifiedSharedMemory))) {
Alexey Bataev92327c52018-03-26 16:40:55 +00002671 SmallString<64> PtrName;
2672 {
2673 llvm::raw_svector_ostream OS(PtrName);
Gheorghe-Teodor Bercea625f59d2019-08-01 21:15:58 +00002674 OS << CGM.getMangledName(GlobalDecl(VD));
2675 if (!VD->isExternallyVisible()) {
2676 unsigned DeviceID, FileID, Line;
2677 getTargetEntryUniqueInfo(CGM.getContext(),
2678 VD->getCanonicalDecl()->getBeginLoc(),
2679 DeviceID, FileID, Line);
2680 OS << llvm::format("_%x", FileID);
2681 }
2682 OS << "_decl_tgt_ref_ptr";
Alexey Bataev92327c52018-03-26 16:40:55 +00002683 }
2684 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName);
2685 if (!Ptr) {
2686 QualType PtrTy = CGM.getContext().getPointerType(VD->getType());
2687 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy),
2688 PtrName);
Gheorghe-Teodor Bercea625f59d2019-08-01 21:15:58 +00002689
2690 auto *GV = cast<llvm::GlobalVariable>(Ptr);
2691 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
2692
2693 if (!CGM.getLangOpts().OpenMPIsDevice)
Alexey Bataev03f270c2018-03-30 18:31:07 +00002694 GV->setInitializer(CGM.GetAddrOfGlobal(VD));
Alexey Bataev03f270c2018-03-30 18:31:07 +00002695 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr));
Alexey Bataev92327c52018-03-26 16:40:55 +00002696 }
2697 return Address(Ptr, CGM.getContext().getDeclAlign(VD));
2698 }
2699 return Address::invalid();
2700}
2701
Alexey Bataev97720002014-11-11 04:05:39 +00002702llvm::Constant *
2703CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002704 assert(!CGM.getLangOpts().OpenMPUseTLS ||
2705 !CGM.getContext().getTargetInfo().isTLSSupported());
Alexey Bataev97720002014-11-11 04:05:39 +00002706 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev18fa2322018-05-02 14:20:50 +00002707 std::string Suffix = getName({"cache", ""});
2708 return getOrCreateInternalVariable(
2709 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix));
Alexey Bataev97720002014-11-11 04:05:39 +00002710}
2711
John McCall7f416cc2015-09-08 08:05:57 +00002712Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
2713 const VarDecl *VD,
2714 Address VDAddr,
2715 SourceLocation Loc) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002716 if (CGM.getLangOpts().OpenMPUseTLS &&
2717 CGM.getContext().getTargetInfo().isTLSSupported())
2718 return VDAddr;
2719
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002720 llvm::Type *VarTy = VDAddr.getElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002721 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00002722 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
2723 CGM.Int8PtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00002724 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
2725 getOrCreateThreadPrivateCache(VD)};
John McCall7f416cc2015-09-08 08:05:57 +00002726 return Address(CGF.EmitRuntimeCall(
2727 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
2728 VDAddr.getAlignment());
Alexey Bataev97720002014-11-11 04:05:39 +00002729}
2730
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002731void CGOpenMPRuntime::emitThreadPrivateVarInit(
John McCall7f416cc2015-09-08 08:05:57 +00002732 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
Alexey Bataev97720002014-11-11 04:05:39 +00002733 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
2734 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
2735 // library.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002736 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002737 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +00002738 OMPLoc);
2739 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
2740 // to register constructor/destructor for variable.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002741 llvm::Value *Args[] = {
2742 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy),
2743 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +00002744 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002745 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +00002746}
2747
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002748llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
John McCall7f416cc2015-09-08 08:05:57 +00002749 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
Alexey Bataev97720002014-11-11 04:05:39 +00002750 bool PerformInit, CodeGenFunction *CGF) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002751 if (CGM.getLangOpts().OpenMPUseTLS &&
2752 CGM.getContext().getTargetInfo().isTLSSupported())
2753 return nullptr;
2754
Alexey Bataev97720002014-11-11 04:05:39 +00002755 VD = VD->getDefinition(CGM.getContext());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00002756 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) {
Alexey Bataev97720002014-11-11 04:05:39 +00002757 QualType ASTTy = VD->getType();
2758
2759 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002760 const Expr *Init = VD->getAnyInitializer();
Alexey Bataev97720002014-11-11 04:05:39 +00002761 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
2762 // Generate function that re-emits the declaration's initializer into the
2763 // threadprivate copy of the variable VD
2764 CodeGenFunction CtorCGF(CGM);
2765 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002766 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
2767 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
Alexey Bataev56223232017-06-09 13:40:18 +00002768 ImplicitParamDecl::Other);
Alexey Bataev97720002014-11-11 04:05:39 +00002769 Args.push_back(&Dst);
2770
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002771 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
John McCallc56a8b32016-03-11 04:30:31 +00002772 CGM.getContext().VoidPtrTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002773 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002774 std::string Name = getName({"__kmpc_global_ctor_", ""});
2775 llvm::Function *Fn =
2776 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002777 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002778 Args, Loc, Loc);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002779 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002780 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00002781 CGM.getContext().VoidPtrTy, Dst.getLocation());
John McCall7f416cc2015-09-08 08:05:57 +00002782 Address Arg = Address(ArgVal, VDAddr.getAlignment());
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002783 Arg = CtorCGF.Builder.CreateElementBitCast(
2784 Arg, CtorCGF.ConvertTypeForMem(ASTTy));
Alexey Bataev97720002014-11-11 04:05:39 +00002785 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
2786 /*IsInitializer=*/true);
2787 ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002788 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00002789 CGM.getContext().VoidPtrTy, Dst.getLocation());
2790 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
2791 CtorCGF.FinishFunction();
2792 Ctor = Fn;
2793 }
2794 if (VD->getType().isDestructedType() != QualType::DK_none) {
2795 // Generate function that emits destructor call for the threadprivate copy
2796 // of the variable VD
2797 CodeGenFunction DtorCGF(CGM);
2798 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002799 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
2800 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
Alexey Bataev56223232017-06-09 13:40:18 +00002801 ImplicitParamDecl::Other);
Alexey Bataev97720002014-11-11 04:05:39 +00002802 Args.push_back(&Dst);
2803
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002804 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
John McCallc56a8b32016-03-11 04:30:31 +00002805 CGM.getContext().VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002806 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002807 std::string Name = getName({"__kmpc_global_dtor_", ""});
2808 llvm::Function *Fn =
2809 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
Adrian Prantl1858c662016-04-24 22:22:29 +00002810 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
Alexey Bataev97720002014-11-11 04:05:39 +00002811 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002812 Loc, Loc);
Adrian Prantl1858c662016-04-24 22:22:29 +00002813 // Create a scope with an artificial location for the body of this function.
2814 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002815 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar(
Alexey Bataev97720002014-11-11 04:05:39 +00002816 DtorCGF.GetAddrOfLocalVar(&Dst),
John McCall7f416cc2015-09-08 08:05:57 +00002817 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
2818 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
Alexey Bataev97720002014-11-11 04:05:39 +00002819 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
2820 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
2821 DtorCGF.FinishFunction();
2822 Dtor = Fn;
2823 }
2824 // Do not emit init function if it is not required.
2825 if (!Ctor && !Dtor)
2826 return nullptr;
2827
2828 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002829 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
2830 /*isVarArg=*/false)
2831 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002832 // Copying constructor for the threadprivate variable.
2833 // Must be NULL - reserved by runtime, but currently it requires that this
2834 // parameter is always NULL. Otherwise it fires assertion.
2835 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
2836 if (Ctor == nullptr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002837 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
2838 /*isVarArg=*/false)
2839 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002840 Ctor = llvm::Constant::getNullValue(CtorTy);
2841 }
2842 if (Dtor == nullptr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002843 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
2844 /*isVarArg=*/false)
2845 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002846 Dtor = llvm::Constant::getNullValue(DtorTy);
2847 }
2848 if (!CGF) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002849 auto *InitFunctionTy =
Alexey Bataev97720002014-11-11 04:05:39 +00002850 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002851 std::string Name = getName({"__omp_threadprivate_init_", ""});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002852 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction(
Alexey Bataev18fa2322018-05-02 14:20:50 +00002853 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction());
Alexey Bataev97720002014-11-11 04:05:39 +00002854 CodeGenFunction InitCGF(CGM);
2855 FunctionArgList ArgList;
2856 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
2857 CGM.getTypes().arrangeNullaryFunction(), ArgList,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002858 Loc, Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002859 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002860 InitCGF.FinishFunction();
2861 return InitFunction;
2862 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002863 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002864 }
2865 return nullptr;
2866}
2867
Alexey Bataev34f8a702018-03-28 14:28:54 +00002868bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD,
2869 llvm::GlobalVariable *Addr,
2870 bool PerformInit) {
Alexey Bataev36724b72019-10-03 16:46:49 +00002871 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
2872 !CGM.getLangOpts().OpenMPIsDevice)
Alexey Bataev4db9dc62019-09-23 15:53:51 +00002873 return false;
Alexey Bataev34f8a702018-03-28 14:28:54 +00002874 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00002875 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00002876 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
2877 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
2878 HasRequiresUnifiedSharedMemory))
Alexey Bataevd01b7492018-08-15 19:45:12 +00002879 return CGM.getLangOpts().OpenMPIsDevice;
Alexey Bataev34f8a702018-03-28 14:28:54 +00002880 VD = VD->getDefinition(CGM.getContext());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00002881 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second)
Alexey Bataev34f8a702018-03-28 14:28:54 +00002882 return CGM.getLangOpts().OpenMPIsDevice;
2883
2884 QualType ASTTy = VD->getType();
2885
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002886 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc();
Alexey Bataev34f8a702018-03-28 14:28:54 +00002887 // Produce the unique prefix to identify the new target regions. We use
2888 // the source location of the variable declaration which we know to not
2889 // conflict with any target region.
2890 unsigned DeviceID;
2891 unsigned FileID;
2892 unsigned Line;
2893 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line);
2894 SmallString<128> Buffer, Out;
2895 {
2896 llvm::raw_svector_ostream OS(Buffer);
2897 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID)
2898 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
2899 }
2900
2901 const Expr *Init = VD->getAnyInitializer();
2902 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
2903 llvm::Constant *Ctor;
2904 llvm::Constant *ID;
2905 if (CGM.getLangOpts().OpenMPIsDevice) {
2906 // Generate function that re-emits the declaration's initializer into
2907 // the threadprivate copy of the variable VD
2908 CodeGenFunction CtorCGF(CGM);
2909
2910 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2911 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2912 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
2913 FTy, Twine(Buffer, "_ctor"), FI, Loc);
2914 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF);
2915 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
2916 FunctionArgList(), Loc, Loc);
2917 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF);
2918 CtorCGF.EmitAnyExprToMem(Init,
2919 Address(Addr, CGM.getContext().getDeclAlign(VD)),
2920 Init->getType().getQualifiers(),
2921 /*IsInitializer=*/true);
2922 CtorCGF.FinishFunction();
2923 Ctor = Fn;
2924 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
Alexey Bataeve253f2f2018-05-09 14:15:18 +00002925 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor));
Alexey Bataev34f8a702018-03-28 14:28:54 +00002926 } else {
2927 Ctor = new llvm::GlobalVariable(
2928 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
2929 llvm::GlobalValue::PrivateLinkage,
2930 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor"));
2931 ID = Ctor;
2932 }
2933
2934 // Register the information for the entry associated with the constructor.
2935 Out.clear();
2936 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
2937 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor,
Alexey Bataev03f270c2018-03-30 18:31:07 +00002938 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor);
Alexey Bataev34f8a702018-03-28 14:28:54 +00002939 }
2940 if (VD->getType().isDestructedType() != QualType::DK_none) {
2941 llvm::Constant *Dtor;
2942 llvm::Constant *ID;
2943 if (CGM.getLangOpts().OpenMPIsDevice) {
2944 // Generate function that emits destructor call for the threadprivate
2945 // copy of the variable VD
2946 CodeGenFunction DtorCGF(CGM);
2947
2948 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2949 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2950 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
2951 FTy, Twine(Buffer, "_dtor"), FI, Loc);
2952 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
2953 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
2954 FunctionArgList(), Loc, Loc);
2955 // Create a scope with an artificial location for the body of this
2956 // function.
2957 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
2958 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)),
2959 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()),
2960 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
2961 DtorCGF.FinishFunction();
2962 Dtor = Fn;
2963 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
Alexey Bataeve253f2f2018-05-09 14:15:18 +00002964 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor));
Alexey Bataev34f8a702018-03-28 14:28:54 +00002965 } else {
2966 Dtor = new llvm::GlobalVariable(
2967 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
2968 llvm::GlobalValue::PrivateLinkage,
2969 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor"));
2970 ID = Dtor;
2971 }
2972 // Register the information for the entry associated with the destructor.
2973 Out.clear();
2974 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
2975 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor,
Alexey Bataev03f270c2018-03-30 18:31:07 +00002976 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor);
Alexey Bataev34f8a702018-03-28 14:28:54 +00002977 }
2978 return CGM.getLangOpts().OpenMPIsDevice;
2979}
2980
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002981Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
2982 QualType VarType,
2983 StringRef Name) {
Alexey Bataev18fa2322018-05-02 14:20:50 +00002984 std::string Suffix = getName({"artificial", ""});
2985 std::string CacheSuffix = getName({"cache", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002986 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002987 llvm::Value *GAddr =
2988 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002989 llvm::Value *Args[] = {
2990 emitUpdateLocation(CGF, SourceLocation()),
2991 getThreadID(CGF, SourceLocation()),
2992 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy),
2993 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00002994 /*isSigned=*/false),
Alexey Bataev18fa2322018-05-02 14:20:50 +00002995 getOrCreateInternalVariable(
2996 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))};
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002997 return Address(
2998 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2999 CGF.EmitRuntimeCall(
3000 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
3001 VarLVType->getPointerTo(/*AddrSpace=*/0)),
3002 CGM.getPointerAlign());
3003}
3004
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +00003005void CGOpenMPRuntime::emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
3006 const RegionCodeGenTy &ThenGen,
3007 const RegionCodeGenTy &ElseGen) {
Alexey Bataev1d677132015-04-22 13:57:31 +00003008 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
3009
3010 // If the condition constant folds and can be elided, try to avoid emitting
3011 // the condition and the dead arm of the if/else.
3012 bool CondConstant;
3013 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003014 if (CondConstant)
Alexey Bataev1d677132015-04-22 13:57:31 +00003015 ThenGen(CGF);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003016 else
Alexey Bataev1d677132015-04-22 13:57:31 +00003017 ElseGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00003018 return;
3019 }
3020
3021 // Otherwise, the condition did not fold, or we couldn't elide it. Just
3022 // emit the conditional branch.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003023 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then");
3024 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else");
3025 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end");
Alexey Bataev1d677132015-04-22 13:57:31 +00003026 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
3027
3028 // Emit the 'then' code.
3029 CGF.EmitBlock(ThenBlock);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003030 ThenGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00003031 CGF.EmitBranch(ContBlock);
3032 // Emit the 'else' code if present.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003033 // There is no need to emit line number for unconditional branch.
3034 (void)ApplyDebugLocation::CreateEmpty(CGF);
3035 CGF.EmitBlock(ElseBlock);
3036 ElseGen(CGF);
3037 // There is no need to emit line number for unconditional branch.
3038 (void)ApplyDebugLocation::CreateEmpty(CGF);
3039 CGF.EmitBranch(ContBlock);
Alexey Bataev1d677132015-04-22 13:57:31 +00003040 // Emit the continuation block for code after the if.
3041 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003042}
3043
Alexey Bataev1d677132015-04-22 13:57:31 +00003044void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00003045 llvm::Function *OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00003046 ArrayRef<llvm::Value *> CapturedVars,
Alexey Bataev1d677132015-04-22 13:57:31 +00003047 const Expr *IfCond) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003048 if (!CGF.HaveInsertPoint())
3049 return;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003050 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003051 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF,
3052 PrePostActionTy &) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00003053 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003054 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev2377fe92015-09-10 08:12:02 +00003055 llvm::Value *Args[] = {
3056 RTLoc,
3057 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003058 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())};
Alexey Bataev2377fe92015-09-10 08:12:02 +00003059 llvm::SmallVector<llvm::Value *, 16> RealArgs;
3060 RealArgs.append(std::begin(Args), std::end(Args));
3061 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
3062
James Y Knight9871db02019-02-05 16:42:33 +00003063 llvm::FunctionCallee RTLFn =
3064 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call);
Alexey Bataev2377fe92015-09-10 08:12:02 +00003065 CGF.EmitRuntimeCall(RTLFn, RealArgs);
3066 };
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003067 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF,
3068 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003069 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
3070 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc);
Alexey Bataev1d677132015-04-22 13:57:31 +00003071 // Build calls:
3072 // __kmpc_serialized_parallel(&Loc, GTid);
3073 llvm::Value *Args[] = {RTLoc, ThreadID};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003074 CGF.EmitRuntimeCall(
3075 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +00003076
Alexey Bataev1d677132015-04-22 13:57:31 +00003077 // OutlinedFn(&GTid, &zero, CapturedStruct);
Alexey Bataev18fa2322018-05-02 14:20:50 +00003078 Address ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty,
3079 /*Name*/ ".zero.addr");
Alexey Bataev1d677132015-04-22 13:57:31 +00003080 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
Alexey Bataev2377fe92015-09-10 08:12:02 +00003081 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
Alexey Bataev8521ff62018-07-25 20:03:01 +00003082 // ThreadId for serialized parallels is 0.
3083 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
Alexey Bataev2377fe92015-09-10 08:12:02 +00003084 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
3085 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
Alexey Bataev3c595a62017-08-14 15:01:03 +00003086 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +00003087
Alexey Bataev1d677132015-04-22 13:57:31 +00003088 // __kmpc_end_serialized_parallel(&Loc, GTid);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003089 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID};
Alexey Bataev1d677132015-04-22 13:57:31 +00003090 CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003091 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel),
3092 EndArgs);
Alexey Bataev1d677132015-04-22 13:57:31 +00003093 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003094 if (IfCond) {
Alexey Bataev1d677132015-04-22 13:57:31 +00003095 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003096 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003097 RegionCodeGenTy ThenRCG(ThenGen);
3098 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00003099 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00003100}
3101
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00003102// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +00003103// thread-ID variable (it is passed in a first argument of the outlined function
3104// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
3105// regular serial code region, get thread ID by calling kmp_int32
3106// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
3107// return the address of that temp.
John McCall7f416cc2015-09-08 08:05:57 +00003108Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
3109 SourceLocation Loc) {
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003110 if (auto *OMPRegionInfo =
Alexey Bataevd74d0602014-10-13 06:02:40 +00003111 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003112 if (OMPRegionInfo->getThreadIDVariable())
Alexey Bataev62b63b12015-03-10 07:28:44 +00003113 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00003114
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003115 llvm::Value *ThreadID = getThreadID(CGF, Loc);
3116 QualType Int32Ty =
Alexey Bataevd74d0602014-10-13 06:02:40 +00003117 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003118 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
Alexey Bataevd74d0602014-10-13 06:02:40 +00003119 CGF.EmitStoreOfScalar(ThreadID,
John McCall7f416cc2015-09-08 08:05:57 +00003120 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
Alexey Bataevd74d0602014-10-13 06:02:40 +00003121
3122 return ThreadIDTemp;
3123}
3124
Alexey Bataev1af5bd52019-03-05 17:47:18 +00003125llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable(
3126 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003127 SmallString<256> Buffer;
3128 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00003129 Out << Name;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003130 StringRef RuntimeName = Out.str();
Alexey Bataev43a919f2018-04-13 17:48:43 +00003131 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first;
David Blaikie13156b62014-11-19 03:06:06 +00003132 if (Elem.second) {
3133 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00003134 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00003135 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00003136 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003137
David Blaikie13156b62014-11-19 03:06:06 +00003138 return Elem.second = new llvm::GlobalVariable(
3139 CGM.getModule(), Ty, /*IsConstant*/ false,
3140 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
Alexey Bataev1af5bd52019-03-05 17:47:18 +00003141 Elem.first(), /*InsertBefore=*/nullptr,
3142 llvm::GlobalValue::NotThreadLocal, AddressSpace);
Alexey Bataev97720002014-11-11 04:05:39 +00003143}
3144
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003145llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev18fa2322018-05-02 14:20:50 +00003146 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str();
3147 std::string Name = getName({Prefix, "var"});
3148 return getOrCreateInternalVariable(KmpCriticalNameTy, Name);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003149}
3150
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003151namespace {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003152/// Common pre(post)-action for different OpenMP constructs.
3153class CommonActionTy final : public PrePostActionTy {
James Y Knight9871db02019-02-05 16:42:33 +00003154 llvm::FunctionCallee EnterCallee;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003155 ArrayRef<llvm::Value *> EnterArgs;
James Y Knight9871db02019-02-05 16:42:33 +00003156 llvm::FunctionCallee ExitCallee;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003157 ArrayRef<llvm::Value *> ExitArgs;
3158 bool Conditional;
3159 llvm::BasicBlock *ContBlock = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003160
3161public:
James Y Knight9871db02019-02-05 16:42:33 +00003162 CommonActionTy(llvm::FunctionCallee EnterCallee,
3163 ArrayRef<llvm::Value *> EnterArgs,
3164 llvm::FunctionCallee ExitCallee,
3165 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003166 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
3167 ExitArgs(ExitArgs), Conditional(Conditional) {}
3168 void Enter(CodeGenFunction &CGF) override {
3169 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs);
3170 if (Conditional) {
3171 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes);
3172 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
3173 ContBlock = CGF.createBasicBlock("omp_if.end");
3174 // Generate the branch (If-stmt)
3175 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
3176 CGF.EmitBlock(ThenBlock);
3177 }
Alexey Bataeva744ff52015-05-05 09:24:37 +00003178 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003179 void Done(CodeGenFunction &CGF) {
3180 // Emit the rest of blocks/branches
3181 CGF.EmitBranch(ContBlock);
3182 CGF.EmitBlock(ContBlock, true);
3183 }
3184 void Exit(CodeGenFunction &CGF) override {
3185 CGF.EmitRuntimeCall(ExitCallee, ExitArgs);
Alexey Bataev3e6124b2015-04-10 07:48:12 +00003186 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003187};
Hans Wennborg7eb54642015-09-10 17:07:54 +00003188} // anonymous namespace
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003189
3190void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
3191 StringRef CriticalName,
3192 const RegionCodeGenTy &CriticalOpGen,
Alexey Bataevfc57d162015-12-15 10:55:09 +00003193 SourceLocation Loc, const Expr *Hint) {
3194 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
Alexey Bataev75ddfab2014-12-01 11:32:38 +00003195 // CriticalOpGen();
3196 // __kmpc_end_critical(ident_t *, gtid, Lock);
3197 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev8ef31412015-12-18 07:58:25 +00003198 if (!CGF.HaveInsertPoint())
3199 return;
Alexey Bataevfc57d162015-12-15 10:55:09 +00003200 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3201 getCriticalRegionLock(CriticalName)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003202 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args),
3203 std::end(Args));
Alexey Bataevfc57d162015-12-15 10:55:09 +00003204 if (Hint) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003205 EnterArgs.push_back(CGF.Builder.CreateIntCast(
3206 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false));
3207 }
3208 CommonActionTy Action(
3209 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint
3210 : OMPRTL__kmpc_critical),
3211 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args);
3212 CriticalOpGen.setAction(Action);
Alexey Bataevfc57d162015-12-15 10:55:09 +00003213 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003214}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003215
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003216void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003217 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003218 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003219 if (!CGF.HaveInsertPoint())
3220 return;
Alexey Bataev8d690652014-12-04 07:23:53 +00003221 // if(__kmpc_master(ident_t *, gtid)) {
3222 // MasterOpGen();
3223 // __kmpc_end_master(ident_t *, gtid);
3224 // }
3225 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00003226 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003227 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args,
3228 createRuntimeFunction(OMPRTL__kmpc_end_master), Args,
3229 /*Conditional=*/true);
3230 MasterOpGen.setAction(Action);
3231 emitInlinedDirective(CGF, OMPD_master, MasterOpGen);
3232 Action.Done(CGF);
Alexey Bataev8d690652014-12-04 07:23:53 +00003233}
3234
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003235void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
3236 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003237 if (!CGF.HaveInsertPoint())
3238 return;
Alexey Bataev9f797f32015-02-05 05:57:51 +00003239 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
3240 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003241 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00003242 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003243 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00003244 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
3245 Region->emitUntiedSwitch(CGF);
Alexey Bataev9f797f32015-02-05 05:57:51 +00003246}
3247
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003248void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
3249 const RegionCodeGenTy &TaskgroupOpGen,
3250 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003251 if (!CGF.HaveInsertPoint())
3252 return;
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003253 // __kmpc_taskgroup(ident_t *, gtid);
3254 // TaskgroupOpGen();
3255 // __kmpc_end_taskgroup(ident_t *, gtid);
3256 // Prepare arguments and build a call to __kmpc_taskgroup
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003257 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
3258 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args,
3259 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
3260 Args);
3261 TaskgroupOpGen.setAction(Action);
3262 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003263}
3264
John McCall7f416cc2015-09-08 08:05:57 +00003265/// Given an array of pointers to variables, project the address of a
3266/// given variable.
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003267static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
3268 unsigned Index, const VarDecl *Var) {
John McCall7f416cc2015-09-08 08:05:57 +00003269 // Pull out the pointer to the variable.
James Y Knight751fe282019-02-09 22:22:28 +00003270 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index);
John McCall7f416cc2015-09-08 08:05:57 +00003271 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
3272
3273 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003274 Addr = CGF.Builder.CreateElementBitCast(
3275 Addr, CGF.ConvertTypeForMem(Var->getType()));
John McCall7f416cc2015-09-08 08:05:57 +00003276 return Addr;
3277}
3278
Alexey Bataeva63048e2015-03-23 06:18:07 +00003279static llvm::Value *emitCopyprivateCopyFunction(
Alexey Bataev420d45b2015-04-14 05:11:24 +00003280 CodeGenModule &CGM, llvm::Type *ArgsType,
3281 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003282 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps,
3283 SourceLocation Loc) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003284 ASTContext &C = CGM.getContext();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003285 // void copy_func(void *LHSArg, void *RHSArg);
3286 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003287 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3288 ImplicitParamDecl::Other);
3289 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3290 ImplicitParamDecl::Other);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003291 Args.push_back(&LHSArg);
3292 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003293 const auto &CGFI =
3294 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00003295 std::string Name =
3296 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"});
3297 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
3298 llvm::GlobalValue::InternalLinkage, Name,
3299 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00003300 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00003301 Fn->setDoesNotRecurse();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003302 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003303 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev420d45b2015-04-14 05:11:24 +00003304 // Dest = (void*[n])(LHSArg);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003305 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00003306 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3307 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
3308 ArgsType), CGF.getPointerAlign());
3309 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3310 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
3311 ArgsType), CGF.getPointerAlign());
Alexey Bataeva63048e2015-03-23 06:18:07 +00003312 // *(Type0*)Dst[0] = *(Type0*)Src[0];
3313 // *(Type1*)Dst[1] = *(Type1*)Src[1];
3314 // ...
3315 // *(Typen*)Dst[n] = *(Typen*)Src[n];
Alexey Bataeva63048e2015-03-23 06:18:07 +00003316 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003317 const auto *DestVar =
3318 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +00003319 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
3320
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003321 const auto *SrcVar =
3322 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +00003323 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
3324
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003325 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003326 QualType Type = VD->getType();
John McCall7f416cc2015-09-08 08:05:57 +00003327 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003328 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00003329 CGF.FinishFunction();
3330 return Fn;
3331}
3332
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003333void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003334 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00003335 SourceLocation Loc,
3336 ArrayRef<const Expr *> CopyprivateVars,
3337 ArrayRef<const Expr *> SrcExprs,
3338 ArrayRef<const Expr *> DstExprs,
3339 ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003340 if (!CGF.HaveInsertPoint())
3341 return;
Alexey Bataeva63048e2015-03-23 06:18:07 +00003342 assert(CopyprivateVars.size() == SrcExprs.size() &&
3343 CopyprivateVars.size() == DstExprs.size() &&
3344 CopyprivateVars.size() == AssignmentOps.size());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003345 ASTContext &C = CGM.getContext();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003346 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003347 // if(__kmpc_single(ident_t *, gtid)) {
3348 // SingleOpGen();
3349 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003350 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003351 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00003352 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3353 // <copy_func>, did_it);
3354
John McCall7f416cc2015-09-08 08:05:57 +00003355 Address DidIt = Address::invalid();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003356 if (!CopyprivateVars.empty()) {
3357 // int32 did_it = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003358 QualType KmpInt32Ty =
3359 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003360 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
John McCall7f416cc2015-09-08 08:05:57 +00003361 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003362 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003363 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00003364 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003365 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args,
3366 createRuntimeFunction(OMPRTL__kmpc_end_single), Args,
3367 /*Conditional=*/true);
3368 SingleOpGen.setAction(Action);
3369 emitInlinedDirective(CGF, OMPD_single, SingleOpGen);
3370 if (DidIt.isValid()) {
3371 // did_it = 1;
3372 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
3373 }
3374 Action.Done(CGF);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003375 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3376 // <copy_func>, did_it);
John McCall7f416cc2015-09-08 08:05:57 +00003377 if (DidIt.isValid()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00003378 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
Richard Smith772e2662019-10-04 01:25:59 +00003379 QualType CopyprivateArrayTy = C.getConstantArrayType(
3380 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
3381 /*IndexTypeQuals=*/0);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003382 // Create a list of all private variables for copyprivate.
John McCall7f416cc2015-09-08 08:05:57 +00003383 Address CopyprivateList =
Alexey Bataeva63048e2015-03-23 06:18:07 +00003384 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
3385 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +00003386 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I);
John McCall7f416cc2015-09-08 08:05:57 +00003387 CGF.Builder.CreateStore(
Alexey Bataeva63048e2015-03-23 06:18:07 +00003388 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00003389 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy),
3390 Elem);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003391 }
3392 // Build function that copies private values from single region to all other
3393 // threads in the corresponding parallel region.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003394 llvm::Value *CpyFn = emitCopyprivateCopyFunction(
Alexey Bataeva63048e2015-03-23 06:18:07 +00003395 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003396 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003397 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00003398 Address CL =
3399 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
3400 CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003401 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003402 llvm::Value *Args[] = {
3403 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
3404 getThreadID(CGF, Loc), // i32 <gtid>
Alexey Bataev66beaa92015-04-30 03:47:32 +00003405 BufSize, // size_t <buf_size>
John McCall7f416cc2015-09-08 08:05:57 +00003406 CL.getPointer(), // void *<copyprivate list>
Alexey Bataeva63048e2015-03-23 06:18:07 +00003407 CpyFn, // void (*) (void *, void *) <copy_func>
3408 DidItVal // i32 did_it
3409 };
3410 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
3411 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003412}
3413
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003414void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
3415 const RegionCodeGenTy &OrderedOpGen,
Alexey Bataev5f600d62015-09-29 03:48:57 +00003416 SourceLocation Loc, bool IsThreads) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003417 if (!CGF.HaveInsertPoint())
3418 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003419 // __kmpc_ordered(ident_t *, gtid);
3420 // OrderedOpGen();
3421 // __kmpc_end_ordered(ident_t *, gtid);
3422 // Prepare arguments and build a call to __kmpc_ordered
Alexey Bataev5f600d62015-09-29 03:48:57 +00003423 if (IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003424 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003425 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args,
3426 createRuntimeFunction(OMPRTL__kmpc_end_ordered),
3427 Args);
3428 OrderedOpGen.setAction(Action);
3429 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
3430 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003431 }
Alexey Bataev5f600d62015-09-29 03:48:57 +00003432 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003433}
3434
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003435unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) {
Alexey Bataev50b3c952016-02-19 10:38:26 +00003436 unsigned Flags;
3437 if (Kind == OMPD_for)
3438 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
3439 else if (Kind == OMPD_sections)
3440 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
3441 else if (Kind == OMPD_single)
3442 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
3443 else if (Kind == OMPD_barrier)
3444 Flags = OMP_IDENT_BARRIER_EXPL;
3445 else
3446 Flags = OMP_IDENT_BARRIER_IMPL;
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003447 return Flags;
3448}
3449
Alexey Bataevf6a53d62019-03-18 18:40:00 +00003450void CGOpenMPRuntime::getDefaultScheduleAndChunk(
3451 CodeGenFunction &CGF, const OMPLoopDirective &S,
3452 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const {
3453 // Check if the loop directive is actually a doacross loop directive. In this
3454 // case choose static, 1 schedule.
3455 if (llvm::any_of(
3456 S.getClausesOfKind<OMPOrderedClause>(),
3457 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) {
3458 ScheduleKind = OMPC_SCHEDULE_static;
3459 // Chunk size is 1 in this case.
3460 llvm::APInt ChunkSize(32, 1);
3461 ChunkExpr = IntegerLiteral::Create(
3462 CGF.getContext(), ChunkSize,
3463 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
3464 SourceLocation());
3465 }
3466}
3467
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003468void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
3469 OpenMPDirectiveKind Kind, bool EmitChecks,
3470 bool ForceSimpleCall) {
3471 if (!CGF.HaveInsertPoint())
3472 return;
3473 // Build call __kmpc_cancel_barrier(loc, thread_id);
3474 // Build call __kmpc_barrier(loc, thread_id);
3475 unsigned Flags = getDefaultFlagsForBarriers(Kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003476 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
3477 // thread_id);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003478 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
3479 getThreadID(CGF, Loc)};
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003480 if (auto *OMPRegionInfo =
3481 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00003482 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003483 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003484 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev25e5b442015-09-15 12:52:43 +00003485 if (EmitChecks) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003486 // if (__kmpc_cancel_barrier()) {
3487 // exit from construct;
3488 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003489 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
3490 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
3491 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003492 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
3493 CGF.EmitBlock(ExitBB);
3494 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003495 CodeGenFunction::JumpDest CancelDestination =
Alexey Bataev25e5b442015-09-15 12:52:43 +00003496 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003497 CGF.EmitBranchThroughCleanup(CancelDestination);
3498 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
3499 }
3500 return;
3501 }
3502 }
3503 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003504}
3505
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003506/// Map the OpenMP loop schedule to the runtime enumeration.
Alexander Musmanc6388682014-12-15 07:07:06 +00003507static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003508 bool Chunked, bool Ordered) {
Alexander Musmanc6388682014-12-15 07:07:06 +00003509 switch (ScheduleKind) {
3510 case OMPC_SCHEDULE_static:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003511 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
3512 : (Ordered ? OMP_ord_static : OMP_sch_static);
Alexander Musmanc6388682014-12-15 07:07:06 +00003513 case OMPC_SCHEDULE_dynamic:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003514 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00003515 case OMPC_SCHEDULE_guided:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003516 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00003517 case OMPC_SCHEDULE_runtime:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003518 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
3519 case OMPC_SCHEDULE_auto:
3520 return Ordered ? OMP_ord_auto : OMP_sch_auto;
Alexander Musmanc6388682014-12-15 07:07:06 +00003521 case OMPC_SCHEDULE_unknown:
3522 assert(!Chunked && "chunk was specified but schedule kind not known");
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003523 return Ordered ? OMP_ord_static : OMP_sch_static;
Alexander Musmanc6388682014-12-15 07:07:06 +00003524 }
3525 llvm_unreachable("Unexpected runtime schedule");
3526}
3527
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003528/// Map the OpenMP distribute schedule to the runtime enumeration.
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003529static OpenMPSchedType
3530getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
3531 // only static is allowed for dist_schedule
3532 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
3533}
3534
Alexander Musmanc6388682014-12-15 07:07:06 +00003535bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
3536 bool Chunked) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003537 OpenMPSchedType Schedule =
3538 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
Alexander Musmanc6388682014-12-15 07:07:06 +00003539 return Schedule == OMP_sch_static;
3540}
3541
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003542bool CGOpenMPRuntime::isStaticNonchunked(
3543 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003544 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003545 return Schedule == OMP_dist_sch_static;
3546}
3547
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00003548bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind,
3549 bool Chunked) const {
3550 OpenMPSchedType Schedule =
3551 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
3552 return Schedule == OMP_sch_static_chunked;
3553}
3554
3555bool CGOpenMPRuntime::isStaticChunked(
3556 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
3557 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
3558 return Schedule == OMP_dist_sch_static_chunked;
3559}
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003560
Alexander Musmandf7a8e22015-01-22 08:49:35 +00003561bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003562 OpenMPSchedType Schedule =
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003563 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00003564 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
3565 return Schedule != OMP_sch_static;
3566}
3567
Alexey Bataev07a3b592019-08-23 19:52:05 +00003568static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003569 OpenMPScheduleClauseModifier M1,
3570 OpenMPScheduleClauseModifier M2) {
Alexey Bataev6cff6242016-05-30 13:05:14 +00003571 int Modifier = 0;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003572 switch (M1) {
3573 case OMPC_SCHEDULE_MODIFIER_monotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003574 Modifier = OMP_sch_modifier_monotonic;
3575 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003576 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003577 Modifier = OMP_sch_modifier_nonmonotonic;
3578 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003579 case OMPC_SCHEDULE_MODIFIER_simd:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003580 if (Schedule == OMP_sch_static_chunked)
3581 Schedule = OMP_sch_static_balanced_chunked;
3582 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003583 case OMPC_SCHEDULE_MODIFIER_last:
3584 case OMPC_SCHEDULE_MODIFIER_unknown:
3585 break;
3586 }
3587 switch (M2) {
3588 case OMPC_SCHEDULE_MODIFIER_monotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003589 Modifier = OMP_sch_modifier_monotonic;
3590 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003591 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003592 Modifier = OMP_sch_modifier_nonmonotonic;
3593 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003594 case OMPC_SCHEDULE_MODIFIER_simd:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003595 if (Schedule == OMP_sch_static_chunked)
3596 Schedule = OMP_sch_static_balanced_chunked;
3597 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003598 case OMPC_SCHEDULE_MODIFIER_last:
3599 case OMPC_SCHEDULE_MODIFIER_unknown:
3600 break;
3601 }
Alexey Bataev07a3b592019-08-23 19:52:05 +00003602 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription.
3603 // If the static schedule kind is specified or if the ordered clause is
3604 // specified, and if the nonmonotonic modifier is not specified, the effect is
3605 // as if the monotonic modifier is specified. Otherwise, unless the monotonic
3606 // modifier is specified, the effect is as if the nonmonotonic modifier is
3607 // specified.
3608 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) {
3609 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static ||
3610 Schedule == OMP_sch_static_balanced_chunked ||
3611 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static))
3612 Modifier = OMP_sch_modifier_nonmonotonic;
3613 }
Alexey Bataev6cff6242016-05-30 13:05:14 +00003614 return Schedule | Modifier;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003615}
3616
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003617void CGOpenMPRuntime::emitForDispatchInit(
3618 CodeGenFunction &CGF, SourceLocation Loc,
3619 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
3620 bool Ordered, const DispatchRTInput &DispatchValues) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003621 if (!CGF.HaveInsertPoint())
3622 return;
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003623 OpenMPSchedType Schedule = getRuntimeSchedule(
3624 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered);
John McCall7f416cc2015-09-08 08:05:57 +00003625 assert(Ordered ||
3626 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
Alexey Bataev6cff6242016-05-30 13:05:14 +00003627 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
3628 Schedule != OMP_sch_static_balanced_chunked));
John McCall7f416cc2015-09-08 08:05:57 +00003629 // Call __kmpc_dispatch_init(
3630 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
3631 // kmp_int[32|64] lower, kmp_int[32|64] upper,
3632 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00003633
John McCall7f416cc2015-09-08 08:05:57 +00003634 // If the Chunk was not specified in the clause - use default value 1.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003635 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk
3636 : CGF.Builder.getIntN(IVSize, 1);
John McCall7f416cc2015-09-08 08:05:57 +00003637 llvm::Value *Args[] = {
Alexey Bataev07a3b592019-08-23 19:52:05 +00003638 emitUpdateLocation(CGF, Loc),
3639 getThreadID(CGF, Loc),
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003640 CGF.Builder.getInt32(addMonoNonMonoModifier(
Alexey Bataev07a3b592019-08-23 19:52:05 +00003641 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type
3642 DispatchValues.LB, // Lower
3643 DispatchValues.UB, // Upper
3644 CGF.Builder.getIntN(IVSize, 1), // Stride
3645 Chunk // Chunk
John McCall7f416cc2015-09-08 08:05:57 +00003646 };
3647 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
3648}
3649
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003650static void emitForStaticInitCall(
3651 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
James Y Knight9871db02019-02-05 16:42:33 +00003652 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003653 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003654 const CGOpenMPRuntime::StaticRTInput &Values) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003655 if (!CGF.HaveInsertPoint())
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003656 return;
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003657
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003658 assert(!Values.Ordered);
3659 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
3660 Schedule == OMP_sch_static_balanced_chunked ||
3661 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
3662 Schedule == OMP_dist_sch_static ||
3663 Schedule == OMP_dist_sch_static_chunked);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003664
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003665 // Call __kmpc_for_static_init(
3666 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
3667 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
3668 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
3669 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
3670 llvm::Value *Chunk = Values.Chunk;
3671 if (Chunk == nullptr) {
3672 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
3673 Schedule == OMP_dist_sch_static) &&
3674 "expected static non-chunked schedule");
3675 // If the Chunk was not specified in the clause - use default value 1.
3676 Chunk = CGF.Builder.getIntN(Values.IVSize, 1);
3677 } else {
3678 assert((Schedule == OMP_sch_static_chunked ||
3679 Schedule == OMP_sch_static_balanced_chunked ||
3680 Schedule == OMP_ord_static_chunked ||
3681 Schedule == OMP_dist_sch_static_chunked) &&
3682 "expected static chunked schedule");
3683 }
3684 llvm::Value *Args[] = {
3685 UpdateLocation,
3686 ThreadId,
Alexey Bataev07a3b592019-08-23 19:52:05 +00003687 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003688 M2)), // Schedule type
3689 Values.IL.getPointer(), // &isLastIter
3690 Values.LB.getPointer(), // &LB
3691 Values.UB.getPointer(), // &UB
3692 Values.ST.getPointer(), // &Stride
3693 CGF.Builder.getIntN(Values.IVSize, 1), // Incr
3694 Chunk // Chunk
3695 };
3696 CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003697}
3698
John McCall7f416cc2015-09-08 08:05:57 +00003699void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
3700 SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003701 OpenMPDirectiveKind DKind,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003702 const OpenMPScheduleTy &ScheduleKind,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003703 const StaticRTInput &Values) {
3704 OpenMPSchedType ScheduleNum = getRuntimeSchedule(
3705 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered);
3706 assert(isOpenMPWorksharingDirective(DKind) &&
3707 "Expected loop-based or sections-based directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003708 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003709 isOpenMPLoopDirective(DKind)
3710 ? OMP_IDENT_WORK_LOOP
3711 : OMP_IDENT_WORK_SECTIONS);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003712 llvm::Value *ThreadId = getThreadID(CGF, Loc);
James Y Knight9871db02019-02-05 16:42:33 +00003713 llvm::FunctionCallee StaticInitFunction =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003714 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003715 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003716 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003717}
John McCall7f416cc2015-09-08 08:05:57 +00003718
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003719void CGOpenMPRuntime::emitDistributeStaticInit(
3720 CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003721 OpenMPDistScheduleClauseKind SchedKind,
3722 const CGOpenMPRuntime::StaticRTInput &Values) {
3723 OpenMPSchedType ScheduleNum =
3724 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003725 llvm::Value *UpdatedLocation =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003726 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003727 llvm::Value *ThreadId = getThreadID(CGF, Loc);
James Y Knight9871db02019-02-05 16:42:33 +00003728 llvm::FunctionCallee StaticInitFunction =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003729 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003730 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
3731 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003732 OMPC_SCHEDULE_MODIFIER_unknown, Values);
Alexander Musmanc6388682014-12-15 07:07:06 +00003733}
3734
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003735void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
Alexey Bataevf43f7142017-09-06 16:17:35 +00003736 SourceLocation Loc,
3737 OpenMPDirectiveKind DKind) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003738 if (!CGF.HaveInsertPoint())
3739 return;
Alexander Musmanc6388682014-12-15 07:07:06 +00003740 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataevf43f7142017-09-06 16:17:35 +00003741 llvm::Value *Args[] = {
3742 emitUpdateLocation(CGF, Loc,
3743 isOpenMPDistributeDirective(DKind)
3744 ? OMP_IDENT_WORK_DISTRIBUTE
3745 : isOpenMPLoopDirective(DKind)
3746 ? OMP_IDENT_WORK_LOOP
3747 : OMP_IDENT_WORK_SECTIONS),
3748 getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003749 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
3750 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00003751}
3752
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003753void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
3754 SourceLocation Loc,
3755 unsigned IVSize,
3756 bool IVSigned) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003757 if (!CGF.HaveInsertPoint())
3758 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003759 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00003760 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003761 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
3762}
3763
Alexander Musman92bdaab2015-03-12 13:37:50 +00003764llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
3765 SourceLocation Loc, unsigned IVSize,
John McCall7f416cc2015-09-08 08:05:57 +00003766 bool IVSigned, Address IL,
3767 Address LB, Address UB,
3768 Address ST) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00003769 // Call __kmpc_dispatch_next(
3770 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
3771 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
3772 // kmp_int[32|64] *p_stride);
3773 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00003774 emitUpdateLocation(CGF, Loc),
3775 getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00003776 IL.getPointer(), // &isLastIter
3777 LB.getPointer(), // &Lower
3778 UB.getPointer(), // &Upper
3779 ST.getPointer() // &Stride
Alexander Musman92bdaab2015-03-12 13:37:50 +00003780 };
3781 llvm::Value *Call =
3782 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
3783 return CGF.EmitScalarConversion(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003784 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00003785 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00003786}
3787
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003788void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
3789 llvm::Value *NumThreads,
3790 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003791 if (!CGF.HaveInsertPoint())
3792 return;
Alexey Bataevb2059782014-10-13 08:23:51 +00003793 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
3794 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003795 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00003796 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003797 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
3798 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00003799}
3800
Alexey Bataev7f210c62015-06-18 13:40:03 +00003801void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
3802 OpenMPProcBindClauseKind ProcBind,
3803 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003804 if (!CGF.HaveInsertPoint())
3805 return;
Alexey Bataev7f210c62015-06-18 13:40:03 +00003806 // Constants for proc bind value accepted by the runtime.
3807 enum ProcBindTy {
3808 ProcBindFalse = 0,
3809 ProcBindTrue,
3810 ProcBindMaster,
3811 ProcBindClose,
3812 ProcBindSpread,
3813 ProcBindIntel,
3814 ProcBindDefault
3815 } RuntimeProcBind;
3816 switch (ProcBind) {
3817 case OMPC_PROC_BIND_master:
3818 RuntimeProcBind = ProcBindMaster;
3819 break;
3820 case OMPC_PROC_BIND_close:
3821 RuntimeProcBind = ProcBindClose;
3822 break;
3823 case OMPC_PROC_BIND_spread:
3824 RuntimeProcBind = ProcBindSpread;
3825 break;
3826 case OMPC_PROC_BIND_unknown:
3827 llvm_unreachable("Unsupported proc_bind value.");
3828 }
3829 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
3830 llvm::Value *Args[] = {
3831 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3832 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
3833 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
3834}
3835
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003836void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
3837 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003838 if (!CGF.HaveInsertPoint())
3839 return;
Alexey Bataevd76df6d2015-02-24 12:55:09 +00003840 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003841 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
3842 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00003843}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003844
Alexey Bataev62b63b12015-03-10 07:28:44 +00003845namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003846/// Indexes of fields for type kmp_task_t.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003847enum KmpTaskTFields {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003848 /// List of shared variables.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003849 KmpTaskTShareds,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003850 /// Task routine.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003851 KmpTaskTRoutine,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003852 /// Partition id for the untied tasks.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003853 KmpTaskTPartId,
Alexey Bataevad537bb2016-05-30 09:06:50 +00003854 /// Function with call of destructors for private variables.
3855 Data1,
3856 /// Task priority.
3857 Data2,
Alexey Bataev7292c292016-04-25 12:22:29 +00003858 /// (Taskloops only) Lower bound.
3859 KmpTaskTLowerBound,
3860 /// (Taskloops only) Upper bound.
3861 KmpTaskTUpperBound,
3862 /// (Taskloops only) Stride.
3863 KmpTaskTStride,
3864 /// (Taskloops only) Is last iteration flag.
3865 KmpTaskTLastIter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003866 /// (Taskloops only) Reduction data.
3867 KmpTaskTReductions,
Alexey Bataev62b63b12015-03-10 07:28:44 +00003868};
Hans Wennborg7eb54642015-09-10 17:07:54 +00003869} // anonymous namespace
Alexey Bataev62b63b12015-03-10 07:28:44 +00003870
Samuel Antaoee8fb302016-01-06 13:42:12 +00003871bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003872 return OffloadEntriesTargetRegion.empty() &&
3873 OffloadEntriesDeviceGlobalVar.empty();
Samuel Antaoee8fb302016-01-06 13:42:12 +00003874}
3875
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003876/// Initialize target region entry.
Samuel Antaoee8fb302016-01-06 13:42:12 +00003877void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3878 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3879 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00003880 unsigned Order) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003881 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
3882 "only required for the device "
3883 "code generation.");
Samuel Antao2de62b02016-02-13 23:35:10 +00003884 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
Samuel Antaof83efdb2017-01-05 16:02:49 +00003885 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003886 OMPTargetRegionEntryTargetRegion);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003887 ++OffloadingEntriesNum;
3888}
3889
3890void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3891 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3892 StringRef ParentName, unsigned LineNum,
Samuel Antaof83efdb2017-01-05 16:02:49 +00003893 llvm::Constant *Addr, llvm::Constant *ID,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003894 OMPTargetRegionEntryKind Flags) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003895 // If we are emitting code for a target, the entry is already initialized,
3896 // only has to be registered.
3897 if (CGM.getLangOpts().OpenMPIsDevice) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00003898 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) {
3899 unsigned DiagID = CGM.getDiags().getCustomDiagID(
3900 DiagnosticsEngine::Error,
3901 "Unable to find target region on line '%0' in the device code.");
3902 CGM.getDiags().Report(DiagID) << LineNum;
3903 return;
3904 }
Samuel Antao2de62b02016-02-13 23:35:10 +00003905 auto &Entry =
3906 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
Samuel Antaoee8fb302016-01-06 13:42:12 +00003907 assert(Entry.isValid() && "Entry not initialized!");
3908 Entry.setAddress(Addr);
3909 Entry.setID(ID);
Samuel Antaof83efdb2017-01-05 16:02:49 +00003910 Entry.setFlags(Flags);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003911 } else {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003912 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags);
Samuel Antao2de62b02016-02-13 23:35:10 +00003913 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00003914 ++OffloadingEntriesNum;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003915 }
3916}
3917
3918bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00003919 unsigned DeviceID, unsigned FileID, StringRef ParentName,
3920 unsigned LineNum) const {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003921 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
3922 if (PerDevice == OffloadEntriesTargetRegion.end())
3923 return false;
3924 auto PerFile = PerDevice->second.find(FileID);
3925 if (PerFile == PerDevice->second.end())
3926 return false;
3927 auto PerParentName = PerFile->second.find(ParentName);
3928 if (PerParentName == PerFile->second.end())
3929 return false;
3930 auto PerLine = PerParentName->second.find(LineNum);
3931 if (PerLine == PerParentName->second.end())
3932 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003933 // Fail if this entry is already registered.
Samuel Antao2de62b02016-02-13 23:35:10 +00003934 if (PerLine->second.getAddress() || PerLine->second.getID())
Samuel Antaoee8fb302016-01-06 13:42:12 +00003935 return false;
3936 return true;
3937}
3938
3939void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
3940 const OffloadTargetRegionEntryInfoActTy &Action) {
3941 // Scan all target region entries and perform the provided action.
Alexey Bataev03f270c2018-03-30 18:31:07 +00003942 for (const auto &D : OffloadEntriesTargetRegion)
3943 for (const auto &F : D.second)
3944 for (const auto &P : F.second)
3945 for (const auto &L : P.second)
Samuel Antao2de62b02016-02-13 23:35:10 +00003946 Action(D.first, F.first, P.first(), L.first, L.second);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003947}
3948
Alexey Bataev03f270c2018-03-30 18:31:07 +00003949void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3950 initializeDeviceGlobalVarEntryInfo(StringRef Name,
3951 OMPTargetGlobalVarEntryKind Flags,
3952 unsigned Order) {
3953 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
3954 "only required for the device "
3955 "code generation.");
3956 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
3957 ++OffloadingEntriesNum;
3958}
Samuel Antaoee8fb302016-01-06 13:42:12 +00003959
Alexey Bataev03f270c2018-03-30 18:31:07 +00003960void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3961 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr,
3962 CharUnits VarSize,
3963 OMPTargetGlobalVarEntryKind Flags,
3964 llvm::GlobalValue::LinkageTypes Linkage) {
3965 if (CGM.getLangOpts().OpenMPIsDevice) {
3966 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3967 assert(Entry.isValid() && Entry.getFlags() == Flags &&
3968 "Entry not initialized!");
3969 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
3970 "Resetting with the new address.");
Alexey Bataev8259cc32019-03-12 20:05:17 +00003971 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) {
3972 if (Entry.getVarSize().isZero()) {
3973 Entry.setVarSize(VarSize);
3974 Entry.setLinkage(Linkage);
3975 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003976 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00003977 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003978 Entry.setVarSize(VarSize);
3979 Entry.setLinkage(Linkage);
Alexey Bataev8259cc32019-03-12 20:05:17 +00003980 Entry.setAddress(Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00003981 } else {
Alexey Bataev8259cc32019-03-12 20:05:17 +00003982 if (hasDeviceGlobalVarEntryInfo(VarName)) {
3983 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3984 assert(Entry.isValid() && Entry.getFlags() == Flags &&
3985 "Entry not initialized!");
3986 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
3987 "Resetting with the new address.");
3988 if (Entry.getVarSize().isZero()) {
3989 Entry.setVarSize(VarSize);
3990 Entry.setLinkage(Linkage);
3991 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003992 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00003993 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003994 OffloadEntriesDeviceGlobalVar.try_emplace(
3995 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage);
3996 ++OffloadingEntriesNum;
3997 }
3998}
3999
4000void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
4001 actOnDeviceGlobalVarEntriesInfo(
4002 const OffloadDeviceGlobalVarEntryInfoActTy &Action) {
4003 // Scan all target region entries and perform the provided action.
4004 for (const auto &E : OffloadEntriesDeviceGlobalVar)
4005 Action(E.getKey(), E.getValue());
Samuel Antaoee8fb302016-01-06 13:42:12 +00004006}
4007
4008llvm::Function *
4009CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004010 // If we don't have entries or if we are emitting code for the device, we
4011 // don't need to do anything.
4012 if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty())
4013 return nullptr;
4014
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004015 llvm::Module &M = CGM.getModule();
4016 ASTContext &C = CGM.getContext();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004017
4018 // Get list of devices we care about
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004019 const std::vector<llvm::Triple> &Devices = CGM.getLangOpts().OMPTargetTriples;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004020
4021 // We should be creating an offloading descriptor only if there are devices
4022 // specified.
4023 assert(!Devices.empty() && "No OpenMP offloading devices??");
4024
4025 // Create the external variables that will point to the begin and end of the
4026 // host entries section. These will be defined by the linker.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004027 llvm::Type *OffloadEntryTy =
Samuel Antaoee8fb302016-01-06 13:42:12 +00004028 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004029 auto *HostEntriesBegin = new llvm::GlobalVariable(
Samuel Antaoee8fb302016-01-06 13:42:12 +00004030 M, OffloadEntryTy, /*isConstant=*/true,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00004031 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr,
Sergey Dmitriev4b343fd2019-09-27 20:00:51 +00004032 "__start_omp_offloading_entries");
4033 HostEntriesBegin->setVisibility(llvm::GlobalValue::HiddenVisibility);
4034 auto *HostEntriesEnd = new llvm::GlobalVariable(
4035 M, OffloadEntryTy, /*isConstant=*/true,
4036 llvm::GlobalValue::ExternalLinkage,
4037 /*Initializer=*/nullptr, "__stop_omp_offloading_entries");
4038 HostEntriesEnd->setVisibility(llvm::GlobalValue::HiddenVisibility);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004039
4040 // Create all device images
Samuel Antaoee8fb302016-01-06 13:42:12 +00004041 auto *DeviceImageTy = cast<llvm::StructType>(
4042 CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy()));
John McCall23c9dc62016-11-28 22:18:27 +00004043 ConstantInitBuilder DeviceImagesBuilder(CGM);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004044 ConstantArrayBuilder DeviceImagesEntries =
4045 DeviceImagesBuilder.beginArray(DeviceImageTy);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004046
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004047 for (const llvm::Triple &Device : Devices) {
Alexey Bataev03f270c2018-03-30 18:31:07 +00004048 StringRef T = Device.getTriple();
Alexey Bataev18fa2322018-05-02 14:20:50 +00004049 std::string BeginName = getName({"omp_offloading", "img_start", ""});
Samuel Antaoee8fb302016-01-06 13:42:12 +00004050 auto *ImgBegin = new llvm::GlobalVariable(
Alexey Bataev62a4cb02018-07-31 18:27:42 +00004051 M, CGM.Int8Ty, /*isConstant=*/true,
4052 llvm::GlobalValue::ExternalWeakLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00004053 /*Initializer=*/nullptr, Twine(BeginName).concat(T));
4054 std::string EndName = getName({"omp_offloading", "img_end", ""});
Samuel Antaoee8fb302016-01-06 13:42:12 +00004055 auto *ImgEnd = new llvm::GlobalVariable(
Alexey Bataev62a4cb02018-07-31 18:27:42 +00004056 M, CGM.Int8Ty, /*isConstant=*/true,
4057 llvm::GlobalValue::ExternalWeakLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00004058 /*Initializer=*/nullptr, Twine(EndName).concat(T));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004059
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004060 llvm::Constant *Data[] = {ImgBegin, ImgEnd, HostEntriesBegin,
4061 HostEntriesEnd};
4062 createConstantGlobalStructAndAddToParent(CGM, getTgtDeviceImageQTy(), Data,
4063 DeviceImagesEntries);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004064 }
4065
4066 // Create device images global array.
Alexey Bataev18fa2322018-05-02 14:20:50 +00004067 std::string ImagesName = getName({"omp_offloading", "device_images"});
John McCall6c9f1fdb2016-11-19 08:17:24 +00004068 llvm::GlobalVariable *DeviceImages =
Alexey Bataev18fa2322018-05-02 14:20:50 +00004069 DeviceImagesEntries.finishAndCreateGlobal(ImagesName,
4070 CGM.getPointerAlign(),
4071 /*isConstant=*/true);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00004072 DeviceImages->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004073
4074 // This is a Zero array to be used in the creation of the constant expressions
4075 llvm::Constant *Index[] = {llvm::Constant::getNullValue(CGM.Int32Ty),
4076 llvm::Constant::getNullValue(CGM.Int32Ty)};
4077
4078 // Create the target region descriptor.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004079 llvm::Constant *Data[] = {
4080 llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()),
4081 llvm::ConstantExpr::getGetElementPtr(DeviceImages->getValueType(),
4082 DeviceImages, Index),
4083 HostEntriesBegin, HostEntriesEnd};
Alexey Bataev18fa2322018-05-02 14:20:50 +00004084 std::string Descriptor = getName({"omp_offloading", "descriptor"});
Mike Ricee1ca7b62018-08-29 15:45:11 +00004085 llvm::GlobalVariable *Desc = createGlobalStruct(
4086 CGM, getTgtBinaryDescriptorQTy(), /*IsConstant=*/true, Data, Descriptor);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004087
4088 // Emit code to register or unregister the descriptor at execution
4089 // startup or closing, respectively.
4090
Alexey Bataev03f270c2018-03-30 18:31:07 +00004091 llvm::Function *UnRegFn;
4092 {
4093 FunctionArgList Args;
4094 ImplicitParamDecl DummyPtr(C, C.VoidPtrTy, ImplicitParamDecl::Other);
4095 Args.push_back(&DummyPtr);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004096
Alexey Bataev03f270c2018-03-30 18:31:07 +00004097 CodeGenFunction CGF(CGM);
4098 // Disable debug info for global (de-)initializer because they are not part
4099 // of some particular construct.
4100 CGF.disableDebugInfo();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004101 const auto &FI =
4102 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
4103 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004104 std::string UnregName = getName({"omp_offloading", "descriptor_unreg"});
4105 UnRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, UnregName, FI);
Alexey Bataev03f270c2018-03-30 18:31:07 +00004106 CGF.StartFunction(GlobalDecl(), C.VoidTy, UnRegFn, FI, Args);
4107 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_unregister_lib),
4108 Desc);
4109 CGF.FinishFunction();
4110 }
4111 llvm::Function *RegFn;
4112 {
4113 CodeGenFunction CGF(CGM);
4114 // Disable debug info for global (de-)initializer because they are not part
4115 // of some particular construct.
4116 CGF.disableDebugInfo();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004117 const auto &FI = CGM.getTypes().arrangeNullaryFunction();
Alexey Bataev03f270c2018-03-30 18:31:07 +00004118 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Sergey Dmitrievbde9cf92018-08-03 20:19:28 +00004119
4120 // Encode offload target triples into the registration function name. It
4121 // will serve as a comdat key for the registration/unregistration code for
4122 // this particular combination of offloading targets.
4123 SmallVector<StringRef, 4U> RegFnNameParts(Devices.size() + 2U);
4124 RegFnNameParts[0] = "omp_offloading";
4125 RegFnNameParts[1] = "descriptor_reg";
4126 llvm::transform(Devices, std::next(RegFnNameParts.begin(), 2),
4127 [](const llvm::Triple &T) -> const std::string& {
4128 return T.getTriple();
4129 });
4130 llvm::sort(std::next(RegFnNameParts.begin(), 2), RegFnNameParts.end());
4131 std::string Descriptor = getName(RegFnNameParts);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004132 RegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, Descriptor, FI);
Alexey Bataev03f270c2018-03-30 18:31:07 +00004133 CGF.StartFunction(GlobalDecl(), C.VoidTy, RegFn, FI, FunctionArgList());
4134 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_lib), Desc);
4135 // Create a variable to drive the registration and unregistration of the
4136 // descriptor, so we can reuse the logic that emits Ctors and Dtors.
4137 ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(),
4138 SourceLocation(), nullptr, C.CharTy,
4139 ImplicitParamDecl::Other);
4140 CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc);
4141 CGF.FinishFunction();
4142 }
George Rokos29d0f002017-05-27 03:03:13 +00004143 if (CGM.supportsCOMDAT()) {
4144 // It is sufficient to call registration function only once, so create a
4145 // COMDAT group for registration/unregistration functions and associated
4146 // data. That would reduce startup time and code size. Registration
4147 // function serves as a COMDAT group key.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004148 llvm::Comdat *ComdatKey = M.getOrInsertComdat(RegFn->getName());
George Rokos29d0f002017-05-27 03:03:13 +00004149 RegFn->setLinkage(llvm::GlobalValue::LinkOnceAnyLinkage);
4150 RegFn->setVisibility(llvm::GlobalValue::HiddenVisibility);
4151 RegFn->setComdat(ComdatKey);
4152 UnRegFn->setComdat(ComdatKey);
4153 DeviceImages->setComdat(ComdatKey);
4154 Desc->setComdat(ComdatKey);
4155 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004156 return RegFn;
4157}
4158
Alexey Bataev03f270c2018-03-30 18:31:07 +00004159void CGOpenMPRuntime::createOffloadEntry(
4160 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags,
4161 llvm::GlobalValue::LinkageTypes Linkage) {
Samuel Antao2de62b02016-02-13 23:35:10 +00004162 StringRef Name = Addr->getName();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004163 llvm::Module &M = CGM.getModule();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004164 llvm::LLVMContext &C = M.getContext();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004165
4166 // Create constant string with the name.
4167 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
4168
Alexey Bataev18fa2322018-05-02 14:20:50 +00004169 std::string StringName = getName({"omp_offloading", "entry_name"});
4170 auto *Str = new llvm::GlobalVariable(
4171 M, StrPtrInit->getType(), /*isConstant=*/true,
4172 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00004173 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004174
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004175 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy),
4176 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy),
4177 llvm::ConstantInt::get(CGM.SizeTy, Size),
4178 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
4179 llvm::ConstantInt::get(CGM.Int32Ty, 0)};
Alexey Bataev18fa2322018-05-02 14:20:50 +00004180 std::string EntryName = getName({"omp_offloading", "entry", ""});
Mike Ricee1ca7b62018-08-29 15:45:11 +00004181 llvm::GlobalVariable *Entry = createGlobalStruct(
4182 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data,
4183 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004184
4185 // The entry has to be created in the section the linker expects it to be.
Sergey Dmitriev4b343fd2019-09-27 20:00:51 +00004186 Entry->setSection("omp_offloading_entries");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004187}
4188
4189void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
4190 // Emit the offloading entries and metadata so that the device codegen side
Samuel Antao4c8035b2016-12-12 18:00:20 +00004191 // can easily figure out what to emit. The produced metadata looks like
4192 // this:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004193 //
4194 // !omp_offload.info = !{!1, ...}
4195 //
4196 // Right now we only generate metadata for function that contain target
4197 // regions.
4198
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00004199 // If we do not have entries, we don't need to do anything.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004200 if (OffloadEntriesInfoManager.empty())
4201 return;
4202
4203 llvm::Module &M = CGM.getModule();
4204 llvm::LLVMContext &C = M.getContext();
Alexey Bataevba643691d2019-10-03 16:20:34 +00004205 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *,
4206 SourceLocation, StringRef>,
4207 16>
Samuel Antaoee8fb302016-01-06 13:42:12 +00004208 OrderedEntries(OffloadEntriesInfoManager.size());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004209 llvm::SmallVector<StringRef, 16> ParentFunctions(
4210 OffloadEntriesInfoManager.size());
Samuel Antaoee8fb302016-01-06 13:42:12 +00004211
Simon Pilgrim2c518802017-03-30 14:13:19 +00004212 // Auxiliary methods to create metadata values and strings.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004213 auto &&GetMDInt = [this](unsigned V) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004214 return llvm::ConstantAsMetadata::get(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004215 llvm::ConstantInt::get(CGM.Int32Ty, V));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004216 };
4217
Alexey Bataev03f270c2018-03-30 18:31:07 +00004218 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); };
4219
4220 // Create the offloading info metadata node.
4221 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004222
4223 // Create function that emits metadata for each target region entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00004224 auto &&TargetRegionMetadataEmitter =
Alexey Bataevba643691d2019-10-03 16:20:34 +00004225 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt,
4226 &GetMDString](
Alexey Bataev03f270c2018-03-30 18:31:07 +00004227 unsigned DeviceID, unsigned FileID, StringRef ParentName,
4228 unsigned Line,
4229 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
4230 // Generate metadata for target regions. Each entry of this metadata
4231 // contains:
4232 // - Entry 0 -> Kind of this type of metadata (0).
4233 // - Entry 1 -> Device ID of the file where the entry was identified.
4234 // - Entry 2 -> File ID of the file where the entry was identified.
4235 // - Entry 3 -> Mangled name of the function where the entry was
4236 // identified.
4237 // - Entry 4 -> Line in the file where the entry was identified.
4238 // - Entry 5 -> Order the entry was created.
4239 // The first element of the metadata node is the kind.
4240 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID),
4241 GetMDInt(FileID), GetMDString(ParentName),
4242 GetMDInt(Line), GetMDInt(E.getOrder())};
Samuel Antaoee8fb302016-01-06 13:42:12 +00004243
Alexey Bataevba643691d2019-10-03 16:20:34 +00004244 SourceLocation Loc;
4245 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(),
4246 E = CGM.getContext().getSourceManager().fileinfo_end();
4247 I != E; ++I) {
4248 if (I->getFirst()->getUniqueID().getDevice() == DeviceID &&
4249 I->getFirst()->getUniqueID().getFile() == FileID) {
4250 Loc = CGM.getContext().getSourceManager().translateFileLineCol(
4251 I->getFirst(), Line, 1);
4252 break;
4253 }
4254 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004255 // Save this entry in the right position of the ordered entries array.
Alexey Bataevba643691d2019-10-03 16:20:34 +00004256 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName);
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004257 ParentFunctions[E.getOrder()] = ParentName;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004258
Alexey Bataev03f270c2018-03-30 18:31:07 +00004259 // Add metadata to the named metadata node.
4260 MD->addOperand(llvm::MDNode::get(C, Ops));
4261 };
Samuel Antaoee8fb302016-01-06 13:42:12 +00004262
4263 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
4264 TargetRegionMetadataEmitter);
4265
Alexey Bataev03f270c2018-03-30 18:31:07 +00004266 // Create function that emits metadata for each device global variable entry;
4267 auto &&DeviceGlobalVarMetadataEmitter =
4268 [&C, &OrderedEntries, &GetMDInt, &GetMDString,
4269 MD](StringRef MangledName,
4270 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar
4271 &E) {
4272 // Generate metadata for global variables. Each entry of this metadata
4273 // contains:
4274 // - Entry 0 -> Kind of this type of metadata (1).
4275 // - Entry 1 -> Mangled name of the variable.
4276 // - Entry 2 -> Declare target kind.
4277 // - Entry 3 -> Order the entry was created.
4278 // The first element of the metadata node is the kind.
4279 llvm::Metadata *Ops[] = {
4280 GetMDInt(E.getKind()), GetMDString(MangledName),
4281 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
4282
4283 // Save this entry in the right position of the ordered entries array.
Alexey Bataevba643691d2019-10-03 16:20:34 +00004284 OrderedEntries[E.getOrder()] =
4285 std::make_tuple(&E, SourceLocation(), MangledName);
Alexey Bataev03f270c2018-03-30 18:31:07 +00004286
4287 // Add metadata to the named metadata node.
4288 MD->addOperand(llvm::MDNode::get(C, Ops));
4289 };
4290
4291 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo(
4292 DeviceGlobalVarMetadataEmitter);
4293
Alexey Bataevba643691d2019-10-03 16:20:34 +00004294 for (const auto &E : OrderedEntries) {
4295 assert(std::get<0>(E) && "All ordered entries must exist!");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004296 if (const auto *CE =
Samuel Antaoee8fb302016-01-06 13:42:12 +00004297 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
Alexey Bataevba643691d2019-10-03 16:20:34 +00004298 std::get<0>(E))) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004299 if (!CE->getID() || !CE->getAddress()) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004300 // Do not blame the entry if the parent funtion is not emitted.
4301 StringRef FnName = ParentFunctions[CE->getOrder()];
4302 if (!CGM.GetGlobalValue(FnName))
4303 continue;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004304 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4305 DiagnosticsEngine::Error,
Alexey Bataevba643691d2019-10-03 16:20:34 +00004306 "Offloading entry for target region in %0 is incorrect: either the "
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004307 "address or the ID is invalid.");
Alexey Bataevba643691d2019-10-03 16:20:34 +00004308 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004309 continue;
4310 }
Alexey Bataev34f8a702018-03-28 14:28:54 +00004311 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004312 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage);
Alexey Bataevba643691d2019-10-03 16:20:34 +00004313 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy::
4314 OffloadEntryInfoDeviceGlobalVar>(
4315 std::get<0>(E))) {
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004316 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags =
4317 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4318 CE->getFlags());
4319 switch (Flags) {
4320 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00004321 if (CGM.getLangOpts().OpenMPIsDevice &&
4322 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())
4323 continue;
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004324 if (!CE->getAddress()) {
4325 unsigned DiagID = CGM.getDiags().getCustomDiagID(
Alexey Bataevba643691d2019-10-03 16:20:34 +00004326 DiagnosticsEngine::Error, "Offloading entry for declare target "
4327 "variable %0 is incorrect: the "
4328 "address is invalid.");
4329 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E);
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004330 continue;
4331 }
Alexey Bataevb4dd6d22018-08-29 20:41:37 +00004332 // The vaiable has no definition - no need to add the entry.
4333 if (CE->getVarSize().isZero())
4334 continue;
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004335 break;
4336 }
4337 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink:
4338 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) ||
4339 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) &&
4340 "Declaret target link address is set.");
4341 if (CGM.getLangOpts().OpenMPIsDevice)
4342 continue;
4343 if (!CE->getAddress()) {
4344 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4345 DiagnosticsEngine::Error,
4346 "Offloading entry for declare target variable is incorrect: the "
4347 "address is invalid.");
4348 CGM.getDiags().Report(DiagID);
4349 continue;
4350 }
4351 break;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004352 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004353 createOffloadEntry(CE->getAddress(), CE->getAddress(),
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004354 CE->getVarSize().getQuantity(), Flags,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004355 CE->getLinkage());
4356 } else {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004357 llvm_unreachable("Unsupported entry kind.");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004358 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004359 }
4360}
4361
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004362/// Loads all the offload entries information from the host IR
Samuel Antaoee8fb302016-01-06 13:42:12 +00004363/// metadata.
4364void CGOpenMPRuntime::loadOffloadInfoMetadata() {
4365 // If we are in target mode, load the metadata from the host IR. This code has
4366 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
4367
4368 if (!CGM.getLangOpts().OpenMPIsDevice)
4369 return;
4370
4371 if (CGM.getLangOpts().OMPHostIRFile.empty())
4372 return;
4373
4374 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004375 if (auto EC = Buf.getError()) {
4376 CGM.getDiags().Report(diag::err_cannot_open_file)
4377 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004378 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004379 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004380
4381 llvm::LLVMContext C;
Peter Collingbourned9445c42016-11-13 07:00:17 +00004382 auto ME = expectedToErrorOrAndEmitErrors(
4383 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004384
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004385 if (auto EC = ME.getError()) {
4386 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4387 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'");
4388 CGM.getDiags().Report(DiagID)
4389 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004390 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004391 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004392
4393 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
4394 if (!MD)
4395 return;
4396
George Burgess IV00f70bd2018-03-01 05:43:23 +00004397 for (llvm::MDNode *MN : MD->operands()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004398 auto &&GetMDInt = [MN](unsigned Idx) {
4399 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004400 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
4401 };
4402
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004403 auto &&GetMDString = [MN](unsigned Idx) {
4404 auto *V = cast<llvm::MDString>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004405 return V->getString();
4406 };
4407
Alexey Bataev03f270c2018-03-30 18:31:07 +00004408 switch (GetMDInt(0)) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004409 default:
4410 llvm_unreachable("Unexpected metadata!");
4411 break;
4412 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
Alexey Bataev34f8a702018-03-28 14:28:54 +00004413 OffloadingEntryInfoTargetRegion:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004414 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
Alexey Bataev03f270c2018-03-30 18:31:07 +00004415 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2),
4416 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4),
4417 /*Order=*/GetMDInt(5));
4418 break;
4419 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
4420 OffloadingEntryInfoDeviceGlobalVar:
4421 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo(
4422 /*MangledName=*/GetMDString(1),
4423 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4424 /*Flags=*/GetMDInt(2)),
4425 /*Order=*/GetMDInt(3));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004426 break;
4427 }
4428 }
4429}
4430
Alexey Bataev62b63b12015-03-10 07:28:44 +00004431void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
4432 if (!KmpRoutineEntryPtrTy) {
4433 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004434 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004435 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
4436 FunctionProtoType::ExtProtoInfo EPI;
4437 KmpRoutineEntryPtrQTy = C.getPointerType(
4438 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
4439 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
4440 }
4441}
4442
Samuel Antaoee8fb302016-01-06 13:42:12 +00004443QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004444 // Make sure the type of the entry is already created. This is the type we
4445 // have to create:
4446 // struct __tgt_offload_entry{
4447 // void *addr; // Pointer to the offload entry info.
4448 // // (function or global)
4449 // char *name; // Name of the function or global.
4450 // size_t size; // Size of the entry info (0 if it a function).
Samuel Antaof83efdb2017-01-05 16:02:49 +00004451 // int32_t flags; // Flags associated with the entry, e.g. 'link'.
4452 // int32_t reserved; // Reserved, to use by the runtime library.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004453 // };
4454 if (TgtOffloadEntryQTy.isNull()) {
4455 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004456 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004457 RD->startDefinition();
4458 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4459 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
4460 addFieldToRecordDecl(C, RD, C.getSizeType());
Samuel Antaof83efdb2017-01-05 16:02:49 +00004461 addFieldToRecordDecl(
4462 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4463 addFieldToRecordDecl(
4464 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004465 RD->completeDefinition();
Jonas Hahnfeld5e4df282018-01-18 15:38:03 +00004466 RD->addAttr(PackedAttr::CreateImplicit(C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004467 TgtOffloadEntryQTy = C.getRecordType(RD);
4468 }
4469 return TgtOffloadEntryQTy;
4470}
4471
4472QualType CGOpenMPRuntime::getTgtDeviceImageQTy() {
4473 // These are the types we need to build:
4474 // struct __tgt_device_image{
4475 // void *ImageStart; // Pointer to the target code start.
4476 // void *ImageEnd; // Pointer to the target code end.
4477 // // We also add the host entries to the device image, as it may be useful
4478 // // for the target runtime to have access to that information.
4479 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all
4480 // // the entries.
4481 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
4482 // // entries (non inclusive).
4483 // };
4484 if (TgtDeviceImageQTy.isNull()) {
4485 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004486 RecordDecl *RD = C.buildImplicitRecord("__tgt_device_image");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004487 RD->startDefinition();
4488 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4489 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4490 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4491 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4492 RD->completeDefinition();
4493 TgtDeviceImageQTy = C.getRecordType(RD);
4494 }
4495 return TgtDeviceImageQTy;
4496}
4497
4498QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() {
4499 // struct __tgt_bin_desc{
4500 // int32_t NumDevices; // Number of devices supported.
4501 // __tgt_device_image *DeviceImages; // Arrays of device images
4502 // // (one per device).
4503 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the
4504 // // entries.
4505 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
4506 // // entries (non inclusive).
4507 // };
4508 if (TgtBinaryDescriptorQTy.isNull()) {
4509 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004510 RecordDecl *RD = C.buildImplicitRecord("__tgt_bin_desc");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004511 RD->startDefinition();
4512 addFieldToRecordDecl(
4513 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4514 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy()));
4515 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4516 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4517 RD->completeDefinition();
4518 TgtBinaryDescriptorQTy = C.getRecordType(RD);
4519 }
4520 return TgtBinaryDescriptorQTy;
4521}
4522
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004523namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00004524struct PrivateHelpersTy {
4525 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
4526 const VarDecl *PrivateElemInit)
4527 : Original(Original), PrivateCopy(PrivateCopy),
4528 PrivateElemInit(PrivateElemInit) {}
4529 const VarDecl *Original;
4530 const VarDecl *PrivateCopy;
4531 const VarDecl *PrivateElemInit;
4532};
4533typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Hans Wennborg7eb54642015-09-10 17:07:54 +00004534} // anonymous namespace
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004535
Alexey Bataev9e034042015-05-05 04:05:12 +00004536static RecordDecl *
Craig Topper8674c5c2015-09-29 04:30:07 +00004537createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004538 if (!Privates.empty()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004539 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004540 // Build struct .kmp_privates_t. {
4541 // /* private vars */
4542 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004543 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t");
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004544 RD->startDefinition();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004545 for (const auto &Pair : Privates) {
4546 const VarDecl *VD = Pair.second.Original;
4547 QualType Type = VD->getType().getNonReferenceType();
4548 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type);
Alexey Bataevc71a4092015-09-11 10:29:41 +00004549 if (VD->hasAttrs()) {
4550 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
4551 E(VD->getAttrs().end());
4552 I != E; ++I)
4553 FD->addAttr(*I);
4554 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004555 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004556 RD->completeDefinition();
4557 return RD;
4558 }
4559 return nullptr;
4560}
4561
Alexey Bataev9e034042015-05-05 04:05:12 +00004562static RecordDecl *
Alexey Bataev7292c292016-04-25 12:22:29 +00004563createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind,
4564 QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004565 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004566 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004567 // Build struct kmp_task_t {
4568 // void * shareds;
4569 // kmp_routine_entry_t routine;
4570 // kmp_int32 part_id;
Alexey Bataevad537bb2016-05-30 09:06:50 +00004571 // kmp_cmplrdata_t data1;
4572 // kmp_cmplrdata_t data2;
Alexey Bataev7292c292016-04-25 12:22:29 +00004573 // For taskloops additional fields:
4574 // kmp_uint64 lb;
4575 // kmp_uint64 ub;
4576 // kmp_int64 st;
4577 // kmp_int32 liter;
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004578 // void * reductions;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004579 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004580 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004581 UD->startDefinition();
4582 addFieldToRecordDecl(C, UD, KmpInt32Ty);
4583 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy);
4584 UD->completeDefinition();
4585 QualType KmpCmplrdataTy = C.getRecordType(UD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004586 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t");
Alexey Bataev62b63b12015-03-10 07:28:44 +00004587 RD->startDefinition();
4588 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4589 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
4590 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004591 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
4592 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004593 if (isOpenMPTaskLoopDirective(Kind)) {
4594 QualType KmpUInt64Ty =
4595 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
4596 QualType KmpInt64Ty =
4597 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
4598 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4599 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4600 addFieldToRecordDecl(C, RD, KmpInt64Ty);
4601 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004602 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004603 }
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004604 RD->completeDefinition();
4605 return RD;
4606}
4607
4608static RecordDecl *
4609createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004610 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004611 ASTContext &C = CGM.getContext();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004612 // Build struct kmp_task_t_with_privates {
4613 // kmp_task_t task_data;
4614 // .kmp_privates_t. privates;
4615 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004616 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004617 RD->startDefinition();
4618 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004619 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates))
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004620 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004621 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004622 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004623}
4624
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004625/// Emit a proxy function which accepts kmp_task_t as the second
Alexey Bataev62b63b12015-03-10 07:28:44 +00004626/// argument.
4627/// \code
4628/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00004629/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt,
Alexey Bataev7292c292016-04-25 12:22:29 +00004630/// For taskloops:
4631/// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004632/// tt->reductions, tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004633/// return 0;
4634/// }
4635/// \endcode
James Y Knight9871db02019-02-05 16:42:33 +00004636static llvm::Function *
Alexey Bataev62b63b12015-03-10 07:28:44 +00004637emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev7292c292016-04-25 12:22:29 +00004638 OpenMPDirectiveKind Kind, QualType KmpInt32Ty,
4639 QualType KmpTaskTWithPrivatesPtrQTy,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004640 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
James Y Knight9871db02019-02-05 16:42:33 +00004641 QualType SharedsPtrTy, llvm::Function *TaskFunction,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004642 llvm::Value *TaskPrivatesMap) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004643 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004644 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004645 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4646 ImplicitParamDecl::Other);
4647 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4648 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4649 ImplicitParamDecl::Other);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004650 Args.push_back(&GtidArg);
4651 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004652 const auto &TaskEntryFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004653 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004654 llvm::FunctionType *TaskEntryTy =
4655 CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004656 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""});
4657 auto *TaskEntry = llvm::Function::Create(
4658 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004659 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004660 TaskEntry->setDoesNotRecurse();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004661 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004662 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args,
4663 Loc, Loc);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004664
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004665 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
Alexey Bataev7292c292016-04-25 12:22:29 +00004666 // tt,
4667 // For taskloops:
4668 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
4669 // tt->task_data.shareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004670 llvm::Value *GtidParam = CGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00004671 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
Alexey Bataev31300ed2016-02-04 11:27:03 +00004672 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4673 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4674 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004675 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004676 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004677 LValue Base =
4678 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004679 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004680 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004681 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
4682 llvm::Value *PartidParam = PartIdLVal.getPointer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004683
4684 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004685 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
4686 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev1e491372018-01-23 18:44:14 +00004687 CGF.EmitLoadOfScalar(SharedsLVal, Loc),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004688 CGF.ConvertTypeForMem(SharedsPtrTy));
4689
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004690 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4691 llvm::Value *PrivatesParam;
4692 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004693 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004694 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00004695 PrivatesLVal.getPointer(), CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004696 } else {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004697 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004698 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004699
Alexey Bataev7292c292016-04-25 12:22:29 +00004700 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam,
4701 TaskPrivatesMap,
4702 CGF.Builder
4703 .CreatePointerBitCastOrAddrSpaceCast(
4704 TDBase.getAddress(), CGF.VoidPtrTy)
4705 .getPointer()};
4706 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs),
4707 std::end(CommonArgs));
4708 if (isOpenMPTaskLoopDirective(Kind)) {
4709 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004710 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI);
4711 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004712 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004713 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI);
4714 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004715 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004716 LValue StLVal = CGF.EmitLValueForField(Base, *StFI);
4717 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004718 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004719 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4720 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004721 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004722 LValue RLVal = CGF.EmitLValueForField(Base, *RFI);
4723 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004724 CallArgs.push_back(LBParam);
4725 CallArgs.push_back(UBParam);
4726 CallArgs.push_back(StParam);
4727 CallArgs.push_back(LIParam);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004728 CallArgs.push_back(RParam);
Alexey Bataev7292c292016-04-25 12:22:29 +00004729 }
4730 CallArgs.push_back(SharedsParam);
4731
Alexey Bataev3c595a62017-08-14 15:01:03 +00004732 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction,
4733 CallArgs);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004734 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)),
4735 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004736 CGF.FinishFunction();
4737 return TaskEntry;
4738}
4739
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004740static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
4741 SourceLocation Loc,
4742 QualType KmpInt32Ty,
4743 QualType KmpTaskTWithPrivatesPtrQTy,
4744 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004745 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004746 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004747 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4748 ImplicitParamDecl::Other);
4749 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4750 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4751 ImplicitParamDecl::Other);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004752 Args.push_back(&GtidArg);
4753 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004754 const auto &DestructorFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004755 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004756 llvm::FunctionType *DestructorFnTy =
4757 CGM.getTypes().GetFunctionType(DestructorFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004758 std::string Name =
4759 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""});
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004760 auto *DestructorFn =
4761 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00004762 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004763 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004764 DestructorFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004765 DestructorFn->setDoesNotRecurse();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004766 CodeGenFunction CGF(CGM);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004767 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004768 Args, Loc, Loc);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004769
Alexey Bataev31300ed2016-02-04 11:27:03 +00004770 LValue Base = CGF.EmitLoadOfPointerLValue(
4771 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4772 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004773 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004774 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
4775 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004776 Base = CGF.EmitLValueForField(Base, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004777 for (const auto *Field :
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004778 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004779 if (QualType::DestructionKind DtorKind =
4780 Field->getType().isDestructedType()) {
4781 LValue FieldLValue = CGF.EmitLValueForField(Base, Field);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004782 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
4783 }
4784 }
4785 CGF.FinishFunction();
4786 return DestructorFn;
4787}
4788
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004789/// Emit a privates mapping function for correct handling of private and
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004790/// firstprivate variables.
4791/// \code
4792/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
4793/// **noalias priv1,..., <tyn> **noalias privn) {
4794/// *priv1 = &.privates.priv1;
4795/// ...;
4796/// *privn = &.privates.privn;
4797/// }
4798/// \endcode
4799static llvm::Value *
4800emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Craig Topper8674c5c2015-09-29 04:30:07 +00004801 ArrayRef<const Expr *> PrivateVars,
4802 ArrayRef<const Expr *> FirstprivateVars,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004803 ArrayRef<const Expr *> LastprivateVars,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004804 QualType PrivatesQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004805 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004806 ASTContext &C = CGM.getContext();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004807 FunctionArgList Args;
4808 ImplicitParamDecl TaskPrivatesArg(
4809 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
Alexey Bataev56223232017-06-09 13:40:18 +00004810 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
4811 ImplicitParamDecl::Other);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004812 Args.push_back(&TaskPrivatesArg);
4813 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
4814 unsigned Counter = 1;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004815 for (const Expr *E : PrivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004816 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004817 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4818 C.getPointerType(C.getPointerType(E->getType()))
4819 .withConst()
4820 .withRestrict(),
4821 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004822 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004823 PrivateVarsPos[VD] = Counter;
4824 ++Counter;
4825 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004826 for (const Expr *E : FirstprivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004827 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004828 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4829 C.getPointerType(C.getPointerType(E->getType()))
4830 .withConst()
4831 .withRestrict(),
4832 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004833 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004834 PrivateVarsPos[VD] = Counter;
4835 ++Counter;
4836 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004837 for (const Expr *E : LastprivateVars) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004838 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004839 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4840 C.getPointerType(C.getPointerType(E->getType()))
4841 .withConst()
4842 .withRestrict(),
4843 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004844 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataevf93095a2016-05-05 08:46:22 +00004845 PrivateVarsPos[VD] = Counter;
4846 ++Counter;
4847 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004848 const auto &TaskPrivatesMapFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004849 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004850 llvm::FunctionType *TaskPrivatesMapTy =
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004851 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004852 std::string Name =
4853 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""});
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004854 auto *TaskPrivatesMap = llvm::Function::Create(
Alexey Bataev18fa2322018-05-02 14:20:50 +00004855 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
4856 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004857 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004858 TaskPrivatesMapFnInfo);
Alexey Bataev8c5555c2019-05-21 15:11:58 +00004859 if (CGM.getLangOpts().Optimize) {
4860 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
4861 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
4862 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
4863 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004864 CodeGenFunction CGF(CGM);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004865 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004866 TaskPrivatesMapFnInfo, Args, Loc, Loc);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004867
4868 // *privi = &.privates.privi;
Alexey Bataev31300ed2016-02-04 11:27:03 +00004869 LValue Base = CGF.EmitLoadOfPointerLValue(
4870 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
4871 TaskPrivatesArg.getType()->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004872 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004873 Counter = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004874 for (const FieldDecl *Field : PrivatesQTyRD->fields()) {
4875 LValue FieldLVal = CGF.EmitLValueForField(Base, Field);
4876 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
4877 LValue RefLVal =
4878 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
4879 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue(
Alexey Bataev31300ed2016-02-04 11:27:03 +00004880 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>());
Alexey Bataev2377fe92015-09-10 08:12:02 +00004881 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004882 ++Counter;
4883 }
4884 CGF.FinishFunction();
4885 return TaskPrivatesMap;
4886}
4887
Alexey Bataevf93095a2016-05-05 08:46:22 +00004888/// Emit initialization for private variables in task-based directives.
Alexey Bataev8a831592016-05-10 10:36:51 +00004889static void emitPrivatesInit(CodeGenFunction &CGF,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004890 const OMPExecutableDirective &D,
4891 Address KmpTaskSharedsPtr, LValue TDBase,
4892 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4893 QualType SharedsTy, QualType SharedsPtrTy,
4894 const OMPTaskDataTy &Data,
4895 ArrayRef<PrivateDataTy> Privates, bool ForDup) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004896 ASTContext &C = CGF.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004897 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
4898 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004899 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind())
4900 ? OMPD_taskloop
4901 : OMPD_task;
4902 const CapturedStmt &CS = *D.getCapturedStmt(Kind);
4903 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004904 LValue SrcBase;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004905 bool IsTargetTask =
4906 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) ||
4907 isOpenMPTargetExecutionDirective(D.getDirectiveKind());
4908 // For target-based directives skip 3 firstprivate arrays BasePointersArray,
4909 // PointersArray and SizesArray. The original variables for these arrays are
4910 // not captured and we get their addresses explicitly.
4911 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) ||
Alexey Bataev8451efa2018-01-15 19:06:12 +00004912 (IsTargetTask && KmpTaskSharedsPtr.isValid())) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004913 SrcBase = CGF.MakeAddrLValue(
4914 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4915 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
4916 SharedsTy);
4917 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004918 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004919 for (const PrivateDataTy &Pair : Privates) {
4920 const VarDecl *VD = Pair.second.PrivateCopy;
4921 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004922 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) &&
4923 !CGF.isTrivialInitializer(Init)))) {
Alexey Bataev8a831592016-05-10 10:36:51 +00004924 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004925 if (const VarDecl *Elem = Pair.second.PrivateElemInit) {
4926 const VarDecl *OriginalVD = Pair.second.Original;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004927 // Check if the variable is the target-based BasePointersArray,
4928 // PointersArray or SizesArray.
4929 LValue SharedRefLValue;
Alexey Bataevab41ea62019-03-13 20:46:28 +00004930 QualType Type = PrivateLValue.getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004931 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004932 if (IsTargetTask && !SharedField) {
4933 assert(isa<ImplicitParamDecl>(OriginalVD) &&
4934 isa<CapturedDecl>(OriginalVD->getDeclContext()) &&
4935 cast<CapturedDecl>(OriginalVD->getDeclContext())
4936 ->getNumParams() == 0 &&
4937 isa<TranslationUnitDecl>(
4938 cast<CapturedDecl>(OriginalVD->getDeclContext())
4939 ->getDeclContext()) &&
4940 "Expected artificial target data variable.");
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004941 SharedRefLValue =
4942 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type);
4943 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004944 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField);
4945 SharedRefLValue = CGF.MakeAddrLValue(
4946 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
4947 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl),
4948 SharedRefLValue.getTBAAInfo());
4949 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004950 if (Type->isArrayType()) {
4951 // Initialize firstprivate array.
4952 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) {
4953 // Perform simple memcpy.
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00004954 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004955 } else {
4956 // Initialize firstprivate array using element-by-element
Simon Pilgrim2c518802017-03-30 14:13:19 +00004957 // initialization.
Alexey Bataevf93095a2016-05-05 08:46:22 +00004958 CGF.EmitOMPAggregateAssign(
4959 PrivateLValue.getAddress(), SharedRefLValue.getAddress(), Type,
4960 [&CGF, Elem, Init, &CapturesInfo](Address DestElement,
4961 Address SrcElement) {
4962 // Clean up any temporaries needed by the initialization.
4963 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4964 InitScope.addPrivate(
4965 Elem, [SrcElement]() -> Address { return SrcElement; });
4966 (void)InitScope.Privatize();
4967 // Emit initialization for single element.
4968 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
4969 CGF, &CapturesInfo);
4970 CGF.EmitAnyExprToMem(Init, DestElement,
4971 Init->getType().getQualifiers(),
4972 /*IsInitializer=*/false);
4973 });
4974 }
4975 } else {
4976 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4977 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
4978 return SharedRefLValue.getAddress();
4979 });
4980 (void)InitScope.Privatize();
4981 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
4982 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
4983 /*capturedByInit=*/false);
4984 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004985 } else {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004986 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004987 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004988 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004989 ++FI;
4990 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004991}
4992
4993/// Check if duplication function is required for taskloops.
4994static bool checkInitIsRequired(CodeGenFunction &CGF,
4995 ArrayRef<PrivateDataTy> Privates) {
4996 bool InitRequired = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004997 for (const PrivateDataTy &Pair : Privates) {
4998 const VarDecl *VD = Pair.second.PrivateCopy;
4999 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00005000 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) &&
5001 !CGF.isTrivialInitializer(Init));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005002 if (InitRequired)
5003 break;
Alexey Bataevf93095a2016-05-05 08:46:22 +00005004 }
5005 return InitRequired;
5006}
5007
5008
5009/// Emit task_dup function (for initialization of
5010/// private/firstprivate/lastprivate vars and last_iter flag)
5011/// \code
5012/// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int
5013/// lastpriv) {
5014/// // setup lastprivate flag
5015/// task_dst->last = lastpriv;
5016/// // could be constructor calls here...
5017/// }
5018/// \endcode
5019static llvm::Value *
5020emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
5021 const OMPExecutableDirective &D,
5022 QualType KmpTaskTWithPrivatesPtrQTy,
5023 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
5024 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy,
5025 QualType SharedsPtrTy, const OMPTaskDataTy &Data,
5026 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005027 ASTContext &C = CGM.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00005028 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00005029 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
5030 KmpTaskTWithPrivatesPtrQTy,
5031 ImplicitParamDecl::Other);
5032 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
5033 KmpTaskTWithPrivatesPtrQTy,
5034 ImplicitParamDecl::Other);
5035 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy,
5036 ImplicitParamDecl::Other);
Alexey Bataevf93095a2016-05-05 08:46:22 +00005037 Args.push_back(&DstArg);
5038 Args.push_back(&SrcArg);
5039 Args.push_back(&LastprivArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005040 const auto &TaskDupFnInfo =
Alexey Bataevf93095a2016-05-05 08:46:22 +00005041 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005042 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00005043 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""});
5044 auto *TaskDup = llvm::Function::Create(
5045 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00005046 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00005047 TaskDup->setDoesNotRecurse();
Alexey Bataevf93095a2016-05-05 08:46:22 +00005048 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005049 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc,
5050 Loc);
Alexey Bataevf93095a2016-05-05 08:46:22 +00005051
5052 LValue TDBase = CGF.EmitLoadOfPointerLValue(
5053 CGF.GetAddrOfLocalVar(&DstArg),
5054 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
5055 // task_dst->liter = lastpriv;
5056 if (WithLastIter) {
5057 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
5058 LValue Base = CGF.EmitLValueForField(
5059 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
5060 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
5061 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar(
5062 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc);
5063 CGF.EmitStoreOfScalar(Lastpriv, LILVal);
5064 }
5065
5066 // Emit initial values for private copies (if any).
5067 assert(!Privates.empty());
5068 Address KmpTaskSharedsPtr = Address::invalid();
5069 if (!Data.FirstprivateVars.empty()) {
5070 LValue TDBase = CGF.EmitLoadOfPointerLValue(
5071 CGF.GetAddrOfLocalVar(&SrcArg),
5072 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
5073 LValue Base = CGF.EmitLValueForField(
5074 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
5075 KmpTaskSharedsPtr = Address(
5076 CGF.EmitLoadOfScalar(CGF.EmitLValueForField(
5077 Base, *std::next(KmpTaskTQTyRD->field_begin(),
5078 KmpTaskTShareds)),
5079 Loc),
5080 CGF.getNaturalTypeAlignment(SharedsTy));
5081 }
Alexey Bataev8a831592016-05-10 10:36:51 +00005082 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
5083 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true);
Alexey Bataevf93095a2016-05-05 08:46:22 +00005084 CGF.FinishFunction();
5085 return TaskDup;
5086}
5087
Alexey Bataev8a831592016-05-10 10:36:51 +00005088/// Checks if destructor function is required to be generated.
5089/// \return true if cleanups are required, false otherwise.
5090static bool
5091checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) {
5092 bool NeedsCleanup = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005093 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
5094 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl());
5095 for (const FieldDecl *FD : PrivateRD->fields()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00005096 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType();
5097 if (NeedsCleanup)
5098 break;
5099 }
5100 return NeedsCleanup;
5101}
5102
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005103CGOpenMPRuntime::TaskResultTy
5104CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
5105 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005106 llvm::Function *TaskFunction, QualType SharedsTy,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005107 Address Shareds, const OMPTaskDataTy &Data) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005108 ASTContext &C = CGM.getContext();
Alexey Bataev7292c292016-04-25 12:22:29 +00005109 llvm::SmallVector<PrivateDataTy, 4> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005110 // Aggregate privates and sort them by the alignment.
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005111 auto I = Data.PrivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005112 for (const Expr *E : Data.PrivateVars) {
5113 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00005114 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00005115 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00005116 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00005117 /*PrivateElemInit=*/nullptr));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005118 ++I;
5119 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005120 I = Data.FirstprivateCopies.begin();
5121 auto IElemInitRef = Data.FirstprivateInits.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005122 for (const Expr *E : Data.FirstprivateVars) {
5123 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00005124 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00005125 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00005126 PrivateHelpersTy(
5127 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00005128 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())));
Richard Trieucc3949d2016-02-18 22:34:54 +00005129 ++I;
5130 ++IElemInitRef;
Alexey Bataev9e034042015-05-05 04:05:12 +00005131 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00005132 I = Data.LastprivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005133 for (const Expr *E : Data.LastprivateVars) {
5134 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00005135 Privates.emplace_back(
Alexey Bataevf93095a2016-05-05 08:46:22 +00005136 C.getDeclAlign(VD),
5137 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00005138 /*PrivateElemInit=*/nullptr));
Alexey Bataevf93095a2016-05-05 08:46:22 +00005139 ++I;
5140 }
Fangrui Song899d1392019-04-24 14:43:05 +00005141 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) {
5142 return L.first > R.first;
5143 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005144 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005145 // Build type kmp_routine_entry_t (if not built yet).
5146 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005147 // Build type kmp_task_t (if not built yet).
Alexey Bataeve213f3e2017-10-11 15:29:40 +00005148 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) {
5149 if (SavedKmpTaskloopTQTy.isNull()) {
5150 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5151 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5152 }
5153 KmpTaskTQTy = SavedKmpTaskloopTQTy;
Alexey Bataev3a03a7f2017-10-11 15:56:38 +00005154 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00005155 assert((D.getDirectiveKind() == OMPD_task ||
5156 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) ||
5157 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) &&
5158 "Expected taskloop, task or target directive");
Alexey Bataeve213f3e2017-10-11 15:29:40 +00005159 if (SavedKmpTaskTQTy.isNull()) {
5160 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl(
5161 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
5162 }
5163 KmpTaskTQTy = SavedKmpTaskTQTy;
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005164 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005165 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005166 // Build particular struct kmp_task_t for the given task.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005167 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005168 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005169 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005170 QualType KmpTaskTWithPrivatesPtrQTy =
5171 C.getPointerType(KmpTaskTWithPrivatesQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005172 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
5173 llvm::Type *KmpTaskTWithPrivatesPtrTy =
5174 KmpTaskTWithPrivatesTy->getPointerTo();
5175 llvm::Value *KmpTaskTWithPrivatesTySize =
5176 CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005177 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
5178
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005179 // Emit initial values for private copies (if any).
5180 llvm::Value *TaskPrivatesMap = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005181 llvm::Type *TaskPrivatesMapTy =
James Y Knight9871db02019-02-05 16:42:33 +00005182 std::next(TaskFunction->arg_begin(), 3)->getType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005183 if (!Privates.empty()) {
5184 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataevf93095a2016-05-05 08:46:22 +00005185 TaskPrivatesMap = emitTaskPrivateMappingFunction(
5186 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars,
5187 FI->getType(), Privates);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005188 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5189 TaskPrivatesMap, TaskPrivatesMapTy);
5190 } else {
5191 TaskPrivatesMap = llvm::ConstantPointerNull::get(
5192 cast<llvm::PointerType>(TaskPrivatesMapTy));
5193 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005194 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
5195 // kmp_task_t *tt);
James Y Knight9871db02019-02-05 16:42:33 +00005196 llvm::Function *TaskEntry = emitProxyTaskFunction(
Alexey Bataev7292c292016-04-25 12:22:29 +00005197 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5198 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction,
5199 TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005200
5201 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
5202 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
5203 // kmp_routine_entry_t *task_entry);
5204 // Task flags. Format is taken from
James Y Knight5d71fc52019-01-29 16:37:27 +00005205 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h,
Alexey Bataev62b63b12015-03-10 07:28:44 +00005206 // description of kmp_tasking_flags struct.
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005207 enum {
5208 TiedFlag = 0x1,
5209 FinalFlag = 0x2,
5210 DestructorsFlag = 0x8,
5211 PriorityFlag = 0x20
5212 };
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005213 unsigned Flags = Data.Tied ? TiedFlag : 0;
Alexey Bataev8a831592016-05-10 10:36:51 +00005214 bool NeedsCleanup = false;
5215 if (!Privates.empty()) {
5216 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD);
5217 if (NeedsCleanup)
5218 Flags = Flags | DestructorsFlag;
5219 }
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005220 if (Data.Priority.getInt())
5221 Flags = Flags | PriorityFlag;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005222 llvm::Value *TaskFlags =
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005223 Data.Final.getPointer()
5224 ? CGF.Builder.CreateSelect(Data.Final.getPointer(),
Alexey Bataev62b63b12015-03-10 07:28:44 +00005225 CGF.Builder.getInt32(FinalFlag),
5226 CGF.Builder.getInt32(/*C=*/0))
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005227 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005228 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005229 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00005230 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc),
5231 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize,
5232 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5233 TaskEntry, KmpRoutineEntryPtrTy)};
5234 llvm::Value *NewTask;
5235 if (D.hasClausesOfKind<OMPNowaitClause>()) {
5236 // Check if we have any device clause associated with the directive.
5237 const Expr *Device = nullptr;
5238 if (auto *C = D.getSingleClause<OMPDeviceClause>())
5239 Device = C->getDevice();
5240 // Emit device ID if any otherwise use default value.
5241 llvm::Value *DeviceID;
5242 if (Device)
5243 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
5244 CGF.Int64Ty, /*isSigned=*/true);
5245 else
5246 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
5247 AllocArgs.push_back(DeviceID);
5248 NewTask = CGF.EmitRuntimeCall(
5249 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs);
5250 } else {
5251 NewTask = CGF.EmitRuntimeCall(
Alexey Bataev62b63b12015-03-10 07:28:44 +00005252 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Gheorghe-Teodor Bercea545a9fe2019-06-14 20:19:54 +00005253 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005254 llvm::Value *NewTaskNewTaskTTy =
5255 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5256 NewTask, KmpTaskTWithPrivatesPtrTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005257 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
5258 KmpTaskTWithPrivatesQTy);
5259 LValue TDBase =
5260 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005261 // Fill the data in the resulting kmp_task_t record.
5262 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00005263 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005264 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00005265 KmpTaskSharedsPtr =
5266 Address(CGF.EmitLoadOfScalar(
5267 CGF.EmitLValueForField(
5268 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
5269 KmpTaskTShareds)),
5270 Loc),
5271 CGF.getNaturalTypeAlignment(SharedsTy));
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00005272 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy);
5273 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy);
Richard Smithe78fac52018-04-05 20:52:58 +00005274 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005275 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005276 // Emit initial values for private copies (if any).
Alexey Bataevf93095a2016-05-05 08:46:22 +00005277 TaskResultTy Result;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005278 if (!Privates.empty()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00005279 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD,
5280 SharedsTy, SharedsPtrTy, Data, Privates,
5281 /*ForDup=*/false);
Alexey Bataevf93095a2016-05-05 08:46:22 +00005282 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
5283 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) {
5284 Result.TaskDupFn = emitTaskDupFunction(
5285 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
5286 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates,
5287 /*WithLastIter=*/!Data.LastprivateVars.empty());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005288 }
5289 }
Alexey Bataevad537bb2016-05-30 09:06:50 +00005290 // Fields of union "kmp_cmplrdata_t" for destructors and priority.
5291 enum { Priority = 0, Destructors = 1 };
Alexey Bataev62b63b12015-03-10 07:28:44 +00005292 // Provide pointer to function with destructors for privates.
Alexey Bataevad537bb2016-05-30 09:06:50 +00005293 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005294 const RecordDecl *KmpCmplrdataUD =
5295 (*FI)->getType()->getAsUnionType()->getDecl();
Alexey Bataevad537bb2016-05-30 09:06:50 +00005296 if (NeedsCleanup) {
5297 llvm::Value *DestructorFn = emitDestructorsFunction(
5298 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5299 KmpTaskTWithPrivatesQTy);
5300 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI);
5301 LValue DestructorsLV = CGF.EmitLValueForField(
5302 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
5303 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5304 DestructorFn, KmpRoutineEntryPtrTy),
5305 DestructorsLV);
5306 }
5307 // Set priority.
5308 if (Data.Priority.getInt()) {
5309 LValue Data2LV = CGF.EmitLValueForField(
5310 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
5311 LValue PriorityLV = CGF.EmitLValueForField(
5312 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
5313 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV);
5314 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005315 Result.NewTask = NewTask;
5316 Result.TaskEntry = TaskEntry;
5317 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
5318 Result.TDBase = TDBase;
5319 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
5320 return Result;
Alexey Bataev7292c292016-04-25 12:22:29 +00005321}
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005322
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005323void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
5324 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005325 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005326 QualType SharedsTy, Address Shareds,
5327 const Expr *IfCond,
5328 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005329 if (!CGF.HaveInsertPoint())
5330 return;
5331
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005332 TaskResultTy Result =
5333 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
5334 llvm::Value *NewTask = Result.NewTask;
James Y Knight9871db02019-02-05 16:42:33 +00005335 llvm::Function *TaskEntry = Result.TaskEntry;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005336 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy;
5337 LValue TDBase = Result.TDBase;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005338 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD;
5339 ASTContext &C = CGM.getContext();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005340 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00005341 Address DependenciesArray = Address::invalid();
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005342 unsigned NumDependencies = Data.Dependences.size();
John McCall7f416cc2015-09-08 08:05:57 +00005343 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005344 // Dependence kind for RTL.
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005345 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 };
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005346 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
5347 RecordDecl *KmpDependInfoRD;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005348 QualType FlagsTy =
5349 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005350 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
5351 if (KmpDependInfoTy.isNull()) {
5352 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
5353 KmpDependInfoRD->startDefinition();
5354 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
5355 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
5356 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
5357 KmpDependInfoRD->completeDefinition();
5358 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005359 } else {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005360 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005361 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005362 // Define type kmp_depend_info[<Dependences.size()>];
5363 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00005364 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Richard Smith772e2662019-10-04 01:25:59 +00005365 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005366 // kmp_depend_info[<Dependences.size()>] deps;
Alexey Bataev48591dd2016-04-20 04:01:36 +00005367 DependenciesArray =
5368 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005369 for (unsigned I = 0; I < NumDependencies; ++I) {
5370 const Expr *E = Data.Dependences[I].second;
5371 LValue Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005372 llvm::Value *Size;
5373 QualType Ty = E->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005374 if (const auto *ASE =
5375 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005376 LValue UpAddrLVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00005377 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005378 llvm::Value *UpAddr =
John McCall7f416cc2015-09-08 08:05:57 +00005379 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005380 llvm::Value *LowIntPtr =
John McCall7f416cc2015-09-08 08:05:57 +00005381 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005382 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
5383 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005384 } else {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005385 Size = CGF.getTypeSize(Ty);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005386 }
5387 LValue Base = CGF.MakeAddrLValue(
James Y Knight751fe282019-02-09 22:22:28 +00005388 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005389 KmpDependInfoTy);
5390 // deps[i].base_addr = &<Dependences[i].second>;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005391 LValue BaseAddrLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005392 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00005393 CGF.EmitStoreOfScalar(
5394 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy),
5395 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005396 // deps[i].len = sizeof(<Dependences[i].second>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005397 LValue LenLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005398 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
5399 CGF.EmitStoreOfScalar(Size, LenLVal);
5400 // deps[i].flags = <Dependences[i].first>;
5401 RTLDependenceKindTy DepKind;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005402 switch (Data.Dependences[I].first) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005403 case OMPC_DEPEND_in:
5404 DepKind = DepIn;
5405 break;
Alexey Bataev92e82f92015-11-23 13:33:42 +00005406 // Out and InOut dependencies must use the same code.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005407 case OMPC_DEPEND_out:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005408 case OMPC_DEPEND_inout:
5409 DepKind = DepInOut;
5410 break;
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005411 case OMPC_DEPEND_mutexinoutset:
5412 DepKind = DepMutexInOutSet;
5413 break;
Alexey Bataeveb482352015-12-18 05:05:56 +00005414 case OMPC_DEPEND_source:
Alexey Bataeva636c7f2015-12-23 10:27:45 +00005415 case OMPC_DEPEND_sink:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005416 case OMPC_DEPEND_unknown:
5417 llvm_unreachable("Unknown task dependence type");
5418 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005419 LValue FlagsLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005420 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
5421 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
5422 FlagsLVal);
5423 }
John McCall7f416cc2015-09-08 08:05:57 +00005424 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knightf5f1b0e2019-02-08 15:34:12 +00005425 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005426 }
5427
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005428 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev62b63b12015-03-10 07:28:44 +00005429 // libcall.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005430 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
5431 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
5432 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
5433 // list is not empty
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005434 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5435 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00005436 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
5437 llvm::Value *DepTaskArgs[7];
5438 if (NumDependencies) {
5439 DepTaskArgs[0] = UpLoc;
5440 DepTaskArgs[1] = ThreadID;
5441 DepTaskArgs[2] = NewTask;
5442 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
5443 DepTaskArgs[4] = DependenciesArray.getPointer();
5444 DepTaskArgs[5] = CGF.Builder.getInt32(0);
5445 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5446 }
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005447 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies,
5448 &TaskArgs,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005449 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005450 if (!Data.Tied) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005451 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005452 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
Alexey Bataev48591dd2016-04-20 04:01:36 +00005453 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
5454 }
John McCall7f416cc2015-09-08 08:05:57 +00005455 if (NumDependencies) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005456 CGF.EmitRuntimeCall(
Alexey Bataev48591dd2016-04-20 04:01:36 +00005457 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs);
John McCall7f416cc2015-09-08 08:05:57 +00005458 } else {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005459 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
John McCall7f416cc2015-09-08 08:05:57 +00005460 TaskArgs);
5461 }
Alexey Bataev48591dd2016-04-20 04:01:36 +00005462 // Check if parent region is untied and build return for untied task;
5463 if (auto *Region =
5464 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
5465 Region->emitUntiedSwitch(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00005466 };
John McCall7f416cc2015-09-08 08:05:57 +00005467
5468 llvm::Value *DepWaitTaskArgs[6];
5469 if (NumDependencies) {
5470 DepWaitTaskArgs[0] = UpLoc;
5471 DepWaitTaskArgs[1] = ThreadID;
5472 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
5473 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
5474 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
5475 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5476 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005477 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
Alexey Bataev3c595a62017-08-14 15:01:03 +00005478 NumDependencies, &DepWaitTaskArgs,
5479 Loc](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005480 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005481 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
5482 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
5483 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
5484 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
5485 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00005486 if (NumDependencies)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005487 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005488 DepWaitTaskArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005489 // Call proxy_task_entry(gtid, new_task);
Alexey Bataev3c595a62017-08-14 15:01:03 +00005490 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
5491 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005492 Action.Enter(CGF);
5493 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
Alexey Bataev3c595a62017-08-14 15:01:03 +00005494 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
Alexey Bataev2c7eee52017-08-04 19:10:54 +00005495 OutlinedFnArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005496 };
5497
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005498 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
5499 // kmp_task_t *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005500 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
5501 // kmp_task_t *new_task);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005502 RegionCodeGenTy RCG(CodeGen);
5503 CommonActionTy Action(
5504 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs,
5505 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs);
5506 RCG.setAction(Action);
5507 RCG(CGF);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005508 };
John McCall7f416cc2015-09-08 08:05:57 +00005509
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005510 if (IfCond) {
Alexey Bataev1d677132015-04-22 13:57:31 +00005511 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005512 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005513 RegionCodeGenTy ThenRCG(ThenCodeGen);
5514 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00005515 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005516}
5517
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005518void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
5519 const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005520 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005521 QualType SharedsTy, Address Shareds,
5522 const Expr *IfCond,
5523 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005524 if (!CGF.HaveInsertPoint())
5525 return;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005526 TaskResultTy Result =
5527 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005528 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev7292c292016-04-25 12:22:29 +00005529 // libcall.
5530 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
5531 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
5532 // sched, kmp_uint64 grainsize, void *task_dup);
5533 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5534 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
5535 llvm::Value *IfVal;
5536 if (IfCond) {
5537 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy,
5538 /*isSigned=*/true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005539 } else {
Alexey Bataev7292c292016-04-25 12:22:29 +00005540 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005541 }
Alexey Bataev7292c292016-04-25 12:22:29 +00005542
5543 LValue LBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005544 Result.TDBase,
5545 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005546 const auto *LBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005547 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl());
5548 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(),
5549 /*IsInitializer=*/true);
5550 LValue UBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005551 Result.TDBase,
5552 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005553 const auto *UBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005554 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl());
5555 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(),
5556 /*IsInitializer=*/true);
5557 LValue StLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005558 Result.TDBase,
5559 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005560 const auto *StVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005561 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl());
5562 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(),
5563 /*IsInitializer=*/true);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005564 // Store reductions address.
5565 LValue RedLVal = CGF.EmitLValueForField(
5566 Result.TDBase,
5567 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005568 if (Data.Reductions) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005569 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005570 } else {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005571 CGF.EmitNullInitialization(RedLVal.getAddress(),
5572 CGF.getContext().VoidPtrTy);
5573 }
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005574 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
Alexey Bataev7292c292016-04-25 12:22:29 +00005575 llvm::Value *TaskArgs[] = {
Alexey Bataev33446032017-07-12 18:09:32 +00005576 UpLoc,
5577 ThreadID,
5578 Result.NewTask,
5579 IfVal,
5580 LBLVal.getPointer(),
5581 UBLVal.getPointer(),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00005582 CGF.EmitLoadOfScalar(StLVal, Loc),
Alexey Bataevac6e4de2018-10-24 19:06:37 +00005583 llvm::ConstantInt::getSigned(
5584 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005585 llvm::ConstantInt::getSigned(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005586 CGF.IntTy, Data.Schedule.getPointer()
5587 ? Data.Schedule.getInt() ? NumTasks : Grainsize
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005588 : NoSchedule),
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005589 Data.Schedule.getPointer()
5590 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty,
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005591 /*isSigned=*/false)
5592 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0),
Alexey Bataev33446032017-07-12 18:09:32 +00005593 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5594 Result.TaskDupFn, CGF.VoidPtrTy)
5595 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)};
Alexey Bataev7292c292016-04-25 12:22:29 +00005596 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs);
5597}
5598
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005599/// Emit reduction operation for each element of array (required for
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005600/// array sections) LHS op = RHS.
5601/// \param Type Type of array.
5602/// \param LHSVar Variable on the left side of the reduction operation
5603/// (references element of array in original variable).
5604/// \param RHSVar Variable on the right side of the reduction operation
5605/// (references element of array in original variable).
5606/// \param RedOpGen Generator of reduction operation with use of LHSVar and
5607/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00005608static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005609 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
5610 const VarDecl *RHSVar,
5611 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
5612 const Expr *, const Expr *)> &RedOpGen,
5613 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
5614 const Expr *UpExpr = nullptr) {
5615 // Perform element-by-element initialization.
5616 QualType ElementTy;
5617 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
5618 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
5619
5620 // Drill down to the base element type on both arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005621 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
5622 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005623
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005624 llvm::Value *RHSBegin = RHSAddr.getPointer();
5625 llvm::Value *LHSBegin = LHSAddr.getPointer();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005626 // Cast from pointer to array type to pointer to single element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005627 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005628 // The basic structure here is a while-do loop.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005629 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
5630 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
5631 llvm::Value *IsEmpty =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005632 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
5633 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
5634
5635 // Enter the loop body, making that address the current address.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005636 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005637 CGF.EmitBlock(BodyBB);
5638
5639 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
5640
5641 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
5642 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
5643 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
5644 Address RHSElementCurrent =
5645 Address(RHSElementPHI,
5646 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5647
5648 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
5649 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
5650 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
5651 Address LHSElementCurrent =
5652 Address(LHSElementPHI,
5653 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5654
5655 // Emit copy.
5656 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005657 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; });
5658 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005659 Scope.Privatize();
5660 RedOpGen(CGF, XExpr, EExpr, UpExpr);
5661 Scope.ForceCleanup();
5662
5663 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005664 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005665 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005666 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005667 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
5668 // Check whether we've reached the end.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005669 llvm::Value *Done =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005670 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
5671 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
5672 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
5673 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
5674
5675 // Done.
5676 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
5677}
5678
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005679/// Emit reduction combiner. If the combiner is a simple expression emit it as
5680/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
5681/// UDR combiner function.
5682static void emitReductionCombiner(CodeGenFunction &CGF,
5683 const Expr *ReductionOp) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005684 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
5685 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
5686 if (const auto *DRE =
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005687 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005688 if (const auto *DRD =
5689 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005690 std::pair<llvm::Function *, llvm::Function *> Reduction =
5691 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
5692 RValue Func = RValue::get(Reduction.first);
5693 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
5694 CGF.EmitIgnoredExpr(ReductionOp);
5695 return;
5696 }
5697 CGF.EmitIgnoredExpr(ReductionOp);
5698}
5699
James Y Knight9871db02019-02-05 16:42:33 +00005700llvm::Function *CGOpenMPRuntime::emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005701 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates,
5702 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
5703 ArrayRef<const Expr *> ReductionOps) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005704 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005705
5706 // void reduction_func(void *LHSArg, void *RHSArg);
5707 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005708 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5709 ImplicitParamDecl::Other);
5710 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5711 ImplicitParamDecl::Other);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005712 Args.push_back(&LHSArg);
5713 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005714 const auto &CGFI =
5715 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00005716 std::string Name = getName({"omp", "reduction", "reduction_func"});
5717 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
5718 llvm::GlobalValue::InternalLinkage, Name,
5719 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00005720 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00005721 Fn->setDoesNotRecurse();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005722 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005723 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005724
5725 // Dst = (void*[n])(LHSArg);
5726 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00005727 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5728 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
5729 ArgsType), CGF.getPointerAlign());
5730 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5731 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
5732 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005733
5734 // ...
5735 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
5736 // ...
5737 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005738 auto IPriv = Privates.begin();
5739 unsigned Idx = 0;
5740 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005741 const auto *RHSVar =
5742 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
5743 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005744 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005745 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005746 const auto *LHSVar =
5747 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
5748 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005749 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005750 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005751 QualType PrivTy = (*IPriv)->getType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00005752 if (PrivTy->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005753 // Get array size and emit VLA type.
5754 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005755 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005756 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005757 const VariableArrayType *VLA =
5758 CGF.getContext().getAsVariableArrayType(PrivTy);
5759 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005760 CodeGenFunction::OpaqueValueMapping OpaqueMap(
Alexey Bataev1189bd02016-01-26 12:20:39 +00005761 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005762 CGF.EmitVariablyModifiedType(PrivTy);
5763 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005764 }
5765 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005766 IPriv = Privates.begin();
5767 auto ILHS = LHSExprs.begin();
5768 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005769 for (const Expr *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005770 if ((*IPriv)->getType()->isArrayType()) {
5771 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005772 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5773 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005774 EmitOMPAggregateReduction(
5775 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5776 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5777 emitReductionCombiner(CGF, E);
5778 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005779 } else {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005780 // Emit reduction for array subscript or single variable.
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005781 emitReductionCombiner(CGF, E);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005782 }
Richard Trieucc3949d2016-02-18 22:34:54 +00005783 ++IPriv;
5784 ++ILHS;
5785 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005786 }
5787 Scope.ForceCleanup();
5788 CGF.FinishFunction();
5789 return Fn;
5790}
5791
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005792void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF,
5793 const Expr *ReductionOp,
5794 const Expr *PrivateRef,
5795 const DeclRefExpr *LHS,
5796 const DeclRefExpr *RHS) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005797 if (PrivateRef->getType()->isArrayType()) {
5798 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005799 const auto *LHSVar = cast<VarDecl>(LHS->getDecl());
5800 const auto *RHSVar = cast<VarDecl>(RHS->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005801 EmitOMPAggregateReduction(
5802 CGF, PrivateRef->getType(), LHSVar, RHSVar,
5803 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5804 emitReductionCombiner(CGF, ReductionOp);
5805 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005806 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005807 // Emit reduction for array subscript or single variable.
5808 emitReductionCombiner(CGF, ReductionOp);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005809 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005810}
5811
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005812void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005813 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005814 ArrayRef<const Expr *> LHSExprs,
5815 ArrayRef<const Expr *> RHSExprs,
5816 ArrayRef<const Expr *> ReductionOps,
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005817 ReductionOptionsTy Options) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00005818 if (!CGF.HaveInsertPoint())
5819 return;
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005820
5821 bool WithNowait = Options.WithNowait;
5822 bool SimpleReduction = Options.SimpleReduction;
5823
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005824 // Next code should be emitted for reduction:
5825 //
5826 // static kmp_critical_name lock = { 0 };
5827 //
5828 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
5829 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
5830 // ...
5831 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
5832 // *(Type<n>-1*)rhs[<n>-1]);
5833 // }
5834 //
5835 // ...
5836 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
5837 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5838 // RedList, reduce_func, &<lock>)) {
5839 // case 1:
5840 // ...
5841 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5842 // ...
5843 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5844 // break;
5845 // case 2:
5846 // ...
5847 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5848 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00005849 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005850 // break;
5851 // default:;
5852 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005853 //
5854 // if SimpleReduction is true, only the next code is generated:
5855 // ...
5856 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5857 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005858
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005859 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005860
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005861 if (SimpleReduction) {
5862 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005863 auto IPriv = Privates.begin();
5864 auto ILHS = LHSExprs.begin();
5865 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005866 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005867 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5868 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005869 ++IPriv;
5870 ++ILHS;
5871 ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005872 }
5873 return;
5874 }
5875
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005876 // 1. Build a list of reduction variables.
5877 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005878 auto Size = RHSExprs.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005879 for (const Expr *E : Privates) {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005880 if (E->getType()->isVariablyModifiedType())
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005881 // Reserve place for array size.
5882 ++Size;
5883 }
5884 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005885 QualType ReductionArrayTy =
Richard Smith772e2662019-10-04 01:25:59 +00005886 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005887 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00005888 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005889 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005890 auto IPriv = Privates.begin();
5891 unsigned Idx = 0;
5892 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
James Y Knight751fe282019-02-09 22:22:28 +00005893 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
John McCall7f416cc2015-09-08 08:05:57 +00005894 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005895 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00005896 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
5897 Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005898 if ((*IPriv)->getType()->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005899 // Store array size.
5900 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005901 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005902 llvm::Value *Size = CGF.Builder.CreateIntCast(
5903 CGF.getVLASize(
5904 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
Sander de Smalen891af03a2018-02-03 13:55:59 +00005905 .NumElts,
Alexey Bataev1189bd02016-01-26 12:20:39 +00005906 CGF.SizeTy, /*isSigned=*/false);
5907 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
5908 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005909 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005910 }
5911
5912 // 2. Emit reduce_func().
James Y Knight9871db02019-02-05 16:42:33 +00005913 llvm::Function *ReductionFn = emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005914 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
5915 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005916
5917 // 3. Create static kmp_critical_name lock = { 0 };
Alexey Bataev18fa2322018-05-02 14:20:50 +00005918 std::string Name = getName({"reduction"});
5919 llvm::Value *Lock = getCriticalRegionLock(Name);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005920
5921 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5922 // RedList, reduce_func, &<lock>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005923 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
5924 llvm::Value *ThreadId = getThreadID(CGF, Loc);
5925 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
5926 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Samuel Antao4c8035b2016-12-12 18:00:20 +00005927 ReductionList.getPointer(), CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005928 llvm::Value *Args[] = {
5929 IdentTLoc, // ident_t *<loc>
5930 ThreadId, // i32 <gtid>
5931 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
5932 ReductionArrayTySize, // size_type sizeof(RedList)
5933 RL, // void *RedList
5934 ReductionFn, // void (*) (void *, void *) <reduce_func>
5935 Lock // kmp_critical_name *&<lock>
5936 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005937 llvm::Value *Res = CGF.EmitRuntimeCall(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005938 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
5939 : OMPRTL__kmpc_reduce),
5940 Args);
5941
5942 // 5. Build switch(res)
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005943 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
5944 llvm::SwitchInst *SwInst =
5945 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005946
5947 // 6. Build case 1:
5948 // ...
5949 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5950 // ...
5951 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5952 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005953 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005954 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
5955 CGF.EmitBlock(Case1BB);
5956
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005957 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5958 llvm::Value *EndArgs[] = {
5959 IdentTLoc, // ident_t *<loc>
5960 ThreadId, // i32 <gtid>
5961 Lock // kmp_critical_name *&<lock>
5962 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005963 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5964 CodeGenFunction &CGF, PrePostActionTy &Action) {
5965 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005966 auto IPriv = Privates.begin();
5967 auto ILHS = LHSExprs.begin();
5968 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005969 for (const Expr *E : ReductionOps) {
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005970 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5971 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005972 ++IPriv;
5973 ++ILHS;
5974 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005975 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005976 };
5977 RegionCodeGenTy RCG(CodeGen);
5978 CommonActionTy Action(
5979 nullptr, llvm::None,
5980 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
5981 : OMPRTL__kmpc_end_reduce),
5982 EndArgs);
5983 RCG.setAction(Action);
5984 RCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005985
5986 CGF.EmitBranch(DefaultBB);
5987
5988 // 7. Build case 2:
5989 // ...
5990 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5991 // ...
5992 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005993 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005994 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
5995 CGF.EmitBlock(Case2BB);
5996
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005997 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
5998 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005999 auto ILHS = LHSExprs.begin();
6000 auto IRHS = RHSExprs.begin();
6001 auto IPriv = Privates.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006002 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006003 const Expr *XExpr = nullptr;
6004 const Expr *EExpr = nullptr;
6005 const Expr *UpExpr = nullptr;
6006 BinaryOperatorKind BO = BO_Comma;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006007 if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006008 if (BO->getOpcode() == BO_Assign) {
6009 XExpr = BO->getLHS();
6010 UpExpr = BO->getRHS();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00006011 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006012 }
6013 // Try to emit update expression as a simple atomic.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006014 const Expr *RHSExpr = UpExpr;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006015 if (RHSExpr) {
6016 // Analyze RHS part of the whole expression.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006017 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006018 RHSExpr->IgnoreParenImpCasts())) {
6019 // If this is a conditional operator, analyze its condition for
6020 // min/max reduction operator.
6021 RHSExpr = ACO->getCond();
Alexey Bataev69a47792015-05-07 03:54:03 +00006022 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006023 if (const auto *BORHS =
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006024 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
6025 EExpr = BORHS->getRHS();
6026 BO = BORHS->getOpcode();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00006027 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006028 }
6029 if (XExpr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006030 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00006031 auto &&AtomicRedGen = [BO, VD,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006032 Loc](CodeGenFunction &CGF, const Expr *XExpr,
6033 const Expr *EExpr, const Expr *UpExpr) {
6034 LValue X = CGF.EmitLValue(XExpr);
6035 RValue E;
6036 if (EExpr)
6037 E = CGF.EmitAnyExpr(EExpr);
6038 CGF.EmitOMPAtomicSimpleUpdateExpr(
JF Bastien92f4ef12016-04-06 17:26:42 +00006039 X, E, BO, /*IsXLHSInRHSPart=*/true,
6040 llvm::AtomicOrdering::Monotonic, Loc,
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00006041 [&CGF, UpExpr, VD, Loc](RValue XRValue) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006042 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
6043 PrivateScope.addPrivate(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006044 VD, [&CGF, VD, XRValue, Loc]() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006045 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
6046 CGF.emitOMPSimpleStore(
6047 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
6048 VD->getType().getNonReferenceType(), Loc);
6049 return LHSTemp;
6050 });
6051 (void)PrivateScope.Privatize();
6052 return CGF.EmitAnyExpr(UpExpr);
6053 });
6054 };
6055 if ((*IPriv)->getType()->isArrayType()) {
6056 // Emit atomic reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006057 const auto *RHSVar =
6058 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006059 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
6060 AtomicRedGen, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006061 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006062 // Emit atomic reduction for array subscript or single variable.
6063 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006064 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006065 } else {
6066 // Emit as a critical region.
6067 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006068 const Expr *, const Expr *) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006069 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev18fa2322018-05-02 14:20:50 +00006070 std::string Name = RT.getName({"atomic_reduction"});
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006071 RT.emitCriticalRegion(
Alexey Bataev18fa2322018-05-02 14:20:50 +00006072 CGF, Name,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006073 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
6074 Action.Enter(CGF);
6075 emitReductionCombiner(CGF, E);
6076 },
6077 Loc);
6078 };
6079 if ((*IPriv)->getType()->isArrayType()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006080 const auto *LHSVar =
6081 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
6082 const auto *RHSVar =
6083 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006084 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
6085 CritRedGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006086 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006087 CritRedGen(CGF, nullptr, nullptr, nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006088 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006089 }
Richard Trieucc3949d2016-02-18 22:34:54 +00006090 ++ILHS;
6091 ++IRHS;
6092 ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00006093 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006094 };
6095 RegionCodeGenTy AtomicRCG(AtomicCodeGen);
6096 if (!WithNowait) {
6097 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
6098 llvm::Value *EndArgs[] = {
6099 IdentTLoc, // ident_t *<loc>
6100 ThreadId, // i32 <gtid>
6101 Lock // kmp_critical_name *&<lock>
6102 };
6103 CommonActionTy Action(nullptr, llvm::None,
6104 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
6105 EndArgs);
6106 AtomicRCG.setAction(Action);
6107 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006108 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006109 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006110 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00006111
6112 CGF.EmitBranch(DefaultBB);
6113 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
6114}
6115
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006116/// Generates unique name for artificial threadprivate variables.
Alexey Bataev1c44e152018-03-06 18:59:43 +00006117/// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>"
6118static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix,
6119 const Expr *Ref) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006120 SmallString<256> Buffer;
6121 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev1c44e152018-03-06 18:59:43 +00006122 const clang::DeclRefExpr *DE;
6123 const VarDecl *D = ::getBaseDecl(Ref, DE);
6124 if (!D)
6125 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl());
6126 D = D->getCanonicalDecl();
Alexey Bataev18fa2322018-05-02 14:20:50 +00006127 std::string Name = CGM.getOpenMPRuntime().getName(
6128 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)});
6129 Out << Prefix << Name << "_"
Stephen Kellyf2ceec42018-08-09 21:08:08 +00006130 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006131 return Out.str();
6132}
6133
6134/// Emits reduction initializer function:
6135/// \code
6136/// void @.red_init(void* %arg) {
6137/// %0 = bitcast void* %arg to <type>*
6138/// store <type> <init>, <type>* %0
6139/// ret void
6140/// }
6141/// \endcode
6142static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM,
6143 SourceLocation Loc,
6144 ReductionCodeGen &RCG, unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006145 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006146 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006147 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6148 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006149 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006150 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006151 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006152 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006153 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006154 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006155 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006156 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006157 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006158 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006159 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006160 Address PrivateAddr = CGF.EmitLoadOfPointer(
6161 CGF.GetAddrOfLocalVar(&Param),
6162 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6163 llvm::Value *Size = nullptr;
6164 // If the size of the reduction item is non-constant, load it from global
6165 // threadprivate variable.
6166 if (RCG.getSizes(N).second) {
6167 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6168 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006169 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006170 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6171 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006172 }
6173 RCG.emitAggregateType(CGF, N, Size);
6174 LValue SharedLVal;
6175 // If initializer uses initializer from declare reduction construct, emit a
6176 // pointer to the address of the original reduction item (reuired by reduction
6177 // initializer)
6178 if (RCG.usesReductionInitializer(N)) {
6179 Address SharedAddr =
6180 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6181 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006182 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataev21dab122018-03-09 15:20:30 +00006183 SharedAddr = CGF.EmitLoadOfPointer(
6184 SharedAddr,
6185 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006186 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy);
6187 } else {
6188 SharedLVal = CGF.MakeNaturalAlignAddrLValue(
6189 llvm::ConstantPointerNull::get(CGM.VoidPtrTy),
6190 CGM.getContext().VoidPtrTy);
6191 }
6192 // Emit the initializer:
6193 // %0 = bitcast void* %arg to <type>*
6194 // store <type> <init>, <type>* %0
6195 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal,
6196 [](CodeGenFunction &) { return false; });
6197 CGF.FinishFunction();
6198 return Fn;
6199}
6200
6201/// Emits reduction combiner function:
6202/// \code
6203/// void @.red_comb(void* %arg0, void* %arg1) {
6204/// %lhs = bitcast void* %arg0 to <type>*
6205/// %rhs = bitcast void* %arg1 to <type>*
6206/// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs)
6207/// store <type> %2, <type>* %lhs
6208/// ret void
6209/// }
6210/// \endcode
6211static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM,
6212 SourceLocation Loc,
6213 ReductionCodeGen &RCG, unsigned N,
6214 const Expr *ReductionOp,
6215 const Expr *LHS, const Expr *RHS,
6216 const Expr *PrivateRef) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006217 ASTContext &C = CGM.getContext();
6218 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl());
6219 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006220 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006221 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
6222 C.VoidPtrTy, ImplicitParamDecl::Other);
6223 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6224 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006225 Args.emplace_back(&ParamInOut);
6226 Args.emplace_back(&ParamIn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006227 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006228 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006229 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006230 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006231 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006232 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006233 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006234 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006235 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006236 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006237 llvm::Value *Size = nullptr;
6238 // If the size of the reduction item is non-constant, load it from global
6239 // threadprivate variable.
6240 if (RCG.getSizes(N).second) {
6241 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6242 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006243 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006244 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6245 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006246 }
6247 RCG.emitAggregateType(CGF, N, Size);
6248 // Remap lhs and rhs variables to the addresses of the function arguments.
6249 // %lhs = bitcast void* %arg0 to <type>*
6250 // %rhs = bitcast void* %arg1 to <type>*
6251 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006252 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006253 // Pull out the pointer to the variable.
6254 Address PtrAddr = CGF.EmitLoadOfPointer(
6255 CGF.GetAddrOfLocalVar(&ParamInOut),
6256 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6257 return CGF.Builder.CreateElementBitCast(
6258 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType()));
6259 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006260 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006261 // Pull out the pointer to the variable.
6262 Address PtrAddr = CGF.EmitLoadOfPointer(
6263 CGF.GetAddrOfLocalVar(&ParamIn),
6264 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6265 return CGF.Builder.CreateElementBitCast(
6266 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType()));
6267 });
6268 PrivateScope.Privatize();
6269 // Emit the combiner body:
6270 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs)
6271 // store <type> %2, <type>* %lhs
6272 CGM.getOpenMPRuntime().emitSingleReductionCombiner(
6273 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS),
6274 cast<DeclRefExpr>(RHS));
6275 CGF.FinishFunction();
6276 return Fn;
6277}
6278
6279/// Emits reduction finalizer function:
6280/// \code
6281/// void @.red_fini(void* %arg) {
6282/// %0 = bitcast void* %arg to <type>*
6283/// <destroy>(<type>* %0)
6284/// ret void
6285/// }
6286/// \endcode
6287static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM,
6288 SourceLocation Loc,
6289 ReductionCodeGen &RCG, unsigned N) {
6290 if (!RCG.needCleanups(N))
6291 return nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006292 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006293 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006294 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6295 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006296 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006297 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006298 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006299 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006300 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006301 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006302 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006303 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006304 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006305 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006306 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006307 Address PrivateAddr = CGF.EmitLoadOfPointer(
6308 CGF.GetAddrOfLocalVar(&Param),
6309 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6310 llvm::Value *Size = nullptr;
6311 // If the size of the reduction item is non-constant, load it from global
6312 // threadprivate variable.
6313 if (RCG.getSizes(N).second) {
6314 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6315 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006316 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006317 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6318 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006319 }
6320 RCG.emitAggregateType(CGF, N, Size);
6321 // Emit the finalizer body:
6322 // <destroy>(<type>* %0)
6323 RCG.emitCleanups(CGF, N, PrivateAddr);
6324 CGF.FinishFunction();
6325 return Fn;
6326}
6327
6328llvm::Value *CGOpenMPRuntime::emitTaskReductionInit(
6329 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
6330 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
6331 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty())
6332 return nullptr;
6333
6334 // Build typedef struct:
6335 // kmp_task_red_input {
6336 // void *reduce_shar; // shared reduction item
6337 // size_t reduce_size; // size of data item
6338 // void *reduce_init; // data initialization routine
6339 // void *reduce_fini; // data finalization routine
6340 // void *reduce_comb; // data combiner routine
6341 // kmp_task_red_flags_t flags; // flags for additional info from compiler
6342 // } kmp_task_red_input_t;
6343 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006344 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t");
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006345 RD->startDefinition();
6346 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6347 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType());
6348 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6349 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6350 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6351 const FieldDecl *FlagsFD = addFieldToRecordDecl(
6352 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false));
6353 RD->completeDefinition();
6354 QualType RDType = C.getRecordType(RD);
6355 unsigned Size = Data.ReductionVars.size();
6356 llvm::APInt ArraySize(/*numBits=*/64, Size);
6357 QualType ArrayRDType = C.getConstantArrayType(
Richard Smith772e2662019-10-04 01:25:59 +00006358 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006359 // kmp_task_red_input_t .rd_input.[Size];
6360 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input.");
6361 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies,
6362 Data.ReductionOps);
6363 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) {
6364 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt];
6365 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0),
6366 llvm::ConstantInt::get(CGM.SizeTy, Cnt)};
6367 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP(
6368 TaskRedInput.getPointer(), Idxs,
6369 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc,
6370 ".rd_input.gep.");
6371 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType);
6372 // ElemLVal.reduce_shar = &Shareds[Cnt];
6373 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD);
6374 RCG.emitSharedLValue(CGF, Cnt);
6375 llvm::Value *CastedShared =
6376 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer());
6377 CGF.EmitStoreOfScalar(CastedShared, SharedLVal);
6378 RCG.emitAggregateType(CGF, Cnt);
6379 llvm::Value *SizeValInChars;
6380 llvm::Value *SizeVal;
6381 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt);
6382 // We use delayed creation/initialization for VLAs, array sections and
6383 // custom reduction initializations. It is required because runtime does not
6384 // provide the way to pass the sizes of VLAs/array sections to
6385 // initializer/combiner/finalizer functions and does not pass the pointer to
6386 // original reduction item to the initializer. Instead threadprivate global
6387 // variables are used to store these values and use them in the functions.
6388 bool DelayedCreation = !!SizeVal;
6389 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy,
6390 /*isSigned=*/false);
6391 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD);
6392 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal);
6393 // ElemLVal.reduce_init = init;
6394 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD);
6395 llvm::Value *InitAddr =
6396 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt));
6397 CGF.EmitStoreOfScalar(InitAddr, InitLVal);
6398 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt);
6399 // ElemLVal.reduce_fini = fini;
6400 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD);
6401 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt);
6402 llvm::Value *FiniAddr = Fini
6403 ? CGF.EmitCastToVoidPtr(Fini)
6404 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy);
6405 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal);
6406 // ElemLVal.reduce_comb = comb;
6407 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD);
6408 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction(
6409 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt],
6410 RHSExprs[Cnt], Data.ReductionCopies[Cnt]));
6411 CGF.EmitStoreOfScalar(CombAddr, CombLVal);
6412 // ElemLVal.flags = 0;
6413 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD);
6414 if (DelayedCreation) {
6415 CGF.EmitStoreOfScalar(
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006416 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006417 FlagsLVal);
6418 } else
6419 CGF.EmitNullInitialization(FlagsLVal.getAddress(), FlagsLVal.getType());
6420 }
6421 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void
6422 // *data);
6423 llvm::Value *Args[] = {
6424 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6425 /*isSigned=*/true),
6426 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true),
6427 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(),
6428 CGM.VoidPtrTy)};
6429 return CGF.EmitRuntimeCall(
6430 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args);
6431}
6432
6433void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
6434 SourceLocation Loc,
6435 ReductionCodeGen &RCG,
6436 unsigned N) {
6437 auto Sizes = RCG.getSizes(N);
6438 // Emit threadprivate global variable if the type is non-constant
6439 // (Sizes.second = nullptr).
6440 if (Sizes.second) {
6441 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy,
6442 /*isSigned=*/false);
6443 Address SizeAddr = getAddrOfArtificialThreadPrivate(
6444 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006445 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006446 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false);
6447 }
6448 // Store address of the original reduction item if custom initializer is used.
6449 if (RCG.usesReductionInitializer(N)) {
6450 Address SharedAddr = getAddrOfArtificialThreadPrivate(
6451 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006452 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006453 CGF.Builder.CreateStore(
6454 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6455 RCG.getSharedLValue(N).getPointer(), CGM.VoidPtrTy),
6456 SharedAddr, /*IsVolatile=*/false);
6457 }
6458}
6459
6460Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF,
6461 SourceLocation Loc,
6462 llvm::Value *ReductionsPtr,
6463 LValue SharedLVal) {
6464 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
6465 // *d);
6466 llvm::Value *Args[] = {
6467 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6468 /*isSigned=*/true),
6469 ReductionsPtr,
6470 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(SharedLVal.getPointer(),
6471 CGM.VoidPtrTy)};
6472 return Address(
6473 CGF.EmitRuntimeCall(
6474 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args),
6475 SharedLVal.getAlignment());
6476}
6477
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006478void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
6479 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006480 if (!CGF.HaveInsertPoint())
6481 return;
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006482 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
6483 // global_tid);
6484 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
6485 // Ignore return result until untied tasks are supported.
6486 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00006487 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
6488 Region->emitUntiedSwitch(CGF);
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006489}
6490
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006491void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006492 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00006493 const RegionCodeGenTy &CodeGen,
6494 bool HasCancel) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006495 if (!CGF.HaveInsertPoint())
6496 return;
Alexey Bataev25e5b442015-09-15 12:52:43 +00006497 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006498 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00006499}
6500
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006501namespace {
6502enum RTCancelKind {
6503 CancelNoreq = 0,
6504 CancelParallel = 1,
6505 CancelLoop = 2,
6506 CancelSections = 3,
6507 CancelTaskgroup = 4
6508};
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00006509} // anonymous namespace
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006510
6511static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
6512 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00006513 if (CancelRegion == OMPD_parallel)
6514 CancelKind = CancelParallel;
6515 else if (CancelRegion == OMPD_for)
6516 CancelKind = CancelLoop;
6517 else if (CancelRegion == OMPD_sections)
6518 CancelKind = CancelSections;
6519 else {
6520 assert(CancelRegion == OMPD_taskgroup);
6521 CancelKind = CancelTaskgroup;
6522 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006523 return CancelKind;
6524}
6525
6526void CGOpenMPRuntime::emitCancellationPointCall(
6527 CodeGenFunction &CGF, SourceLocation Loc,
6528 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006529 if (!CGF.HaveInsertPoint())
6530 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006531 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
6532 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006533 if (auto *OMPRegionInfo =
6534 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Jonas Hahnfeldb07931f2017-02-17 18:32:58 +00006535 // For 'cancellation point taskgroup', the task region info may not have a
6536 // cancel. This may instead happen in another adjacent task.
6537 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006538 llvm::Value *Args[] = {
6539 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
6540 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006541 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006542 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006543 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
6544 // if (__kmpc_cancellationpoint()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006545 // exit from construct;
6546 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006547 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6548 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6549 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006550 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6551 CGF.EmitBlock(ExitBB);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006552 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006553 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev25e5b442015-09-15 12:52:43 +00006554 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006555 CGF.EmitBranchThroughCleanup(CancelDest);
6556 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6557 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006558 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006559}
6560
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006561void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00006562 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006563 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006564 if (!CGF.HaveInsertPoint())
6565 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006566 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
6567 // kmp_int32 cncl_kind);
6568 if (auto *OMPRegionInfo =
6569 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006570 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF,
6571 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006572 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev87933c72015-09-18 08:07:34 +00006573 llvm::Value *Args[] = {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006574 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
Alexey Bataev87933c72015-09-18 08:07:34 +00006575 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
6576 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006577 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006578 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
Alexey Bataev87933c72015-09-18 08:07:34 +00006579 // if (__kmpc_cancel()) {
Alexey Bataev87933c72015-09-18 08:07:34 +00006580 // exit from construct;
6581 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006582 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6583 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6584 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev87933c72015-09-18 08:07:34 +00006585 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6586 CGF.EmitBlock(ExitBB);
Alexey Bataev87933c72015-09-18 08:07:34 +00006587 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006588 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev87933c72015-09-18 08:07:34 +00006589 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6590 CGF.EmitBranchThroughCleanup(CancelDest);
6591 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6592 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006593 if (IfCond) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006594 emitOMPIfClause(CGF, IfCond, ThenGen,
6595 [](CodeGenFunction &, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006596 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006597 RegionCodeGenTy ThenRCG(ThenGen);
6598 ThenRCG(CGF);
6599 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006600 }
6601}
Samuel Antaobed3c462015-10-02 16:14:20 +00006602
Samuel Antaoee8fb302016-01-06 13:42:12 +00006603void CGOpenMPRuntime::emitTargetOutlinedFunction(
6604 const OMPExecutableDirective &D, StringRef ParentName,
6605 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006606 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00006607 assert(!ParentName.empty() && "Invalid target region parent name!");
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00006608 HasEmittedTargetRegion = true;
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006609 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
6610 IsOffloadEntry, CodeGen);
6611}
6612
6613void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
6614 const OMPExecutableDirective &D, StringRef ParentName,
6615 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6616 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antao2de62b02016-02-13 23:35:10 +00006617 // Create a unique name for the entry function using the source location
6618 // information of the current target region. The name will be something like:
Samuel Antaoee8fb302016-01-06 13:42:12 +00006619 //
Samuel Antao2de62b02016-02-13 23:35:10 +00006620 // __omp_offloading_DD_FFFF_PP_lBB
Samuel Antaoee8fb302016-01-06 13:42:12 +00006621 //
6622 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
Samuel Antao2de62b02016-02-13 23:35:10 +00006623 // mangled name of the function that encloses the target region and BB is the
6624 // line number of the target region.
Samuel Antaoee8fb302016-01-06 13:42:12 +00006625
6626 unsigned DeviceID;
6627 unsigned FileID;
6628 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00006629 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00006630 Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006631 SmallString<64> EntryFnName;
6632 {
6633 llvm::raw_svector_ostream OS(EntryFnName);
Samuel Antao2de62b02016-02-13 23:35:10 +00006634 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
6635 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00006636 }
6637
Alexey Bataev475a7442018-01-12 19:39:11 +00006638 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006639
Samuel Antaobed3c462015-10-02 16:14:20 +00006640 CodeGenFunction CGF(CGM, true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006641 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
Samuel Antaobed3c462015-10-02 16:14:20 +00006642 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006643
Samuel Antao6d004262016-06-16 18:39:34 +00006644 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006645
6646 // If this target outline function is not an offload entry, we don't need to
6647 // register it.
6648 if (!IsOffloadEntry)
6649 return;
6650
6651 // The target region ID is used by the runtime library to identify the current
6652 // target region, so it only has to be unique and not necessarily point to
6653 // anything. It could be the pointer to the outlined function that implements
6654 // the target region, but we aren't using that so that the compiler doesn't
6655 // need to keep that, and could therefore inline the host function if proven
6656 // worthwhile during optimization. In the other hand, if emitting code for the
6657 // device, the ID has to be the function address so that it can retrieved from
6658 // the offloading entry and launched by the runtime library. We also mark the
6659 // outlined function to have external linkage in case we are emitting code for
6660 // the device, because these functions will be entry points to the device.
6661
6662 if (CGM.getLangOpts().OpenMPIsDevice) {
6663 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
Alexey Bataev9a700172018-05-08 14:16:57 +00006664 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Rafael Espindolacbca4872018-01-11 22:15:12 +00006665 OutlinedFn->setDSOLocal(false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006666 } else {
Alexey Bataevc15ea702018-05-09 18:02:37 +00006667 std::string Name = getName({EntryFnName, "region_id"});
Samuel Antaoee8fb302016-01-06 13:42:12 +00006668 OutlinedFnID = new llvm::GlobalVariable(
6669 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
Alexey Bataev9a700172018-05-08 14:16:57 +00006670 llvm::GlobalValue::WeakAnyLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006671 llvm::Constant::getNullValue(CGM.Int8Ty), Name);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006672 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00006673
6674 // Register the information for the entry associated with this target region.
6675 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
Samuel Antaof83efdb2017-01-05 16:02:49 +00006676 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID,
Alexey Bataev03f270c2018-03-30 18:31:07 +00006677 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion);
Samuel Antaobed3c462015-10-02 16:14:20 +00006678}
6679
Alexey Bataev5c427362019-04-10 19:11:33 +00006680/// Checks if the expression is constant or does not have non-trivial function
6681/// calls.
6682static bool isTrivial(ASTContext &Ctx, const Expr * E) {
6683 // We can skip constant expressions.
6684 // We can skip expressions with trivial calls or simple expressions.
6685 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) ||
6686 !E->hasNonTrivialCall(Ctx)) &&
6687 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true);
6688}
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006689
Alexey Bataev5c427362019-04-10 19:11:33 +00006690const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx,
6691 const Stmt *Body) {
6692 const Stmt *Child = Body->IgnoreContainers();
6693 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) {
6694 Child = nullptr;
6695 for (const Stmt *S : C->body()) {
6696 if (const auto *E = dyn_cast<Expr>(S)) {
6697 if (isTrivial(Ctx, E))
6698 continue;
6699 }
6700 // Some of the statements can be ignored.
6701 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) ||
6702 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S))
6703 continue;
6704 // Analyze declarations.
6705 if (const auto *DS = dyn_cast<DeclStmt>(S)) {
6706 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) {
6707 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6708 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6709 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6710 isa<UsingDirectiveDecl>(D) ||
6711 isa<OMPDeclareReductionDecl>(D) ||
6712 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6713 return true;
6714 const auto *VD = dyn_cast<VarDecl>(D);
6715 if (!VD)
6716 return false;
6717 return VD->isConstexpr() ||
6718 ((VD->getType().isTrivialType(Ctx) ||
6719 VD->getType()->isReferenceType()) &&
6720 (!VD->hasInit() || isTrivial(Ctx, VD->getInit())));
6721 }))
6722 continue;
6723 }
6724 // Found multiple children - cannot get the one child only.
6725 if (Child)
6726 return nullptr;
6727 Child = S;
6728 }
6729 if (Child)
6730 Child = Child->IgnoreContainers();
6731 }
6732 return Child;
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006733}
6734
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006735/// Emit the number of teams for a target directive. Inspect the num_teams
6736/// clause associated with a teams construct combined or closely nested
6737/// with the target directive.
6738///
6739/// Emit a team of size one for directives such as 'target parallel' that
6740/// have no associated teams construct.
6741///
6742/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006743static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006744emitNumTeamsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006745 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006746 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6747 "Clauses associated with the teams directive expected to be emitted "
6748 "only for the host!");
6749 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6750 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6751 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006752 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006753 switch (DirectiveKind) {
6754 case OMPD_target: {
6755 const auto *CS = D.getInnermostCapturedStmt();
6756 const auto *Body =
6757 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
6758 const Stmt *ChildStmt =
6759 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body);
6760 if (const auto *NestedDir =
6761 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6762 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) {
6763 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) {
6764 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6765 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6766 const Expr *NumTeams =
6767 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6768 llvm::Value *NumTeamsVal =
6769 CGF.EmitScalarExpr(NumTeams,
6770 /*IgnoreResultAssign*/ true);
6771 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006772 /*isSigned=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00006773 }
6774 return Bld.getInt32(0);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006775 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006776 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) ||
6777 isOpenMPSimdDirective(NestedDir->getDirectiveKind()))
6778 return Bld.getInt32(1);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006779 return Bld.getInt32(0);
6780 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006781 return nullptr;
Samuel Antaob68e2db2016-03-03 16:20:23 +00006782 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006783 case OMPD_target_teams:
6784 case OMPD_target_teams_distribute:
6785 case OMPD_target_teams_distribute_simd:
6786 case OMPD_target_teams_distribute_parallel_for:
6787 case OMPD_target_teams_distribute_parallel_for_simd: {
6788 if (D.hasClausesOfKind<OMPNumTeamsClause>()) {
6789 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF);
6790 const Expr *NumTeams =
6791 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6792 llvm::Value *NumTeamsVal =
6793 CGF.EmitScalarExpr(NumTeams,
6794 /*IgnoreResultAssign*/ true);
6795 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006796 /*isSigned=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00006797 }
6798 return Bld.getInt32(0);
6799 }
6800 case OMPD_target_parallel:
6801 case OMPD_target_parallel_for:
6802 case OMPD_target_parallel_for_simd:
6803 case OMPD_target_simd:
6804 return Bld.getInt32(1);
6805 case OMPD_parallel:
6806 case OMPD_for:
6807 case OMPD_parallel_for:
6808 case OMPD_parallel_sections:
6809 case OMPD_for_simd:
6810 case OMPD_parallel_for_simd:
6811 case OMPD_cancel:
6812 case OMPD_cancellation_point:
6813 case OMPD_ordered:
6814 case OMPD_threadprivate:
6815 case OMPD_allocate:
6816 case OMPD_task:
6817 case OMPD_simd:
6818 case OMPD_sections:
6819 case OMPD_section:
6820 case OMPD_single:
6821 case OMPD_master:
6822 case OMPD_critical:
6823 case OMPD_taskyield:
6824 case OMPD_barrier:
6825 case OMPD_taskwait:
6826 case OMPD_taskgroup:
6827 case OMPD_atomic:
6828 case OMPD_flush:
6829 case OMPD_teams:
6830 case OMPD_target_data:
6831 case OMPD_target_exit_data:
6832 case OMPD_target_enter_data:
6833 case OMPD_distribute:
6834 case OMPD_distribute_simd:
6835 case OMPD_distribute_parallel_for:
6836 case OMPD_distribute_parallel_for_simd:
6837 case OMPD_teams_distribute:
6838 case OMPD_teams_distribute_simd:
6839 case OMPD_teams_distribute_parallel_for:
6840 case OMPD_teams_distribute_parallel_for_simd:
6841 case OMPD_target_update:
6842 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00006843 case OMPD_declare_variant:
Alexey Bataev5c427362019-04-10 19:11:33 +00006844 case OMPD_declare_target:
6845 case OMPD_end_declare_target:
6846 case OMPD_declare_reduction:
6847 case OMPD_declare_mapper:
6848 case OMPD_taskloop:
6849 case OMPD_taskloop_simd:
6850 case OMPD_requires:
6851 case OMPD_unknown:
6852 break;
6853 }
6854 llvm_unreachable("Unexpected directive kind.");
6855}
Samuel Antaob68e2db2016-03-03 16:20:23 +00006856
Alexey Bataev5c427362019-04-10 19:11:33 +00006857static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS,
6858 llvm::Value *DefaultThreadLimitVal) {
6859 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6860 CGF.getContext(), CS->getCapturedStmt());
6861 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6862 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) {
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006863 llvm::Value *NumThreads = nullptr;
6864 llvm::Value *CondVal = nullptr;
6865 // Handle if clause. If if clause present, the number of threads is
6866 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6867 if (Dir->hasClausesOfKind<OMPIfClause>()) {
6868 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6869 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6870 const OMPIfClause *IfClause = nullptr;
6871 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) {
6872 if (C->getNameModifier() == OMPD_unknown ||
6873 C->getNameModifier() == OMPD_parallel) {
6874 IfClause = C;
6875 break;
6876 }
6877 }
6878 if (IfClause) {
6879 const Expr *Cond = IfClause->getCondition();
6880 bool Result;
6881 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6882 if (!Result)
6883 return CGF.Builder.getInt32(1);
6884 } else {
6885 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange());
6886 if (const auto *PreInit =
6887 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) {
6888 for (const auto *I : PreInit->decls()) {
6889 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6890 CGF.EmitVarDecl(cast<VarDecl>(*I));
6891 } else {
6892 CodeGenFunction::AutoVarEmission Emission =
6893 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6894 CGF.EmitAutoVarCleanups(Emission);
6895 }
6896 }
6897 }
6898 CondVal = CGF.EvaluateExprAsBool(Cond);
6899 }
6900 }
6901 }
6902 // Check the value of num_threads clause iff if clause was not specified
6903 // or is not evaluated to false.
Alexey Bataev5c427362019-04-10 19:11:33 +00006904 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) {
6905 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6906 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6907 const auto *NumThreadsClause =
6908 Dir->getSingleClause<OMPNumThreadsClause>();
6909 CodeGenFunction::LexicalScope Scope(
6910 CGF, NumThreadsClause->getNumThreads()->getSourceRange());
6911 if (const auto *PreInit =
6912 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6913 for (const auto *I : PreInit->decls()) {
6914 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6915 CGF.EmitVarDecl(cast<VarDecl>(*I));
6916 } else {
6917 CodeGenFunction::AutoVarEmission Emission =
6918 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6919 CGF.EmitAutoVarCleanups(Emission);
6920 }
6921 }
6922 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006923 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads());
Alexey Bataev5c427362019-04-10 19:11:33 +00006924 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006925 /*isSigned=*/false);
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006926 if (DefaultThreadLimitVal)
6927 NumThreads = CGF.Builder.CreateSelect(
6928 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads),
6929 DefaultThreadLimitVal, NumThreads);
6930 } else {
6931 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal
6932 : CGF.Builder.getInt32(0);
Alexey Bataev5c427362019-04-10 19:11:33 +00006933 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006934 // Process condition of the if clause.
6935 if (CondVal) {
6936 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads,
6937 CGF.Builder.getInt32(1));
6938 }
6939 return NumThreads;
Alexey Bataev5c427362019-04-10 19:11:33 +00006940 }
6941 if (isOpenMPSimdDirective(Dir->getDirectiveKind()))
6942 return CGF.Builder.getInt32(1);
6943 return DefaultThreadLimitVal;
6944 }
6945 return DefaultThreadLimitVal ? DefaultThreadLimitVal
6946 : CGF.Builder.getInt32(0);
Samuel Antaob68e2db2016-03-03 16:20:23 +00006947}
6948
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006949/// Emit the number of threads for a target directive. Inspect the
6950/// thread_limit clause associated with a teams construct combined or closely
6951/// nested with the target directive.
6952///
6953/// Emit the num_threads clause for directives such as 'target parallel' that
6954/// have no associated teams construct.
6955///
6956/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006957static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006958emitNumThreadsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006959 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006960 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6961 "Clauses associated with the teams directive expected to be emitted "
6962 "only for the host!");
6963 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6964 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6965 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006966 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006967 llvm::Value *ThreadLimitVal = nullptr;
6968 llvm::Value *NumThreadsVal = nullptr;
6969 switch (DirectiveKind) {
6970 case OMPD_target: {
6971 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6972 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6973 return NumThreads;
6974 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6975 CGF.getContext(), CS->getCapturedStmt());
6976 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6977 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) {
6978 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6979 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6980 const auto *ThreadLimitClause =
6981 Dir->getSingleClause<OMPThreadLimitClause>();
6982 CodeGenFunction::LexicalScope Scope(
6983 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange());
6984 if (const auto *PreInit =
6985 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6986 for (const auto *I : PreInit->decls()) {
6987 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6988 CGF.EmitVarDecl(cast<VarDecl>(*I));
6989 } else {
6990 CodeGenFunction::AutoVarEmission Emission =
6991 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6992 CGF.EmitAutoVarCleanups(Emission);
6993 }
6994 }
6995 }
6996 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6997 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6998 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00006999 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00007000 }
7001 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) &&
7002 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) {
7003 CS = Dir->getInnermostCapturedStmt();
7004 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
7005 CGF.getContext(), CS->getCapturedStmt());
7006 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
7007 }
7008 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) &&
7009 !isOpenMPSimdDirective(Dir->getDirectiveKind())) {
7010 CS = Dir->getInnermostCapturedStmt();
7011 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
7012 return NumThreads;
7013 }
7014 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind()))
7015 return Bld.getInt32(1);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00007016 }
Alexey Bataev5c427362019-04-10 19:11:33 +00007017 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
7018 }
7019 case OMPD_target_teams: {
7020 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
7021 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
7022 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
7023 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
7024 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
7025 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00007026 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00007027 }
7028 const CapturedStmt *CS = D.getInnermostCapturedStmt();
7029 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
7030 return NumThreads;
7031 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
7032 CGF.getContext(), CS->getCapturedStmt());
7033 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
7034 if (Dir->getDirectiveKind() == OMPD_distribute) {
7035 CS = Dir->getInnermostCapturedStmt();
7036 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
7037 return NumThreads;
7038 }
7039 }
7040 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
7041 }
7042 case OMPD_target_teams_distribute:
7043 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
7044 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
7045 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
7046 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
7047 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
7048 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00007049 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00007050 }
7051 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal);
7052 case OMPD_target_parallel:
7053 case OMPD_target_parallel_for:
7054 case OMPD_target_parallel_for_simd:
7055 case OMPD_target_teams_distribute_parallel_for:
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00007056 case OMPD_target_teams_distribute_parallel_for_simd: {
7057 llvm::Value *CondVal = nullptr;
7058 // Handle if clause. If if clause present, the number of threads is
7059 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
7060 if (D.hasClausesOfKind<OMPIfClause>()) {
7061 const OMPIfClause *IfClause = nullptr;
7062 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) {
7063 if (C->getNameModifier() == OMPD_unknown ||
7064 C->getNameModifier() == OMPD_parallel) {
7065 IfClause = C;
7066 break;
7067 }
7068 }
7069 if (IfClause) {
7070 const Expr *Cond = IfClause->getCondition();
7071 bool Result;
7072 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
7073 if (!Result)
7074 return Bld.getInt32(1);
7075 } else {
7076 CodeGenFunction::RunCleanupsScope Scope(CGF);
7077 CondVal = CGF.EvaluateExprAsBool(Cond);
7078 }
7079 }
7080 }
Alexey Bataev5c427362019-04-10 19:11:33 +00007081 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
7082 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
7083 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
7084 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
7085 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
7086 ThreadLimitVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00007087 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00007088 }
7089 if (D.hasClausesOfKind<OMPNumThreadsClause>()) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00007090 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
Alexey Bataev5c427362019-04-10 19:11:33 +00007091 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>();
7092 llvm::Value *NumThreads = CGF.EmitScalarExpr(
7093 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true);
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00007094 NumThreadsVal =
Rui Ueyama49a3ad22019-07-16 04:46:31 +00007095 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00007096 ThreadLimitVal = ThreadLimitVal
Alexey Bataev5c427362019-04-10 19:11:33 +00007097 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal,
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00007098 ThreadLimitVal),
7099 NumThreadsVal, ThreadLimitVal)
7100 : NumThreadsVal;
Alexey Bataev50a1c782017-12-01 21:31:08 +00007101 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00007102 if (!ThreadLimitVal)
7103 ThreadLimitVal = Bld.getInt32(0);
7104 if (CondVal)
7105 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1));
7106 return ThreadLimitVal;
7107 }
Alexey Bataev5c427362019-04-10 19:11:33 +00007108 case OMPD_target_teams_distribute_simd:
7109 case OMPD_target_simd:
7110 return Bld.getInt32(1);
7111 case OMPD_parallel:
7112 case OMPD_for:
7113 case OMPD_parallel_for:
7114 case OMPD_parallel_sections:
7115 case OMPD_for_simd:
7116 case OMPD_parallel_for_simd:
7117 case OMPD_cancel:
7118 case OMPD_cancellation_point:
7119 case OMPD_ordered:
7120 case OMPD_threadprivate:
7121 case OMPD_allocate:
7122 case OMPD_task:
7123 case OMPD_simd:
7124 case OMPD_sections:
7125 case OMPD_section:
7126 case OMPD_single:
7127 case OMPD_master:
7128 case OMPD_critical:
7129 case OMPD_taskyield:
7130 case OMPD_barrier:
7131 case OMPD_taskwait:
7132 case OMPD_taskgroup:
7133 case OMPD_atomic:
7134 case OMPD_flush:
7135 case OMPD_teams:
7136 case OMPD_target_data:
7137 case OMPD_target_exit_data:
7138 case OMPD_target_enter_data:
7139 case OMPD_distribute:
7140 case OMPD_distribute_simd:
7141 case OMPD_distribute_parallel_for:
7142 case OMPD_distribute_parallel_for_simd:
7143 case OMPD_teams_distribute:
7144 case OMPD_teams_distribute_simd:
7145 case OMPD_teams_distribute_parallel_for:
7146 case OMPD_teams_distribute_parallel_for_simd:
7147 case OMPD_target_update:
7148 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00007149 case OMPD_declare_variant:
Alexey Bataev5c427362019-04-10 19:11:33 +00007150 case OMPD_declare_target:
7151 case OMPD_end_declare_target:
7152 case OMPD_declare_reduction:
7153 case OMPD_declare_mapper:
7154 case OMPD_taskloop:
7155 case OMPD_taskloop_simd:
7156 case OMPD_requires:
7157 case OMPD_unknown:
7158 break;
Samuel Antaob68e2db2016-03-03 16:20:23 +00007159 }
Alexey Bataev5c427362019-04-10 19:11:33 +00007160 llvm_unreachable("Unsupported directive kind.");
Samuel Antaob68e2db2016-03-03 16:20:23 +00007161}
7162
Samuel Antao86ace552016-04-27 22:40:57 +00007163namespace {
Alexey Bataevb3638132018-07-19 16:34:13 +00007164LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
7165
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007166// Utility to handle information from clauses associated with a given
Samuel Antao86ace552016-04-27 22:40:57 +00007167// construct that use mappable expressions (e.g. 'map' clause, 'to' clause).
7168// It provides a convenient interface to obtain the information and generate
7169// code for that information.
7170class MappableExprsHandler {
7171public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007172 /// Values for bit flags used to specify the mapping type for
Samuel Antao86ace552016-04-27 22:40:57 +00007173 /// offloading.
Alexey Bataevb3638132018-07-19 16:34:13 +00007174 enum OpenMPOffloadMappingFlags : uint64_t {
7175 /// No flags
7176 OMP_MAP_NONE = 0x0,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007177 /// Allocate memory on the device and move data from host to device.
Samuel Antao86ace552016-04-27 22:40:57 +00007178 OMP_MAP_TO = 0x01,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007179 /// Allocate memory on the device and move data from device to host.
Samuel Antao86ace552016-04-27 22:40:57 +00007180 OMP_MAP_FROM = 0x02,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007181 /// Always perform the requested mapping action on the element, even
Samuel Antao86ace552016-04-27 22:40:57 +00007182 /// if it was already mapped before.
7183 OMP_MAP_ALWAYS = 0x04,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007184 /// Delete the element from the device environment, ignoring the
Samuel Antao86ace552016-04-27 22:40:57 +00007185 /// current reference count associated with the element.
Samuel Antao6782e942016-05-26 16:48:10 +00007186 OMP_MAP_DELETE = 0x08,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007187 /// The element being mapped is a pointer-pointee pair; both the
George Rokos065755d2017-11-07 18:27:04 +00007188 /// pointer and the pointee should be mapped.
7189 OMP_MAP_PTR_AND_OBJ = 0x10,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007190 /// This flags signals that the base address of an entry should be
George Rokos065755d2017-11-07 18:27:04 +00007191 /// passed to the target kernel as an argument.
7192 OMP_MAP_TARGET_PARAM = 0x20,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007193 /// Signal that the runtime library has to return the device pointer
George Rokos065755d2017-11-07 18:27:04 +00007194 /// in the current position for the data being mapped. Used when we have the
7195 /// use_device_ptr clause.
7196 OMP_MAP_RETURN_PARAM = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007197 /// This flag signals that the reference being passed is a pointer to
Samuel Antaod486f842016-05-26 16:53:38 +00007198 /// private data.
George Rokos065755d2017-11-07 18:27:04 +00007199 OMP_MAP_PRIVATE = 0x80,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007200 /// Pass the element to the device by value.
George Rokos065755d2017-11-07 18:27:04 +00007201 OMP_MAP_LITERAL = 0x100,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007202 /// Implicit map
7203 OMP_MAP_IMPLICIT = 0x200,
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007204 /// Close is a hint to the runtime to allocate memory close to
7205 /// the target device.
7206 OMP_MAP_CLOSE = 0x400,
Alexey Bataevb3638132018-07-19 16:34:13 +00007207 /// The 16 MSBs of the flags indicate whether the entry is member of some
7208 /// struct/class.
7209 OMP_MAP_MEMBER_OF = 0xffff000000000000,
7210 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF),
Samuel Antao86ace552016-04-27 22:40:57 +00007211 };
7212
Michael Krused47b9432019-08-05 18:43:21 +00007213 /// Get the offset of the OMP_MAP_MEMBER_OF field.
7214 static unsigned getFlagMemberOffset() {
7215 unsigned Offset = 0;
7216 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1);
7217 Remain = Remain >> 1)
7218 Offset++;
7219 return Offset;
7220 }
7221
Samuel Antaocc10b852016-07-28 14:23:26 +00007222 /// Class that associates information with a base pointer to be passed to the
7223 /// runtime library.
7224 class BasePointerInfo {
7225 /// The base pointer.
7226 llvm::Value *Ptr = nullptr;
7227 /// The base declaration that refers to this device pointer, or null if
7228 /// there is none.
7229 const ValueDecl *DevPtrDecl = nullptr;
7230
7231 public:
7232 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr)
7233 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {}
7234 llvm::Value *operator*() const { return Ptr; }
7235 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; }
7236 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; }
7237 };
7238
Alexey Bataevb3638132018-07-19 16:34:13 +00007239 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>;
7240 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>;
7241 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>;
7242
7243 /// Map between a struct and the its lowest & highest elements which have been
7244 /// mapped.
7245 /// [ValueDecl *] --> {LE(FieldIndex, Pointer),
7246 /// HE(FieldIndex, Pointer)}
7247 struct StructRangeInfoTy {
7248 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = {
7249 0, Address::invalid()};
7250 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = {
7251 0, Address::invalid()};
7252 Address Base = Address::invalid();
7253 };
Samuel Antao86ace552016-04-27 22:40:57 +00007254
7255private:
Alexey Bataevb3638132018-07-19 16:34:13 +00007256 /// Kind that defines how a device pointer has to be returned.
7257 struct MapInfo {
7258 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
7259 OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
Kelvin Lief579432018-12-18 22:18:41 +00007260 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataevb3638132018-07-19 16:34:13 +00007261 bool ReturnDevicePointer = false;
7262 bool IsImplicit = false;
7263
7264 MapInfo() = default;
7265 MapInfo(
7266 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Kelvin Lief579432018-12-18 22:18:41 +00007267 OpenMPMapClauseKind MapType,
7268 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007269 bool ReturnDevicePointer, bool IsImplicit)
Kelvin Lief579432018-12-18 22:18:41 +00007270 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
Alexey Bataevb3638132018-07-19 16:34:13 +00007271 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {}
7272 };
7273
7274 /// If use_device_ptr is used on a pointer which is a struct member and there
7275 /// is no map information about it, then emission of that entry is deferred
7276 /// until the whole struct has been processed.
7277 struct DeferredDevicePtrEntryTy {
7278 const Expr *IE = nullptr;
7279 const ValueDecl *VD = nullptr;
7280
7281 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD)
7282 : IE(IE), VD(VD) {}
7283 };
7284
Michael Krused47b9432019-08-05 18:43:21 +00007285 /// The target directive from where the mappable clauses were extracted. It
7286 /// is either a executable directive or a user-defined mapper directive.
7287 llvm::PointerUnion<const OMPExecutableDirective *,
7288 const OMPDeclareMapperDecl *>
7289 CurDir;
Samuel Antao86ace552016-04-27 22:40:57 +00007290
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007291 /// Function the directive is being generated for.
Samuel Antao86ace552016-04-27 22:40:57 +00007292 CodeGenFunction &CGF;
7293
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007294 /// Set of all first private variables in the current directive.
Alexey Bataevf288cf92019-06-27 18:53:07 +00007295 /// bool data is set to true if the variable is implicitly marked as
7296 /// firstprivate, false otherwise.
7297 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls;
Samuel Antaod486f842016-05-26 16:53:38 +00007298
Samuel Antao6890b092016-07-28 14:25:09 +00007299 /// Map between device pointer declarations and their expression components.
7300 /// The key value for declarations in 'this' is null.
7301 llvm::DenseMap<
7302 const ValueDecl *,
7303 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7304 DevPointersMap;
7305
Samuel Antao86ace552016-04-27 22:40:57 +00007306 llvm::Value *getExprTypeSize(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007307 QualType ExprTy = E->getType().getCanonicalType();
Samuel Antao86ace552016-04-27 22:40:57 +00007308
7309 // Reference types are ignored for mapping purposes.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007310 if (const auto *RefTy = ExprTy->getAs<ReferenceType>())
Samuel Antao86ace552016-04-27 22:40:57 +00007311 ExprTy = RefTy->getPointeeType().getCanonicalType();
7312
7313 // Given that an array section is considered a built-in type, we need to
7314 // do the calculation based on the length of the section instead of relying
7315 // on CGF.getTypeSize(E->getType()).
7316 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) {
7317 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType(
7318 OAE->getBase()->IgnoreParenImpCasts())
7319 .getCanonicalType();
7320
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007321 // If there is no length associated with the expression and lower bound is
7322 // not specified too, that means we are using the whole length of the
7323 // base.
7324 if (!OAE->getLength() && OAE->getColonLoc().isValid() &&
7325 !OAE->getLowerBound())
Samuel Antao86ace552016-04-27 22:40:57 +00007326 return CGF.getTypeSize(BaseTy);
7327
7328 llvm::Value *ElemSize;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007329 if (const auto *PTy = BaseTy->getAs<PointerType>()) {
Samuel Antao86ace552016-04-27 22:40:57 +00007330 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007331 } else {
7332 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr());
Samuel Antao86ace552016-04-27 22:40:57 +00007333 assert(ATy && "Expecting array type if not a pointer type.");
7334 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType());
7335 }
7336
7337 // If we don't have a length at this point, that is because we have an
7338 // array section with a single element.
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007339 if (!OAE->getLength() && OAE->getColonLoc().isInvalid())
Samuel Antao86ace552016-04-27 22:40:57 +00007340 return ElemSize;
7341
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007342 if (const Expr *LenExpr = OAE->getLength()) {
Michael Liaod838cf72019-10-02 00:22:45 +00007343 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr);
7344 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(),
7345 CGF.getContext().getSizeType(),
7346 LenExpr->getExprLoc());
Alexey Bataevb9b8ca22019-10-01 18:18:03 +00007347 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize);
7348 }
7349 assert(!OAE->getLength() && OAE->getColonLoc().isValid() &&
7350 OAE->getLowerBound() && "expected array_section[lb:].");
7351 // Size = sizetype - lb * elemtype;
7352 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy);
7353 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound());
7354 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(),
7355 CGF.getContext().getSizeType(),
7356 OAE->getLowerBound()->getExprLoc());
7357 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize);
7358 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal);
7359 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal);
7360 LengthVal = CGF.Builder.CreateSelect(
7361 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0));
7362 return LengthVal;
Samuel Antao86ace552016-04-27 22:40:57 +00007363 }
7364 return CGF.getTypeSize(ExprTy);
7365 }
7366
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007367 /// Return the corresponding bits for a given map clause modifier. Add
Samuel Antao86ace552016-04-27 22:40:57 +00007368 /// a flag marking the map as a pointer if requested. Add a flag marking the
Samuel Antao6782e942016-05-26 16:48:10 +00007369 /// map as the first one of a series of maps that relate to the same map
7370 /// expression.
Kelvin Lief579432018-12-18 22:18:41 +00007371 OpenMPOffloadMappingFlags getMapTypeBits(
7372 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
7373 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const {
Alexey Bataevb3638132018-07-19 16:34:13 +00007374 OpenMPOffloadMappingFlags Bits =
7375 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE;
Samuel Antao86ace552016-04-27 22:40:57 +00007376 switch (MapType) {
7377 case OMPC_MAP_alloc:
Samuel Antao6782e942016-05-26 16:48:10 +00007378 case OMPC_MAP_release:
7379 // alloc and release is the default behavior in the runtime library, i.e.
7380 // if we don't pass any bits alloc/release that is what the runtime is
7381 // going to do. Therefore, we don't need to signal anything for these two
7382 // type modifiers.
Samuel Antao86ace552016-04-27 22:40:57 +00007383 break;
7384 case OMPC_MAP_to:
Alexey Bataevb3638132018-07-19 16:34:13 +00007385 Bits |= OMP_MAP_TO;
Samuel Antao86ace552016-04-27 22:40:57 +00007386 break;
7387 case OMPC_MAP_from:
Alexey Bataevb3638132018-07-19 16:34:13 +00007388 Bits |= OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007389 break;
7390 case OMPC_MAP_tofrom:
Alexey Bataevb3638132018-07-19 16:34:13 +00007391 Bits |= OMP_MAP_TO | OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007392 break;
7393 case OMPC_MAP_delete:
Alexey Bataevb3638132018-07-19 16:34:13 +00007394 Bits |= OMP_MAP_DELETE;
Samuel Antao86ace552016-04-27 22:40:57 +00007395 break;
Alexey Bataevb3638132018-07-19 16:34:13 +00007396 case OMPC_MAP_unknown:
Samuel Antao86ace552016-04-27 22:40:57 +00007397 llvm_unreachable("Unexpected map type!");
Samuel Antao86ace552016-04-27 22:40:57 +00007398 }
7399 if (AddPtrFlag)
George Rokos065755d2017-11-07 18:27:04 +00007400 Bits |= OMP_MAP_PTR_AND_OBJ;
7401 if (AddIsTargetParamFlag)
7402 Bits |= OMP_MAP_TARGET_PARAM;
Kelvin Lief579432018-12-18 22:18:41 +00007403 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always)
7404 != MapModifiers.end())
Samuel Antao86ace552016-04-27 22:40:57 +00007405 Bits |= OMP_MAP_ALWAYS;
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007406 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close)
7407 != MapModifiers.end())
7408 Bits |= OMP_MAP_CLOSE;
Samuel Antao86ace552016-04-27 22:40:57 +00007409 return Bits;
7410 }
7411
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007412 /// Return true if the provided expression is a final array section. A
Samuel Antao86ace552016-04-27 22:40:57 +00007413 /// final array section, is one whose length can't be proved to be one.
7414 bool isFinalArraySectionExpression(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007415 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
Samuel Antao86ace552016-04-27 22:40:57 +00007416
7417 // It is not an array section and therefore not a unity-size one.
7418 if (!OASE)
7419 return false;
7420
7421 // An array section with no colon always refer to a single element.
7422 if (OASE->getColonLoc().isInvalid())
7423 return false;
7424
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007425 const Expr *Length = OASE->getLength();
Samuel Antao86ace552016-04-27 22:40:57 +00007426
7427 // If we don't have a length we have to check if the array has size 1
7428 // for this dimension. Also, we should always expect a length if the
7429 // base type is pointer.
7430 if (!Length) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007431 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType(
7432 OASE->getBase()->IgnoreParenImpCasts())
7433 .getCanonicalType();
7434 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
Samuel Antao86ace552016-04-27 22:40:57 +00007435 return ATy->getSize().getSExtValue() != 1;
7436 // If we don't have a constant dimension length, we have to consider
7437 // the current section as having any size, so it is not necessarily
7438 // unitary. If it happen to be unity size, that's user fault.
7439 return true;
7440 }
7441
7442 // Check if the length evaluates to 1.
Fangrui Song407659a2018-11-30 23:41:18 +00007443 Expr::EvalResult Result;
7444 if (!Length->EvaluateAsInt(Result, CGF.getContext()))
Samuel Antao86ace552016-04-27 22:40:57 +00007445 return true; // Can have more that size 1.
7446
Fangrui Song407659a2018-11-30 23:41:18 +00007447 llvm::APSInt ConstLength = Result.Val.getInt();
Samuel Antao86ace552016-04-27 22:40:57 +00007448 return ConstLength.getSExtValue() != 1;
7449 }
7450
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007451 /// Generate the base pointers, section pointers, sizes and map type
Samuel Antao86ace552016-04-27 22:40:57 +00007452 /// bits for the provided map type, map modifier, and expression components.
7453 /// \a IsFirstComponent should be set to true if the provided set of
7454 /// components is the first associated with a capture.
7455 void generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00007456 OpenMPMapClauseKind MapType,
7457 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Samuel Antao86ace552016-04-27 22:40:57 +00007458 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Samuel Antaocc10b852016-07-28 14:23:26 +00007459 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007460 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
Alexey Bataevb3638132018-07-19 16:34:13 +00007461 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007462 bool IsImplicit,
7463 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7464 OverlappedElements = llvm::None) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007465 // The following summarizes what has to be generated for each map and the
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00007466 // types below. The generated information is expressed in this order:
Samuel Antao86ace552016-04-27 22:40:57 +00007467 // base pointer, section pointer, size, flags
7468 // (to add to the ones that come from the map type and modifier).
7469 //
7470 // double d;
7471 // int i[100];
7472 // float *p;
7473 //
7474 // struct S1 {
7475 // int i;
7476 // float f[50];
7477 // }
7478 // struct S2 {
7479 // int i;
7480 // float f[50];
7481 // S1 s;
7482 // double *p;
7483 // struct S2 *ps;
7484 // }
7485 // S2 s;
7486 // S2 *ps;
7487 //
7488 // map(d)
Alexey Bataevb3638132018-07-19 16:34:13 +00007489 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007490 //
7491 // map(i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007492 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007493 //
7494 // map(i[1:23])
Alexey Bataevb3638132018-07-19 16:34:13 +00007495 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007496 //
7497 // map(p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007498 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007499 //
7500 // map(p[1:24])
Alexey Bataevb3638132018-07-19 16:34:13 +00007501 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007502 //
7503 // map(s)
Alexey Bataevb3638132018-07-19 16:34:13 +00007504 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007505 //
7506 // map(s.i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007507 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007508 //
7509 // map(s.s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007510 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007511 //
7512 // map(s.p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007513 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007514 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007515 // map(to: s.p[:22])
7516 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*)
7517 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**)
7518 // &(s.p), &(s.p[0]), 22*sizeof(double),
7519 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***)
7520 // (*) alloc space for struct members, only this is a target parameter
7521 // (**) map the pointer (nothing to be mapped in this example) (the compiler
7522 // optimizes this entry out, same in the examples below)
7523 // (***) map the pointee (map: to)
Samuel Antao86ace552016-04-27 22:40:57 +00007524 //
7525 // map(s.ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007526 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007527 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007528 // map(from: s.ps->s.i)
7529 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7530 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7531 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007532 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007533 // map(to: s.ps->ps)
7534 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7535 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7536 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007537 //
7538 // map(s.ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007539 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7540 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7541 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7542 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007543 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007544 // map(to: s.ps->ps->s.f[:22])
7545 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7546 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7547 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7548 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007549 //
7550 // map(ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007551 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007552 //
7553 // map(ps->i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007554 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007555 //
7556 // map(ps->s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007557 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007558 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007559 // map(from: ps->p)
7560 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007561 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007562 // map(to: ps->p[:22])
7563 // ps, &(ps->p), sizeof(double*), TARGET_PARAM
7564 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1)
7565 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007566 //
7567 // map(ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007568 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007569 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007570 // map(from: ps->ps->s.i)
7571 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7572 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7573 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007574 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007575 // map(from: ps->ps->ps)
7576 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7577 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7578 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007579 //
7580 // map(ps->ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007581 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7582 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7583 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7584 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007585 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007586 // map(to: ps->ps->ps->s.f[:22])
7587 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7588 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7589 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7590 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
7591 //
7592 // map(to: s.f[:22]) map(from: s.p[:33])
7593 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) +
7594 // sizeof(double*) (**), TARGET_PARAM
7595 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO
7596 // &s, &(s.p), sizeof(double*), MEMBER_OF(1)
7597 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7598 // (*) allocate contiguous space needed to fit all mapped members even if
7599 // we allocate space for members not mapped (in this example,
7600 // s.f[22..49] and s.s are not mapped, yet we must allocate space for
7601 // them as well because they fall between &s.f[0] and &s.p)
7602 //
7603 // map(from: s.f[:22]) map(to: ps->p[:33])
7604 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM
7605 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7606 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*)
7607 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO
7608 // (*) the struct this entry pertains to is the 2nd element in the list of
7609 // arguments, hence MEMBER_OF(2)
7610 //
7611 // map(from: s.f[:22], s.s) map(to: ps->p[:33])
7612 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM
7613 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM
7614 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM
7615 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7616 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*)
7617 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO
7618 // (*) the struct this entry pertains to is the 4th element in the list
7619 // of arguments, hence MEMBER_OF(4)
Samuel Antao86ace552016-04-27 22:40:57 +00007620
7621 // Track if the map information being generated is the first for a capture.
7622 bool IsCaptureFirstInfo = IsFirstComponentList;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007623 // When the variable is on a declare target link or in a to clause with
7624 // unified memory, a reference is needed to hold the host/device address
7625 // of the variable.
7626 bool RequiresReference = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007627
7628 // Scan the components from the base to the complete expression.
7629 auto CI = Components.rbegin();
7630 auto CE = Components.rend();
7631 auto I = CI;
7632
7633 // Track if the map information being generated is the first for a list of
7634 // components.
7635 bool IsExpressionFirstInfo = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00007636 Address BP = Address::invalid();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007637 const Expr *AssocExpr = I->getAssociatedExpression();
7638 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7639 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
Samuel Antao86ace552016-04-27 22:40:57 +00007640
Patrick Lystere13b1e32019-01-02 19:28:48 +00007641 if (isa<MemberExpr>(AssocExpr)) {
Samuel Antao86ace552016-04-27 22:40:57 +00007642 // The base is the 'this' pointer. The content of the pointer is going
7643 // to be the base of the field being mapped.
Alexey Bataevb3638132018-07-19 16:34:13 +00007644 BP = CGF.LoadCXXThisAddress();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007645 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7646 (OASE &&
7647 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
7648 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
Samuel Antao86ace552016-04-27 22:40:57 +00007649 } else {
7650 // The base is the reference to the variable.
7651 // BP = &Var.
Patrick Lystere13b1e32019-01-02 19:28:48 +00007652 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
Alexey Bataev92327c52018-03-26 16:40:55 +00007653 if (const auto *VD =
7654 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7655 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007656 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
7657 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
7658 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
7659 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) {
7660 RequiresReference = true;
7661 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataev2c1dffe2018-04-16 20:34:41 +00007662 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007663 }
Alexey Bataev92327c52018-03-26 16:40:55 +00007664 }
Samuel Antao86ace552016-04-27 22:40:57 +00007665
7666 // If the variable is a pointer and is being dereferenced (i.e. is not
Nico Webera6916892016-06-10 18:53:04 +00007667 // the last component), the base has to be the pointer itself, not its
Samuel Antao403ffd42016-07-27 22:49:49 +00007668 // reference. References are ignored for mapping purposes.
7669 QualType Ty =
7670 I->getAssociatedDeclaration()->getType().getNonReferenceType();
7671 if (Ty->isAnyPointerType() && std::next(I) != CE) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007672 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
Samuel Antao86ace552016-04-27 22:40:57 +00007673
7674 // We do not need to generate individual map information for the
7675 // pointer, it can be associated with the combined storage.
7676 ++I;
7677 }
7678 }
7679
Alexey Bataevb3638132018-07-19 16:34:13 +00007680 // Track whether a component of the list should be marked as MEMBER_OF some
7681 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry
7682 // in a component list should be marked as MEMBER_OF, all subsequent entries
7683 // do not belong to the base struct. E.g.
7684 // struct S2 s;
7685 // s.ps->ps->ps->f[:]
7686 // (1) (2) (3) (4)
7687 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a
7688 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3)
7689 // is the pointee of ps(2) which is not member of struct s, so it should not
7690 // be marked as such (it is still PTR_AND_OBJ).
7691 // The variable is initialized to false so that PTR_AND_OBJ entries which
7692 // are not struct members are not considered (e.g. array of pointers to
7693 // data).
7694 bool ShouldBeMemberOf = false;
7695
7696 // Variable keeping track of whether or not we have encountered a component
7697 // in the component list which is a member expression. Useful when we have a
7698 // pointer or a final array section, in which case it is the previous
7699 // component in the list which tells us whether we have a member expression.
7700 // E.g. X.f[:]
7701 // While processing the final array section "[:]" it is "f" which tells us
7702 // whether we are dealing with a member of a declared struct.
7703 const MemberExpr *EncounteredME = nullptr;
7704
Samuel Antao86ace552016-04-27 22:40:57 +00007705 for (; I != CE; ++I) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007706 // If the current component is member of a struct (parent struct) mark it.
7707 if (!EncounteredME) {
7708 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7709 // If we encounter a PTR_AND_OBJ entry from now on it should be marked
7710 // as MEMBER_OF the parent struct.
7711 if (EncounteredME)
7712 ShouldBeMemberOf = true;
7713 }
7714
Samuel Antao86ace552016-04-27 22:40:57 +00007715 auto Next = std::next(I);
7716
7717 // We need to generate the addresses and sizes if this is the last
7718 // component, if the component is a pointer or if it is an array section
7719 // whose length can't be proved to be one. If this is a pointer, it
7720 // becomes the base address for the following components.
7721
7722 // A final array section, is one whose length can't be proved to be one.
7723 bool IsFinalArraySection =
7724 isFinalArraySectionExpression(I->getAssociatedExpression());
7725
7726 // Get information on whether the element is a pointer. Have to do a
7727 // special treatment for array sections given that they are built-in
7728 // types.
7729 const auto *OASE =
7730 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression());
7731 bool IsPointer =
Alexey Bataevb3638132018-07-19 16:34:13 +00007732 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE)
7733 .getCanonicalType()
7734 ->isAnyPointerType()) ||
Samuel Antao86ace552016-04-27 22:40:57 +00007735 I->getAssociatedExpression()->getType()->isAnyPointerType();
7736
7737 if (Next == CE || IsPointer || IsFinalArraySection) {
Samuel Antao86ace552016-04-27 22:40:57 +00007738 // If this is not the last component, we expect the pointer to be
7739 // associated with an array expression or member expression.
7740 assert((Next == CE ||
7741 isa<MemberExpr>(Next->getAssociatedExpression()) ||
7742 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||
7743 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) &&
7744 "Unexpected expression");
7745
Alexey Bataevb3638132018-07-19 16:34:13 +00007746 Address LB =
7747 CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getAddress();
Samuel Antao86ace552016-04-27 22:40:57 +00007748
Alexey Bataevb3638132018-07-19 16:34:13 +00007749 // If this component is a pointer inside the base struct then we don't
7750 // need to create any entry for it - it will be combined with the object
7751 // it is pointing to into a single PTR_AND_OBJ entry.
7752 bool IsMemberPointer =
7753 IsPointer && EncounteredME &&
7754 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) ==
7755 EncounteredME);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007756 if (!OverlappedElements.empty()) {
7757 // Handle base element with the info for overlapped elements.
7758 assert(!PartialStruct.Base.isValid() && "The base element is set.");
7759 assert(Next == CE &&
7760 "Expected last element for the overlapped elements.");
7761 assert(!IsPointer &&
7762 "Unexpected base element with the pointer type.");
7763 // Mark the whole struct as the struct that requires allocation on the
7764 // device.
7765 PartialStruct.LowestElem = {0, LB};
7766 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(
7767 I->getAssociatedExpression()->getType());
7768 Address HB = CGF.Builder.CreateConstGEP(
7769 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB,
7770 CGF.VoidPtrTy),
James Y Knight751fe282019-02-09 22:22:28 +00007771 TypeSize.getQuantity() - 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007772 PartialStruct.HighestElem = {
7773 std::numeric_limits<decltype(
7774 PartialStruct.HighestElem.first)>::max(),
7775 HB};
7776 PartialStruct.Base = BP;
7777 // Emit data for non-overlapped data.
7778 OpenMPOffloadMappingFlags Flags =
7779 OMP_MAP_MEMBER_OF |
Kelvin Lief579432018-12-18 22:18:41 +00007780 getMapTypeBits(MapType, MapModifiers, IsImplicit,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007781 /*AddPtrFlag=*/false,
7782 /*AddIsTargetParamFlag=*/false);
7783 LB = BP;
7784 llvm::Value *Size = nullptr;
7785 // Do bitcopy of all non-overlapped structure elements.
7786 for (OMPClauseMappableExprCommon::MappableExprComponentListRef
7787 Component : OverlappedElements) {
7788 Address ComponentLB = Address::invalid();
7789 for (const OMPClauseMappableExprCommon::MappableComponent &MC :
7790 Component) {
7791 if (MC.getAssociatedDeclaration()) {
7792 ComponentLB =
7793 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
7794 .getAddress();
7795 Size = CGF.Builder.CreatePtrDiff(
7796 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()),
7797 CGF.EmitCastToVoidPtr(LB.getPointer()));
7798 break;
7799 }
7800 }
7801 BasePointers.push_back(BP.getPointer());
7802 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007803 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty,
7804 /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007805 Types.push_back(Flags);
James Y Knight751fe282019-02-09 22:22:28 +00007806 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007807 }
7808 BasePointers.push_back(BP.getPointer());
7809 Pointers.push_back(LB.getPointer());
7810 Size = CGF.Builder.CreatePtrDiff(
7811 CGF.EmitCastToVoidPtr(
James Y Knight751fe282019-02-09 22:22:28 +00007812 CGF.Builder.CreateConstGEP(HB, 1).getPointer()),
Alexey Bataeve82445f2018-09-20 13:54:02 +00007813 CGF.EmitCastToVoidPtr(LB.getPointer()));
Alexey Bataeva90fc662019-06-25 16:00:43 +00007814 Sizes.push_back(
7815 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataeve82445f2018-09-20 13:54:02 +00007816 Types.push_back(Flags);
7817 break;
7818 }
7819 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
Alexey Bataevb3638132018-07-19 16:34:13 +00007820 if (!IsMemberPointer) {
7821 BasePointers.push_back(BP.getPointer());
7822 Pointers.push_back(LB.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00007823 Sizes.push_back(
7824 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true));
Samuel Antao03a3cec2016-07-27 22:52:16 +00007825
Alexey Bataevb3638132018-07-19 16:34:13 +00007826 // We need to add a pointer flag for each map that comes from the
7827 // same expression except for the first one. We also need to signal
7828 // this map is the first one that relates with the current capture
7829 // (there is a set of entries for each capture).
7830 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
Kelvin Lief579432018-12-18 22:18:41 +00007831 MapType, MapModifiers, IsImplicit,
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00007832 !IsExpressionFirstInfo || RequiresReference,
7833 IsCaptureFirstInfo && !RequiresReference);
Alexey Bataevb3638132018-07-19 16:34:13 +00007834
7835 if (!IsExpressionFirstInfo) {
7836 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007837 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags.
Alexey Bataevb3638132018-07-19 16:34:13 +00007838 if (IsPointer)
7839 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS |
Gheorghe-Teodor Bercea0fd073b2019-08-09 21:42:13 +00007840 OMP_MAP_DELETE | OMP_MAP_CLOSE);
Alexey Bataevb3638132018-07-19 16:34:13 +00007841
7842 if (ShouldBeMemberOf) {
7843 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag
7844 // should be later updated with the correct value of MEMBER_OF.
7845 Flags |= OMP_MAP_MEMBER_OF;
7846 // From now on, all subsequent PTR_AND_OBJ entries should not be
7847 // marked as MEMBER_OF.
7848 ShouldBeMemberOf = false;
7849 }
7850 }
7851
7852 Types.push_back(Flags);
Samuel Antao03a3cec2016-07-27 22:52:16 +00007853 }
7854
Alexey Bataevb3638132018-07-19 16:34:13 +00007855 // If we have encountered a member expression so far, keep track of the
7856 // mapped member. If the parent is "*this", then the value declaration
7857 // is nullptr.
7858 if (EncounteredME) {
7859 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl());
7860 unsigned FieldIndex = FD->getFieldIndex();
Samuel Antao03a3cec2016-07-27 22:52:16 +00007861
Alexey Bataevb3638132018-07-19 16:34:13 +00007862 // Update info about the lowest and highest elements for this struct
7863 if (!PartialStruct.Base.isValid()) {
7864 PartialStruct.LowestElem = {FieldIndex, LB};
7865 PartialStruct.HighestElem = {FieldIndex, LB};
7866 PartialStruct.Base = BP;
7867 } else if (FieldIndex < PartialStruct.LowestElem.first) {
7868 PartialStruct.LowestElem = {FieldIndex, LB};
7869 } else if (FieldIndex > PartialStruct.HighestElem.first) {
7870 PartialStruct.HighestElem = {FieldIndex, LB};
7871 }
7872 }
Samuel Antao86ace552016-04-27 22:40:57 +00007873
7874 // If we have a final array section, we are done with this expression.
7875 if (IsFinalArraySection)
7876 break;
7877
7878 // The pointer becomes the base for the next element.
7879 if (Next != CE)
7880 BP = LB;
7881
7882 IsExpressionFirstInfo = false;
7883 IsCaptureFirstInfo = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007884 }
7885 }
7886 }
7887
Alexey Bataevb3638132018-07-19 16:34:13 +00007888 /// Return the adjusted map modifiers if the declaration a capture refers to
7889 /// appears in a first-private clause. This is expected to be used only with
7890 /// directives that start with 'target'.
7891 MappableExprsHandler::OpenMPOffloadMappingFlags
7892 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const {
7893 assert(Cap.capturesVariable() && "Expected capture by reference only!");
7894
7895 // A first private variable captured by reference will use only the
7896 // 'private ptr' and 'map to' flag. Return the right flags if the captured
7897 // declaration is known as first-private in this handler.
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007898 if (FirstPrivateDecls.count(Cap.getCapturedVar())) {
7899 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) &&
7900 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef)
7901 return MappableExprsHandler::OMP_MAP_ALWAYS |
7902 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataevc2b831f2019-04-02 16:03:40 +00007903 if (Cap.getCapturedVar()->getType()->isAnyPointerType())
7904 return MappableExprsHandler::OMP_MAP_TO |
7905 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ;
Alexey Bataevb3638132018-07-19 16:34:13 +00007906 return MappableExprsHandler::OMP_MAP_PRIVATE |
7907 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007908 }
Alexey Bataevb3638132018-07-19 16:34:13 +00007909 return MappableExprsHandler::OMP_MAP_TO |
7910 MappableExprsHandler::OMP_MAP_FROM;
7911 }
7912
7913 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) {
Michael Krused47b9432019-08-05 18:43:21 +00007914 // Rotate by getFlagMemberOffset() bits.
Alexey Bataevb3638132018-07-19 16:34:13 +00007915 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1)
Michael Krused47b9432019-08-05 18:43:21 +00007916 << getFlagMemberOffset());
Alexey Bataevb3638132018-07-19 16:34:13 +00007917 }
7918
7919 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags,
7920 OpenMPOffloadMappingFlags MemberOfFlag) {
7921 // If the entry is PTR_AND_OBJ but has not been marked with the special
7922 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be
7923 // marked as MEMBER_OF.
7924 if ((Flags & OMP_MAP_PTR_AND_OBJ) &&
7925 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF))
7926 return;
7927
7928 // Reset the placeholder value to prepare the flag for the assignment of the
7929 // proper MEMBER_OF value.
7930 Flags &= ~OMP_MAP_MEMBER_OF;
7931 Flags |= MemberOfFlag;
7932 }
7933
Alexey Bataeve82445f2018-09-20 13:54:02 +00007934 void getPlainLayout(const CXXRecordDecl *RD,
7935 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
7936 bool AsBase) const {
7937 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD);
7938
7939 llvm::StructType *St =
7940 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType();
7941
7942 unsigned NumElements = St->getNumElements();
7943 llvm::SmallVector<
7944 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
7945 RecordLayout(NumElements);
7946
7947 // Fill bases.
7948 for (const auto &I : RD->bases()) {
7949 if (I.isVirtual())
7950 continue;
7951 const auto *Base = I.getType()->getAsCXXRecordDecl();
7952 // Ignore empty bases.
7953 if (Base->isEmpty() || CGF.getContext()
7954 .getASTRecordLayout(Base)
7955 .getNonVirtualSize()
7956 .isZero())
7957 continue;
7958
7959 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
7960 RecordLayout[FieldIndex] = Base;
7961 }
7962 // Fill in virtual bases.
7963 for (const auto &I : RD->vbases()) {
7964 const auto *Base = I.getType()->getAsCXXRecordDecl();
7965 // Ignore empty bases.
7966 if (Base->isEmpty())
7967 continue;
7968 unsigned FieldIndex = RL.getVirtualBaseIndex(Base);
7969 if (RecordLayout[FieldIndex])
7970 continue;
7971 RecordLayout[FieldIndex] = Base;
7972 }
7973 // Fill in all the fields.
7974 assert(!RD->isUnion() && "Unexpected union.");
7975 for (const auto *Field : RD->fields()) {
7976 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
7977 // will fill in later.)
Richard Smith78b239e2019-06-20 20:44:45 +00007978 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) {
Alexey Bataeve82445f2018-09-20 13:54:02 +00007979 unsigned FieldIndex = RL.getLLVMFieldNo(Field);
7980 RecordLayout[FieldIndex] = Field;
7981 }
7982 }
7983 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
7984 &Data : RecordLayout) {
7985 if (Data.isNull())
7986 continue;
7987 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>())
7988 getPlainLayout(Base, Layout, /*AsBase=*/true);
7989 else
7990 Layout.push_back(Data.get<const FieldDecl *>());
7991 }
7992 }
7993
Alexey Bataevb3638132018-07-19 16:34:13 +00007994public:
7995 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
Michael Krused47b9432019-08-05 18:43:21 +00007996 : CurDir(&Dir), CGF(CGF) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007997 // Extract firstprivate clause information.
7998 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>())
7999 for (const auto *D : C->varlists())
Alexey Bataevf288cf92019-06-27 18:53:07 +00008000 FirstPrivateDecls.try_emplace(
8001 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit());
Alexey Bataevb3638132018-07-19 16:34:13 +00008002 // Extract device pointer clause information.
8003 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
8004 for (auto L : C->component_lists())
8005 DevPointersMap[L.first].push_back(L.second);
8006 }
8007
Michael Krused47b9432019-08-05 18:43:21 +00008008 /// Constructor for the declare mapper directive.
8009 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF)
8010 : CurDir(&Dir), CGF(CGF) {}
8011
Alexey Bataevb3638132018-07-19 16:34:13 +00008012 /// Generate code for the combined entry if we have a partially mapped struct
8013 /// and take care of the mapping flags of the arguments corresponding to
8014 /// individual struct members.
8015 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers,
8016 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
8017 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes,
8018 const StructRangeInfoTy &PartialStruct) const {
8019 // Base is the base of the struct
8020 BasePointers.push_back(PartialStruct.Base.getPointer());
8021 // Pointer is the address of the lowest element
8022 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer();
8023 Pointers.push_back(LB);
8024 // Size is (addr of {highest+1} element) - (addr of lowest element)
8025 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer();
8026 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1);
8027 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy);
8028 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy);
8029 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008030 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty,
Rui Ueyama49a3ad22019-07-16 04:46:31 +00008031 /*isSigned=*/false);
Alexey Bataevb3638132018-07-19 16:34:13 +00008032 Sizes.push_back(Size);
8033 // Map type is always TARGET_PARAM
8034 Types.push_back(OMP_MAP_TARGET_PARAM);
8035 // Remove TARGET_PARAM flag from the first element
8036 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM;
8037
8038 // All other current entries will be MEMBER_OF the combined entry
8039 // (except for PTR_AND_OBJ entries which do not have a placeholder value
8040 // 0xFFFF in the MEMBER_OF field).
8041 OpenMPOffloadMappingFlags MemberOfFlag =
8042 getMemberOfFlag(BasePointers.size() - 1);
8043 for (auto &M : CurTypes)
8044 setCorrectMemberOfFlag(M, MemberOfFlag);
8045 }
8046
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008047 /// Generate all the base pointers, section pointers, sizes and map
Samuel Antaocc10b852016-07-28 14:23:26 +00008048 /// types for the extracted mappable expressions. Also, for each item that
8049 /// relates with a device pointer, a pair of the relevant declaration and
8050 /// index where it occurs is appended to the device pointers info array.
8051 void generateAllInfo(MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00008052 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
8053 MapFlagsArrayTy &Types) const {
Samuel Antao86ace552016-04-27 22:40:57 +00008054 // We have to process the component lists that relate with the same
8055 // declaration in a single chunk so that we can generate the map flags
8056 // correctly. Therefore, we organize all lists in a map.
Alexey Bataev5d1c3f62017-06-27 15:46:42 +00008057 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
Samuel Antao8d2d7302016-05-26 18:30:22 +00008058
8059 // Helper function to fill the information map for the different supported
8060 // clauses.
Samuel Antaocc10b852016-07-28 14:23:26 +00008061 auto &&InfoGen = [&Info](
8062 const ValueDecl *D,
8063 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
Kelvin Lief579432018-12-18 22:18:41 +00008064 OpenMPMapClauseKind MapType,
8065 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008066 bool ReturnDevicePointer, bool IsImplicit) {
Samuel Antaocc10b852016-07-28 14:23:26 +00008067 const ValueDecl *VD =
8068 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
Kelvin Lief579432018-12-18 22:18:41 +00008069 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00008070 IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00008071 };
Samuel Antao8d2d7302016-05-26 18:30:22 +00008072
Michael Krused47b9432019-08-05 18:43:21 +00008073 assert(CurDir.is<const OMPExecutableDirective *>() &&
8074 "Expect a executable directive");
8075 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
8076 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008077 for (const auto &L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00008078 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(),
Alexey Bataevb3638132018-07-19 16:34:13 +00008079 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00008080 }
Michael Krused47b9432019-08-05 18:43:21 +00008081 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008082 for (const auto &L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00008083 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00008084 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00008085 }
Michael Krused47b9432019-08-05 18:43:21 +00008086 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008087 for (const auto &L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00008088 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00008089 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00008090 }
Samuel Antao86ace552016-04-27 22:40:57 +00008091
Samuel Antaocc10b852016-07-28 14:23:26 +00008092 // Look at the use_device_ptr clause information and mark the existing map
8093 // entries as such. If there is no map information for an entry in the
8094 // use_device_ptr list, we create one with map type 'alloc' and zero size
Alexey Bataevb3638132018-07-19 16:34:13 +00008095 // section. It is the user fault if that was not mapped before. If there is
8096 // no map information and the pointer is a struct member, then we defer the
8097 // emission of that entry until the whole struct has been processed.
8098 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>>
8099 DeferredInfo;
8100
Alexey Bataevb3638132018-07-19 16:34:13 +00008101 for (const auto *C :
Michael Krused47b9432019-08-05 18:43:21 +00008102 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008103 for (const auto &L : C->component_lists()) {
Samuel Antaocc10b852016-07-28 14:23:26 +00008104 assert(!L.second.empty() && "Not expecting empty list of components!");
8105 const ValueDecl *VD = L.second.back().getAssociatedDeclaration();
8106 VD = cast<ValueDecl>(VD->getCanonicalDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008107 const Expr *IE = L.second.back().getAssociatedExpression();
Samuel Antaocc10b852016-07-28 14:23:26 +00008108 // If the first component is a member expression, we have to look into
8109 // 'this', which maps to null in the map of map information. Otherwise
8110 // look directly for the information.
8111 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
8112
8113 // We potentially have map information for this declaration already.
8114 // Look for the first set of components that refer to it.
8115 if (It != Info.end()) {
8116 auto CI = std::find_if(
8117 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) {
8118 return MI.Components.back().getAssociatedDeclaration() == VD;
8119 });
8120 // If we found a map entry, signal that the pointer has to be returned
8121 // and move on to the next declaration.
8122 if (CI != It->second.end()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00008123 CI->ReturnDevicePointer = true;
Samuel Antaocc10b852016-07-28 14:23:26 +00008124 continue;
8125 }
8126 }
8127
8128 // We didn't find any match in our map information - generate a zero
Alexey Bataevb3638132018-07-19 16:34:13 +00008129 // size array section - if the pointer is a struct member we defer this
8130 // action until the whole struct has been processed.
Alexey Bataevb3638132018-07-19 16:34:13 +00008131 if (isa<MemberExpr>(IE)) {
8132 // Insert the pointer into Info to be processed by
8133 // generateInfoForComponentList. Because it is a member pointer
8134 // without a pointee, no entry will be generated for it, therefore
8135 // we need to generate one after the whole struct has been processed.
8136 // Nonetheless, generateInfoForComponentList must be called to take
8137 // the pointer into account for the calculation of the range of the
8138 // partial struct.
Kelvin Lief579432018-12-18 22:18:41 +00008139 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00008140 /*ReturnDevicePointer=*/false, C->isImplicit());
8141 DeferredInfo[nullptr].emplace_back(IE, VD);
8142 } else {
Michael Krused47b9432019-08-05 18:43:21 +00008143 llvm::Value *Ptr =
8144 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc());
Alexey Bataevb3638132018-07-19 16:34:13 +00008145 BasePointers.emplace_back(Ptr, VD);
8146 Pointers.push_back(Ptr);
Michael Krused47b9432019-08-05 18:43:21 +00008147 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00008148 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM);
8149 }
Samuel Antaocc10b852016-07-28 14:23:26 +00008150 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008151 }
Samuel Antaocc10b852016-07-28 14:23:26 +00008152
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008153 for (const auto &M : Info) {
Samuel Antao86ace552016-04-27 22:40:57 +00008154 // We need to know when we generate information for the first component
8155 // associated with a capture, because the mapping flags depend on it.
8156 bool IsFirstComponentList = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00008157
8158 // Temporary versions of arrays
8159 MapBaseValuesArrayTy CurBasePointers;
8160 MapValuesArrayTy CurPointers;
8161 MapValuesArrayTy CurSizes;
8162 MapFlagsArrayTy CurTypes;
8163 StructRangeInfoTy PartialStruct;
8164
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008165 for (const MapInfo &L : M.second) {
Samuel Antao86ace552016-04-27 22:40:57 +00008166 assert(!L.Components.empty() &&
8167 "Not expecting declaration with no component lists.");
Samuel Antaocc10b852016-07-28 14:23:26 +00008168
8169 // Remember the current base pointer index.
Alexey Bataevb3638132018-07-19 16:34:13 +00008170 unsigned CurrentBasePointersIdx = CurBasePointers.size();
Michael Krused47b9432019-08-05 18:43:21 +00008171 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8172 CurBasePointers, CurPointers, CurSizes,
8173 CurTypes, PartialStruct,
8174 IsFirstComponentList, L.IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00008175
8176 // If this entry relates with a device pointer, set the relevant
8177 // declaration and add the 'return pointer' flag.
Alexey Bataevb3638132018-07-19 16:34:13 +00008178 if (L.ReturnDevicePointer) {
8179 assert(CurBasePointers.size() > CurrentBasePointersIdx &&
Samuel Antaocc10b852016-07-28 14:23:26 +00008180 "Unexpected number of mapped base pointers.");
8181
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008182 const ValueDecl *RelevantVD =
8183 L.Components.back().getAssociatedDeclaration();
Samuel Antaocc10b852016-07-28 14:23:26 +00008184 assert(RelevantVD &&
8185 "No relevant declaration related with device pointer??");
8186
Alexey Bataevb3638132018-07-19 16:34:13 +00008187 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD);
8188 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008189 }
Samuel Antao86ace552016-04-27 22:40:57 +00008190 IsFirstComponentList = false;
8191 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008192
8193 // Append any pending zero-length pointers which are struct members and
8194 // used with use_device_ptr.
8195 auto CI = DeferredInfo.find(M.first);
8196 if (CI != DeferredInfo.end()) {
8197 for (const DeferredDevicePtrEntryTy &L : CI->second) {
8198 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer();
8199 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar(
8200 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc());
8201 CurBasePointers.emplace_back(BasePtr, L.VD);
8202 CurPointers.push_back(Ptr);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008203 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty));
Alexey Bataevb3638132018-07-19 16:34:13 +00008204 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder
8205 // value MEMBER_OF=FFFF so that the entry is later updated with the
8206 // correct value of MEMBER_OF.
8207 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM |
8208 OMP_MAP_MEMBER_OF);
8209 }
8210 }
8211
8212 // If there is an entry in PartialStruct it means we have a struct with
8213 // individual members mapped. Emit an extra combined entry.
8214 if (PartialStruct.Base.isValid())
8215 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8216 PartialStruct);
8217
8218 // We need to append the results of this capture to what we already have.
8219 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8220 Pointers.append(CurPointers.begin(), CurPointers.end());
8221 Sizes.append(CurSizes.begin(), CurSizes.end());
8222 Types.append(CurTypes.begin(), CurTypes.end());
Samuel Antao86ace552016-04-27 22:40:57 +00008223 }
8224 }
8225
Michael Krused47b9432019-08-05 18:43:21 +00008226 /// Generate all the base pointers, section pointers, sizes and map types for
8227 /// the extracted map clauses of user-defined mapper.
8228 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers,
8229 MapValuesArrayTy &Pointers,
8230 MapValuesArrayTy &Sizes,
8231 MapFlagsArrayTy &Types) const {
8232 assert(CurDir.is<const OMPDeclareMapperDecl *>() &&
8233 "Expect a declare mapper directive");
8234 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>();
8235 // We have to process the component lists that relate with the same
8236 // declaration in a single chunk so that we can generate the map flags
8237 // correctly. Therefore, we organize all lists in a map.
8238 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
8239
8240 // Helper function to fill the information map for the different supported
8241 // clauses.
8242 auto &&InfoGen = [&Info](
8243 const ValueDecl *D,
8244 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
8245 OpenMPMapClauseKind MapType,
8246 ArrayRef<OpenMPMapModifierKind> MapModifiers,
8247 bool ReturnDevicePointer, bool IsImplicit) {
8248 const ValueDecl *VD =
8249 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
8250 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
8251 IsImplicit);
8252 };
8253
8254 for (const auto *C : CurMapperDir->clauselists()) {
8255 const auto *MC = cast<OMPMapClause>(C);
8256 for (const auto &L : MC->component_lists()) {
8257 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(),
8258 /*ReturnDevicePointer=*/false, MC->isImplicit());
8259 }
8260 }
8261
8262 for (const auto &M : Info) {
8263 // We need to know when we generate information for the first component
8264 // associated with a capture, because the mapping flags depend on it.
8265 bool IsFirstComponentList = true;
8266
8267 // Temporary versions of arrays
8268 MapBaseValuesArrayTy CurBasePointers;
8269 MapValuesArrayTy CurPointers;
8270 MapValuesArrayTy CurSizes;
8271 MapFlagsArrayTy CurTypes;
8272 StructRangeInfoTy PartialStruct;
8273
8274 for (const MapInfo &L : M.second) {
8275 assert(!L.Components.empty() &&
8276 "Not expecting declaration with no component lists.");
8277 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components,
8278 CurBasePointers, CurPointers, CurSizes,
8279 CurTypes, PartialStruct,
8280 IsFirstComponentList, L.IsImplicit);
8281 IsFirstComponentList = false;
8282 }
8283
8284 // If there is an entry in PartialStruct it means we have a struct with
8285 // individual members mapped. Emit an extra combined entry.
8286 if (PartialStruct.Base.isValid())
8287 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
8288 PartialStruct);
8289
8290 // We need to append the results of this capture to what we already have.
8291 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8292 Pointers.append(CurPointers.begin(), CurPointers.end());
8293 Sizes.append(CurSizes.begin(), CurSizes.end());
8294 Types.append(CurTypes.begin(), CurTypes.end());
8295 }
8296 }
8297
Alexey Bataev60705422018-10-30 15:50:12 +00008298 /// Emit capture info for lambdas for variables captured by reference.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008299 void generateInfoForLambdaCaptures(
8300 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers,
8301 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
8302 MapFlagsArrayTy &Types,
8303 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008304 const auto *RD = VD->getType()
8305 .getCanonicalType()
8306 .getNonReferenceType()
8307 ->getAsCXXRecordDecl();
8308 if (!RD || !RD->isLambda())
8309 return;
8310 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD));
8311 LValue VDLVal = CGF.MakeAddrLValue(
8312 VDAddr, VD->getType().getCanonicalType().getNonReferenceType());
8313 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
8314 FieldDecl *ThisCapture = nullptr;
8315 RD->getCaptureFields(Captures, ThisCapture);
8316 if (ThisCapture) {
8317 LValue ThisLVal =
8318 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture);
Alexey Bataev969dbc02018-11-08 15:47:39 +00008319 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture);
8320 LambdaPointers.try_emplace(ThisLVal.getPointer(), VDLVal.getPointer());
8321 BasePointers.push_back(ThisLVal.getPointer());
8322 Pointers.push_back(ThisLValVal.getPointer());
Alexey Bataeva90fc662019-06-25 16:00:43 +00008323 Sizes.push_back(
8324 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8325 CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008326 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008327 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8328 }
8329 for (const LambdaCapture &LC : RD->captures()) {
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008330 if (!LC.capturesVariable())
Alexey Bataev60705422018-10-30 15:50:12 +00008331 continue;
8332 const VarDecl *VD = LC.getCapturedVar();
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008333 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType())
8334 continue;
Alexey Bataev60705422018-10-30 15:50:12 +00008335 auto It = Captures.find(VD);
8336 assert(It != Captures.end() && "Found lambda capture without field.");
8337 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second);
Alexey Bataevaf6725b2019-07-11 13:54:26 +00008338 if (LC.getCaptureKind() == LCK_ByRef) {
8339 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second);
8340 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer());
8341 BasePointers.push_back(VarLVal.getPointer());
8342 Pointers.push_back(VarLValVal.getPointer());
8343 Sizes.push_back(CGF.Builder.CreateIntCast(
8344 CGF.getTypeSize(
8345 VD->getType().getCanonicalType().getNonReferenceType()),
8346 CGF.Int64Ty, /*isSigned=*/true));
8347 } else {
8348 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation());
8349 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer());
8350 BasePointers.push_back(VarLVal.getPointer());
8351 Pointers.push_back(VarRVal.getScalarVal());
8352 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0));
8353 }
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008354 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008355 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8356 }
8357 }
8358
8359 /// Set correct indices for lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008360 void adjustMemberOfForLambdaCaptures(
8361 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
8362 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
8363 MapFlagsArrayTy &Types) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008364 for (unsigned I = 0, E = Types.size(); I < E; ++I) {
8365 // Set correct member_of idx for all implicit lambda captures.
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008366 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008367 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT))
8368 continue;
Alexey Bataev969dbc02018-11-08 15:47:39 +00008369 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]);
8370 assert(BasePtr && "Unable to find base lambda address.");
Alexey Bataev60705422018-10-30 15:50:12 +00008371 int TgtIdx = -1;
8372 for (unsigned J = I; J > 0; --J) {
8373 unsigned Idx = J - 1;
8374 if (Pointers[Idx] != BasePtr)
8375 continue;
8376 TgtIdx = Idx;
8377 break;
8378 }
8379 assert(TgtIdx != -1 && "Unable to find parent lambda.");
8380 // All other current entries will be MEMBER_OF the combined entry
8381 // (except for PTR_AND_OBJ entries which do not have a placeholder value
8382 // 0xFFFF in the MEMBER_OF field).
8383 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx);
8384 setCorrectMemberOfFlag(Types[I], MemberOfFlag);
8385 }
8386 }
8387
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008388 /// Generate the base pointers, section pointers, sizes and map types
Samuel Antao86ace552016-04-27 22:40:57 +00008389 /// associated to a given capture.
8390 void generateInfoForCapture(const CapturedStmt::Capture *Cap,
Samuel Antao6890b092016-07-28 14:25:09 +00008391 llvm::Value *Arg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008392 MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00008393 MapValuesArrayTy &Pointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008394 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
8395 StructRangeInfoTy &PartialStruct) const {
Samuel Antao86ace552016-04-27 22:40:57 +00008396 assert(!Cap->capturesVariableArrayType() &&
8397 "Not expecting to generate map info for a variable array type!");
8398
Samuel Antao6890b092016-07-28 14:25:09 +00008399 // We need to know when we generating information for the first component
Alexey Bataevb3638132018-07-19 16:34:13 +00008400 const ValueDecl *VD = Cap->capturesThis()
8401 ? nullptr
8402 : Cap->getCapturedVar()->getCanonicalDecl();
Samuel Antao86ace552016-04-27 22:40:57 +00008403
Samuel Antao6890b092016-07-28 14:25:09 +00008404 // If this declaration appears in a is_device_ptr clause we just have to
8405 // pass the pointer by value. If it is a reference to a declaration, we just
Alexey Bataevb3638132018-07-19 16:34:13 +00008406 // pass its value.
8407 if (DevPointersMap.count(VD)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008408 BasePointers.emplace_back(Arg, VD);
Samuel Antao6890b092016-07-28 14:25:09 +00008409 Pointers.push_back(Arg);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008410 Sizes.push_back(
8411 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy),
8412 CGF.Int64Ty, /*isSigned=*/true));
George Rokos065755d2017-11-07 18:27:04 +00008413 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM);
Samuel Antao6890b092016-07-28 14:25:09 +00008414 return;
8415 }
8416
Alexey Bataeve82445f2018-09-20 13:54:02 +00008417 using MapData =
8418 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
Kelvin Lief579432018-12-18 22:18:41 +00008419 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008420 SmallVector<MapData, 4> DeclComponentLists;
Michael Krused47b9432019-08-05 18:43:21 +00008421 assert(CurDir.is<const OMPExecutableDirective *>() &&
8422 "Expect a executable directive");
8423 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
8424 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008425 for (const auto &L : C->decl_component_lists(VD)) {
Samuel Antao86ace552016-04-27 22:40:57 +00008426 assert(L.first == VD &&
8427 "We got information for the wrong declaration??");
8428 assert(!L.second.empty() &&
8429 "Not expecting declaration with no component lists.");
Alexey Bataeve82445f2018-09-20 13:54:02 +00008430 DeclComponentLists.emplace_back(L.second, C->getMapType(),
Kelvin Lief579432018-12-18 22:18:41 +00008431 C->getMapTypeModifiers(),
Alexey Bataeve82445f2018-09-20 13:54:02 +00008432 C->isImplicit());
Samuel Antao86ace552016-04-27 22:40:57 +00008433 }
Alexey Bataeve82445f2018-09-20 13:54:02 +00008434 }
8435
8436 // Find overlapping elements (including the offset from the base element).
8437 llvm::SmallDenseMap<
8438 const MapData *,
8439 llvm::SmallVector<
8440 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>,
8441 4>
8442 OverlappedData;
8443 size_t Count = 0;
8444 for (const MapData &L : DeclComponentLists) {
8445 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8446 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008447 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008448 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008449 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008450 ++Count;
8451 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) {
8452 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1;
Kelvin Lief579432018-12-18 22:18:41 +00008453 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008454 auto CI = Components.rbegin();
8455 auto CE = Components.rend();
8456 auto SI = Components1.rbegin();
8457 auto SE = Components1.rend();
8458 for (; CI != CE && SI != SE; ++CI, ++SI) {
8459 if (CI->getAssociatedExpression()->getStmtClass() !=
8460 SI->getAssociatedExpression()->getStmtClass())
8461 break;
8462 // Are we dealing with different variables/fields?
8463 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
8464 break;
8465 }
8466 // Found overlapping if, at least for one component, reached the head of
8467 // the components list.
8468 if (CI == CE || SI == SE) {
8469 assert((CI != CE || SI != SE) &&
8470 "Unexpected full match of the mapping components.");
8471 const MapData &BaseData = CI == CE ? L : L1;
8472 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData =
8473 SI == SE ? Components : Components1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008474 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData);
8475 OverlappedElements.getSecond().push_back(SubData);
8476 }
8477 }
8478 }
8479 // Sort the overlapped elements for each item.
8480 llvm::SmallVector<const FieldDecl *, 4> Layout;
8481 if (!OverlappedData.empty()) {
8482 if (const auto *CRD =
8483 VD->getType().getCanonicalType()->getAsCXXRecordDecl())
8484 getPlainLayout(CRD, Layout, /*AsBase=*/false);
8485 else {
8486 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl();
8487 Layout.append(RD->field_begin(), RD->field_end());
8488 }
8489 }
8490 for (auto &Pair : OverlappedData) {
8491 llvm::sort(
8492 Pair.getSecond(),
8493 [&Layout](
8494 OMPClauseMappableExprCommon::MappableExprComponentListRef First,
8495 OMPClauseMappableExprCommon::MappableExprComponentListRef
8496 Second) {
8497 auto CI = First.rbegin();
8498 auto CE = First.rend();
8499 auto SI = Second.rbegin();
8500 auto SE = Second.rend();
8501 for (; CI != CE && SI != SE; ++CI, ++SI) {
8502 if (CI->getAssociatedExpression()->getStmtClass() !=
8503 SI->getAssociatedExpression()->getStmtClass())
8504 break;
8505 // Are we dealing with different variables/fields?
8506 if (CI->getAssociatedDeclaration() !=
8507 SI->getAssociatedDeclaration())
8508 break;
8509 }
Richard Trieu5061e832018-09-21 21:20:33 +00008510
8511 // Lists contain the same elements.
8512 if (CI == CE && SI == SE)
8513 return false;
8514
8515 // List with less elements is less than list with more elements.
8516 if (CI == CE || SI == SE)
8517 return CI == CE;
8518
Alexey Bataeve82445f2018-09-20 13:54:02 +00008519 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
8520 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
8521 if (FD1->getParent() == FD2->getParent())
8522 return FD1->getFieldIndex() < FD2->getFieldIndex();
8523 const auto It =
8524 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) {
8525 return FD == FD1 || FD == FD2;
8526 });
8527 return *It == FD1;
8528 });
8529 }
8530
8531 // Associated with a capture, because the mapping flags depend on it.
8532 // Go through all of the elements with the overlapped elements.
8533 for (const auto &Pair : OverlappedData) {
8534 const MapData &L = *Pair.getFirst();
8535 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8536 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008537 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008538 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008539 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008540 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
8541 OverlappedComponents = Pair.getSecond();
8542 bool IsFirstComponentList = true;
Kelvin Lief579432018-12-18 22:18:41 +00008543 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008544 BasePointers, Pointers, Sizes, Types,
8545 PartialStruct, IsFirstComponentList,
8546 IsImplicit, OverlappedComponents);
8547 }
8548 // Go through other elements without overlapped elements.
8549 bool IsFirstComponentList = OverlappedData.empty();
8550 for (const MapData &L : DeclComponentLists) {
8551 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8552 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008553 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008554 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008555 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008556 auto It = OverlappedData.find(&L);
8557 if (It == OverlappedData.end())
Kelvin Lief579432018-12-18 22:18:41 +00008558 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008559 BasePointers, Pointers, Sizes, Types,
8560 PartialStruct, IsFirstComponentList,
8561 IsImplicit);
8562 IsFirstComponentList = false;
8563 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008564 }
Samuel Antao86ace552016-04-27 22:40:57 +00008565
Alexey Bataevb3638132018-07-19 16:34:13 +00008566 /// Generate the base pointers, section pointers, sizes and map types
8567 /// associated with the declare target link variables.
8568 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers,
8569 MapValuesArrayTy &Pointers,
8570 MapValuesArrayTy &Sizes,
8571 MapFlagsArrayTy &Types) const {
Michael Krused47b9432019-08-05 18:43:21 +00008572 assert(CurDir.is<const OMPExecutableDirective *>() &&
8573 "Expect a executable directive");
8574 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
Alexey Bataevb3638132018-07-19 16:34:13 +00008575 // Map other list items in the map clause which are not captured variables
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00008576 // but "declare target link" global variables.
Michael Krused47b9432019-08-05 18:43:21 +00008577 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00008578 for (const auto &L : C->component_lists()) {
8579 if (!L.first)
8580 continue;
8581 const auto *VD = dyn_cast<VarDecl>(L.first);
8582 if (!VD)
8583 continue;
8584 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00008585 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00008586 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() ||
8587 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)
Alexey Bataevb3638132018-07-19 16:34:13 +00008588 continue;
8589 StructRangeInfoTy PartialStruct;
8590 generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00008591 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008592 Pointers, Sizes, Types, PartialStruct,
8593 /*IsFirstComponentList=*/true, C->isImplicit());
8594 assert(!PartialStruct.Base.isValid() &&
8595 "No partial structs for declare target link expected.");
8596 }
8597 }
Samuel Antao86ace552016-04-27 22:40:57 +00008598 }
Samuel Antaod486f842016-05-26 16:53:38 +00008599
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008600 /// Generate the default map information for a given capture \a CI,
Samuel Antaod486f842016-05-26 16:53:38 +00008601 /// record field declaration \a RI and captured value \a CV.
Samuel Antaocc10b852016-07-28 14:23:26 +00008602 void generateDefaultMapInfo(const CapturedStmt::Capture &CI,
8603 const FieldDecl &RI, llvm::Value *CV,
8604 MapBaseValuesArrayTy &CurBasePointers,
8605 MapValuesArrayTy &CurPointers,
8606 MapValuesArrayTy &CurSizes,
Alexey Bataevb3638132018-07-19 16:34:13 +00008607 MapFlagsArrayTy &CurMapTypes) const {
Alexey Bataevf288cf92019-06-27 18:53:07 +00008608 bool IsImplicit = true;
Samuel Antaod486f842016-05-26 16:53:38 +00008609 // Do the default mapping.
8610 if (CI.capturesThis()) {
8611 CurBasePointers.push_back(CV);
8612 CurPointers.push_back(CV);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008613 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr());
Alexey Bataeva90fc662019-06-25 16:00:43 +00008614 CurSizes.push_back(
8615 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()),
8616 CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008617 // Default map type.
Samuel Antaocc10b852016-07-28 14:23:26 +00008618 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM);
Samuel Antaod486f842016-05-26 16:53:38 +00008619 } else if (CI.capturesVariableByCopy()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008620 CurBasePointers.push_back(CV);
8621 CurPointers.push_back(CV);
Samuel Antaod486f842016-05-26 16:53:38 +00008622 if (!RI.getType()->isAnyPointerType()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008623 // We have to signal to the runtime captures passed by value that are
8624 // not pointers.
George Rokos065755d2017-11-07 18:27:04 +00008625 CurMapTypes.push_back(OMP_MAP_LITERAL);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008626 CurSizes.push_back(CGF.Builder.CreateIntCast(
8627 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008628 } else {
8629 // Pointers are implicitly mapped with a zero size and no flags
8630 // (other than first map that is added for all implicit maps).
Alexey Bataevb3638132018-07-19 16:34:13 +00008631 CurMapTypes.push_back(OMP_MAP_NONE);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008632 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty));
Samuel Antaod486f842016-05-26 16:53:38 +00008633 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008634 const VarDecl *VD = CI.getCapturedVar();
8635 auto I = FirstPrivateDecls.find(VD);
8636 if (I != FirstPrivateDecls.end())
8637 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008638 } else {
8639 assert(CI.capturesVariable() && "Expected captured reference.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008640 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr());
Samuel Antaod486f842016-05-26 16:53:38 +00008641 QualType ElementType = PtrTy->getPointeeType();
Alexey Bataeva90fc662019-06-25 16:00:43 +00008642 CurSizes.push_back(CGF.Builder.CreateIntCast(
8643 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true));
Samuel Antaod486f842016-05-26 16:53:38 +00008644 // The default map type for a scalar/complex type is 'to' because by
8645 // default the value doesn't have to be retrieved. For an aggregate
8646 // type, the default is 'tofrom'.
Alexey Bataevb3638132018-07-19 16:34:13 +00008647 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI));
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008648 const VarDecl *VD = CI.getCapturedVar();
Alexey Bataevf288cf92019-06-27 18:53:07 +00008649 auto I = FirstPrivateDecls.find(VD);
8650 if (I != FirstPrivateDecls.end() &&
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008651 VD->getType().isConstant(CGF.getContext())) {
8652 llvm::Constant *Addr =
8653 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD);
8654 // Copy the value of the original variable to the new global copy.
8655 CGF.Builder.CreateMemCpy(
8656 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(),
8657 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)),
Rui Ueyama49a3ad22019-07-16 04:46:31 +00008658 CurSizes.back(), /*IsVolatile=*/false);
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008659 // Use new global variable as the base pointers.
8660 CurBasePointers.push_back(Addr);
8661 CurPointers.push_back(Addr);
8662 } else {
8663 CurBasePointers.push_back(CV);
Alexey Bataevf288cf92019-06-27 18:53:07 +00008664 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) {
Alexey Bataevc2b831f2019-04-02 16:03:40 +00008665 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue(
8666 CV, ElementType, CGF.getContext().getDeclAlign(VD),
8667 AlignmentSource::Decl));
8668 CurPointers.push_back(PtrAddr.getPointer());
8669 } else {
8670 CurPointers.push_back(CV);
8671 }
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008672 }
Alexey Bataevf288cf92019-06-27 18:53:07 +00008673 if (I != FirstPrivateDecls.end())
8674 IsImplicit = I->getSecond();
Samuel Antaod486f842016-05-26 16:53:38 +00008675 }
George Rokos065755d2017-11-07 18:27:04 +00008676 // Every default map produces a single argument which is a target parameter.
8677 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM;
Alexey Bataevb3638132018-07-19 16:34:13 +00008678
8679 // Add flag stating this is an implicit map.
Alexey Bataevf288cf92019-06-27 18:53:07 +00008680 if (IsImplicit)
8681 CurMapTypes.back() |= OMP_MAP_IMPLICIT;
Samuel Antaod486f842016-05-26 16:53:38 +00008682 }
Samuel Antao86ace552016-04-27 22:40:57 +00008683};
Samuel Antaodf158d52016-04-27 22:58:19 +00008684} // anonymous namespace
8685
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008686/// Emit the arrays used to pass the captures and map information to the
Samuel Antaodf158d52016-04-27 22:58:19 +00008687/// offloading runtime library. If there is no map or capture information,
8688/// return nullptr by reference.
8689static void
Samuel Antaocc10b852016-07-28 14:23:26 +00008690emitOffloadingArrays(CodeGenFunction &CGF,
8691 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers,
Samuel Antaodf158d52016-04-27 22:58:19 +00008692 MappableExprsHandler::MapValuesArrayTy &Pointers,
8693 MappableExprsHandler::MapValuesArrayTy &Sizes,
Samuel Antaocc10b852016-07-28 14:23:26 +00008694 MappableExprsHandler::MapFlagsArrayTy &MapTypes,
8695 CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008696 CodeGenModule &CGM = CGF.CGM;
8697 ASTContext &Ctx = CGF.getContext();
Samuel Antaodf158d52016-04-27 22:58:19 +00008698
Samuel Antaocc10b852016-07-28 14:23:26 +00008699 // Reset the array information.
8700 Info.clearArrayInfo();
8701 Info.NumberOfPtrs = BasePointers.size();
Samuel Antaodf158d52016-04-27 22:58:19 +00008702
Samuel Antaocc10b852016-07-28 14:23:26 +00008703 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008704 // Detect if we have any capture size requiring runtime evaluation of the
8705 // size so that a constant array could be eventually used.
8706 bool hasRuntimeEvaluationCaptureSize = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008707 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008708 if (!isa<llvm::Constant>(S)) {
8709 hasRuntimeEvaluationCaptureSize = true;
8710 break;
8711 }
8712
Samuel Antaocc10b852016-07-28 14:23:26 +00008713 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true);
Richard Smith772e2662019-10-04 01:25:59 +00008714 QualType PointerArrayType = Ctx.getConstantArrayType(
8715 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal,
8716 /*IndexTypeQuals=*/0);
Samuel Antaodf158d52016-04-27 22:58:19 +00008717
Samuel Antaocc10b852016-07-28 14:23:26 +00008718 Info.BasePointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008719 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
Samuel Antaocc10b852016-07-28 14:23:26 +00008720 Info.PointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008721 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
8722
8723 // If we don't have any VLA types or other types that require runtime
8724 // evaluation, we can use a constant array for the map sizes, otherwise we
8725 // need to fill up the arrays as we do for the pointers.
Alexey Bataeva90fc662019-06-25 16:00:43 +00008726 QualType Int64Ty =
8727 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Samuel Antaodf158d52016-04-27 22:58:19 +00008728 if (hasRuntimeEvaluationCaptureSize) {
Richard Smith772e2662019-10-04 01:25:59 +00008729 QualType SizeArrayType = Ctx.getConstantArrayType(
8730 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal,
8731 /*IndexTypeQuals=*/0);
Samuel Antaocc10b852016-07-28 14:23:26 +00008732 Info.SizesArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008733 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
8734 } else {
8735 // We expect all the sizes to be constant, so we collect them to create
8736 // a constant array.
8737 SmallVector<llvm::Constant *, 16> ConstSizes;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008738 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008739 ConstSizes.push_back(cast<llvm::Constant>(S));
8740
8741 auto *SizesArrayInit = llvm::ConstantArray::get(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008742 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008743 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008744 auto *SizesArrayGbl = new llvm::GlobalVariable(
8745 CGM.getModule(), SizesArrayInit->getType(),
8746 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008747 SizesArrayInit, Name);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008748 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008749 Info.SizesArray = SizesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008750 }
8751
8752 // The map types are always constant so we don't need to generate code to
8753 // fill arrays. Instead, we create an array constant.
Alexey Bataevb3638132018-07-19 16:34:13 +00008754 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0);
8755 llvm::copy(MapTypes, Mapping.begin());
Samuel Antaodf158d52016-04-27 22:58:19 +00008756 llvm::Constant *MapTypesArrayInit =
Alexey Bataevb3638132018-07-19 16:34:13 +00008757 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008758 std::string MaptypesName =
8759 CGM.getOpenMPRuntime().getName({"offload_maptypes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008760 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
8761 CGM.getModule(), MapTypesArrayInit->getType(),
8762 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008763 MapTypesArrayInit, MaptypesName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008764 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008765 Info.MapTypesArray = MapTypesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008766
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008767 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) {
8768 llvm::Value *BPVal = *BasePointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008769 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008770 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008771 Info.BasePointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008772 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8773 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008774 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8775 CGF.Builder.CreateStore(BPVal, BPAddr);
8776
Samuel Antaocc10b852016-07-28 14:23:26 +00008777 if (Info.requiresDevicePointerInfo())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008778 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl())
Alexey Bataev43a919f2018-04-13 17:48:43 +00008779 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr);
Samuel Antaocc10b852016-07-28 14:23:26 +00008780
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008781 llvm::Value *PVal = Pointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008782 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008783 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008784 Info.PointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008785 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8786 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008787 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8788 CGF.Builder.CreateStore(PVal, PAddr);
8789
8790 if (hasRuntimeEvaluationCaptureSize) {
8791 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008792 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008793 Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008794 /*Idx0=*/0,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008795 /*Idx1=*/I);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008796 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty));
Samuel Antaodf158d52016-04-27 22:58:19 +00008797 CGF.Builder.CreateStore(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008798 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true),
Samuel Antaodf158d52016-04-27 22:58:19 +00008799 SAddr);
8800 }
8801 }
8802 }
8803}
Michael Krused47b9432019-08-05 18:43:21 +00008804
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008805/// Emit the arguments to be passed to the runtime library based on the
Samuel Antaodf158d52016-04-27 22:58:19 +00008806/// arrays of pointers, sizes and map types.
8807static void emitOffloadingArraysArgument(
8808 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg,
8809 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008810 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008811 CodeGenModule &CGM = CGF.CGM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008812 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008813 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008814 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8815 Info.BasePointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008816 /*Idx0=*/0, /*Idx1=*/0);
8817 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008818 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8819 Info.PointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008820 /*Idx0=*/0,
8821 /*Idx1=*/0);
8822 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Alexey Bataeva90fc662019-06-25 16:00:43 +00008823 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008824 /*Idx0=*/0, /*Idx1=*/0);
8825 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
George Rokos63bc9d62017-11-21 18:25:12 +00008826 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008827 Info.MapTypesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008828 /*Idx0=*/0,
8829 /*Idx1=*/0);
8830 } else {
8831 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
8832 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
Alexey Bataeva90fc662019-06-25 16:00:43 +00008833 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008834 MapTypesArrayArg =
George Rokos63bc9d62017-11-21 18:25:12 +00008835 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008836 }
Samuel Antao86ace552016-04-27 22:40:57 +00008837}
8838
Alexey Bataev7bb33532019-01-07 21:30:43 +00008839/// Check for inner distribute directive.
8840static const OMPExecutableDirective *
8841getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
8842 const auto *CS = D.getInnermostCapturedStmt();
8843 const auto *Body =
8844 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00008845 const Stmt *ChildStmt =
8846 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
Alexey Bataev7bb33532019-01-07 21:30:43 +00008847
Alexey Bataev5c427362019-04-10 19:11:33 +00008848 if (const auto *NestedDir =
8849 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008850 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind();
8851 switch (D.getDirectiveKind()) {
8852 case OMPD_target:
8853 if (isOpenMPDistributeDirective(DKind))
8854 return NestedDir;
8855 if (DKind == OMPD_teams) {
8856 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
8857 /*IgnoreCaptured=*/true);
8858 if (!Body)
8859 return nullptr;
Alexey Bataev5c427362019-04-10 19:11:33 +00008860 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
8861 if (const auto *NND =
8862 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008863 DKind = NND->getDirectiveKind();
8864 if (isOpenMPDistributeDirective(DKind))
8865 return NND;
8866 }
8867 }
8868 return nullptr;
8869 case OMPD_target_teams:
8870 if (isOpenMPDistributeDirective(DKind))
8871 return NestedDir;
8872 return nullptr;
8873 case OMPD_target_parallel:
8874 case OMPD_target_simd:
8875 case OMPD_target_parallel_for:
8876 case OMPD_target_parallel_for_simd:
8877 return nullptr;
8878 case OMPD_target_teams_distribute:
8879 case OMPD_target_teams_distribute_simd:
8880 case OMPD_target_teams_distribute_parallel_for:
8881 case OMPD_target_teams_distribute_parallel_for_simd:
8882 case OMPD_parallel:
8883 case OMPD_for:
8884 case OMPD_parallel_for:
8885 case OMPD_parallel_sections:
8886 case OMPD_for_simd:
8887 case OMPD_parallel_for_simd:
8888 case OMPD_cancel:
8889 case OMPD_cancellation_point:
8890 case OMPD_ordered:
8891 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00008892 case OMPD_allocate:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008893 case OMPD_task:
8894 case OMPD_simd:
8895 case OMPD_sections:
8896 case OMPD_section:
8897 case OMPD_single:
8898 case OMPD_master:
8899 case OMPD_critical:
8900 case OMPD_taskyield:
8901 case OMPD_barrier:
8902 case OMPD_taskwait:
8903 case OMPD_taskgroup:
8904 case OMPD_atomic:
8905 case OMPD_flush:
8906 case OMPD_teams:
8907 case OMPD_target_data:
8908 case OMPD_target_exit_data:
8909 case OMPD_target_enter_data:
8910 case OMPD_distribute:
8911 case OMPD_distribute_simd:
8912 case OMPD_distribute_parallel_for:
8913 case OMPD_distribute_parallel_for_simd:
8914 case OMPD_teams_distribute:
8915 case OMPD_teams_distribute_simd:
8916 case OMPD_teams_distribute_parallel_for:
8917 case OMPD_teams_distribute_parallel_for_simd:
8918 case OMPD_target_update:
8919 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00008920 case OMPD_declare_variant:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008921 case OMPD_declare_target:
8922 case OMPD_end_declare_target:
8923 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00008924 case OMPD_declare_mapper:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008925 case OMPD_taskloop:
8926 case OMPD_taskloop_simd:
8927 case OMPD_requires:
8928 case OMPD_unknown:
8929 llvm_unreachable("Unexpected directive.");
8930 }
8931 }
8932
8933 return nullptr;
8934}
8935
Michael Krused47b9432019-08-05 18:43:21 +00008936/// Emit the user-defined mapper function. The code generation follows the
8937/// pattern in the example below.
8938/// \code
8939/// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle,
8940/// void *base, void *begin,
8941/// int64_t size, int64_t type) {
8942/// // Allocate space for an array section first.
8943/// if (size > 1 && !maptype.IsDelete)
8944/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
8945/// size*sizeof(Ty), clearToFrom(type));
8946/// // Map members.
8947/// for (unsigned i = 0; i < size; i++) {
8948/// // For each component specified by this mapper:
8949/// for (auto c : all_components) {
8950/// if (c.hasMapper())
8951/// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size,
8952/// c.arg_type);
8953/// else
8954/// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base,
8955/// c.arg_begin, c.arg_size, c.arg_type);
8956/// }
8957/// }
8958/// // Delete the array section.
8959/// if (size > 1 && maptype.IsDelete)
8960/// __tgt_push_mapper_component(rt_mapper_handle, base, begin,
8961/// size*sizeof(Ty), clearToFrom(type));
8962/// }
8963/// \endcode
8964void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D,
8965 CodeGenFunction *CGF) {
8966 if (UDMMap.count(D) > 0)
8967 return;
8968 ASTContext &C = CGM.getContext();
8969 QualType Ty = D->getType();
8970 QualType PtrTy = C.getPointerType(Ty).withRestrict();
8971 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
8972 auto *MapperVarDecl =
8973 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl());
8974 SourceLocation Loc = D->getLocation();
8975 CharUnits ElementSize = C.getTypeSizeInChars(Ty);
8976
8977 // Prepare mapper function arguments and attributes.
8978 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
8979 C.VoidPtrTy, ImplicitParamDecl::Other);
8980 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
8981 ImplicitParamDecl::Other);
8982 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
8983 C.VoidPtrTy, ImplicitParamDecl::Other);
8984 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
8985 ImplicitParamDecl::Other);
8986 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty,
8987 ImplicitParamDecl::Other);
8988 FunctionArgList Args;
8989 Args.push_back(&HandleArg);
8990 Args.push_back(&BaseArg);
8991 Args.push_back(&BeginArg);
8992 Args.push_back(&SizeArg);
8993 Args.push_back(&TypeArg);
8994 const CGFunctionInfo &FnInfo =
8995 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
8996 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
8997 SmallString<64> TyStr;
8998 llvm::raw_svector_ostream Out(TyStr);
8999 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out);
9000 std::string Name = getName({"omp_mapper", TyStr, D->getName()});
9001 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
9002 Name, &CGM.getModule());
9003 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
9004 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
9005 // Start the mapper function code generation.
9006 CodeGenFunction MapperCGF(CGM);
9007 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
9008 // Compute the starting and end addreses of array elements.
9009 llvm::Value *Size = MapperCGF.EmitLoadOfScalar(
9010 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false,
9011 C.getPointerType(Int64Ty), Loc);
9012 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast(
9013 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(),
9014 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy)));
9015 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size);
9016 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar(
9017 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false,
9018 C.getPointerType(Int64Ty), Loc);
9019 // Prepare common arguments for array initiation and deletion.
9020 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar(
9021 MapperCGF.GetAddrOfLocalVar(&HandleArg),
9022 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
9023 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar(
9024 MapperCGF.GetAddrOfLocalVar(&BaseArg),
9025 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
9026 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar(
9027 MapperCGF.GetAddrOfLocalVar(&BeginArg),
9028 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc);
9029
9030 // Emit array initiation if this is an array section and \p MapType indicates
9031 // that memory allocation is required.
9032 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head");
9033 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
9034 ElementSize, HeadBB, /*IsInit=*/true);
9035
9036 // Emit a for loop to iterate through SizeArg of elements and map all of them.
9037
9038 // Emit the loop header block.
9039 MapperCGF.EmitBlock(HeadBB);
9040 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body");
9041 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done");
9042 // Evaluate whether the initial condition is satisfied.
9043 llvm::Value *IsEmpty =
9044 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty");
9045 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
9046 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock();
9047
9048 // Emit the loop body block.
9049 MapperCGF.EmitBlock(BodyBB);
9050 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI(
9051 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent");
9052 PtrPHI->addIncoming(PtrBegin, EntryBB);
9053 Address PtrCurrent =
9054 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg)
9055 .getAlignment()
9056 .alignmentOfArrayElement(ElementSize));
9057 // Privatize the declared variable of mapper to be the current array element.
9058 CodeGenFunction::OMPPrivateScope Scope(MapperCGF);
9059 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() {
9060 return MapperCGF
9061 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>())
9062 .getAddress();
9063 });
9064 (void)Scope.Privatize();
9065
9066 // Get map clause information. Fill up the arrays with all mapped variables.
9067 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
9068 MappableExprsHandler::MapValuesArrayTy Pointers;
9069 MappableExprsHandler::MapValuesArrayTy Sizes;
9070 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9071 MappableExprsHandler MEHandler(*D, MapperCGF);
9072 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes);
9073
9074 // Call the runtime API __tgt_mapper_num_components to get the number of
9075 // pre-existing components.
9076 llvm::Value *OffloadingArgs[] = {Handle};
9077 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall(
9078 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs);
9079 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl(
9080 PreviousSize,
9081 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset()));
9082
9083 // Fill up the runtime mapper handle for all components.
9084 for (unsigned I = 0; I < BasePointers.size(); ++I) {
9085 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast(
9086 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
9087 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast(
9088 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy));
9089 llvm::Value *CurSizeArg = Sizes[I];
9090
9091 // Extract the MEMBER_OF field from the map type.
9092 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member");
9093 MapperCGF.EmitBlock(MemberBB);
9094 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]);
9095 llvm::Value *Member = MapperCGF.Builder.CreateAnd(
9096 OriMapType,
9097 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF));
9098 llvm::BasicBlock *MemberCombineBB =
9099 MapperCGF.createBasicBlock("omp.member.combine");
9100 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type");
9101 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member);
9102 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB);
9103 // Add the number of pre-existing components to the MEMBER_OF field if it
9104 // is valid.
9105 MapperCGF.EmitBlock(MemberCombineBB);
9106 llvm::Value *CombinedMember =
9107 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize);
9108 // Do nothing if it is not a member of previous components.
9109 MapperCGF.EmitBlock(TypeBB);
9110 llvm::PHINode *MemberMapType =
9111 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype");
9112 MemberMapType->addIncoming(OriMapType, MemberBB);
9113 MemberMapType->addIncoming(CombinedMember, MemberCombineBB);
9114
9115 // Combine the map type inherited from user-defined mapper with that
9116 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM
9117 // bits of the \a MapType, which is the input argument of the mapper
9118 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM
9119 // bits of MemberMapType.
9120 // [OpenMP 5.0], 1.2.6. map-type decay.
9121 // | alloc | to | from | tofrom | release | delete
9122 // ----------------------------------------------------------
9123 // alloc | alloc | alloc | alloc | alloc | release | delete
9124 // to | alloc | to | alloc | to | release | delete
9125 // from | alloc | alloc | from | from | release | delete
9126 // tofrom | alloc | to | from | tofrom | release | delete
9127 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd(
9128 MapType,
9129 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO |
9130 MappableExprsHandler::OMP_MAP_FROM));
9131 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc");
9132 llvm::BasicBlock *AllocElseBB =
9133 MapperCGF.createBasicBlock("omp.type.alloc.else");
9134 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to");
9135 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else");
9136 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from");
9137 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end");
9138 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom);
9139 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB);
9140 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM.
9141 MapperCGF.EmitBlock(AllocBB);
9142 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd(
9143 MemberMapType,
9144 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9145 MappableExprsHandler::OMP_MAP_FROM)));
9146 MapperCGF.Builder.CreateBr(EndBB);
9147 MapperCGF.EmitBlock(AllocElseBB);
9148 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ(
9149 LeftToFrom,
9150 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO));
9151 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB);
9152 // In case of to, clear OMP_MAP_FROM.
9153 MapperCGF.EmitBlock(ToBB);
9154 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd(
9155 MemberMapType,
9156 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM));
9157 MapperCGF.Builder.CreateBr(EndBB);
9158 MapperCGF.EmitBlock(ToElseBB);
9159 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ(
9160 LeftToFrom,
9161 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM));
9162 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB);
9163 // In case of from, clear OMP_MAP_TO.
9164 MapperCGF.EmitBlock(FromBB);
9165 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd(
9166 MemberMapType,
9167 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO));
9168 // In case of tofrom, do nothing.
9169 MapperCGF.EmitBlock(EndBB);
9170 llvm::PHINode *CurMapType =
9171 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype");
9172 CurMapType->addIncoming(AllocMapType, AllocBB);
9173 CurMapType->addIncoming(ToMapType, ToBB);
9174 CurMapType->addIncoming(FromMapType, FromBB);
9175 CurMapType->addIncoming(MemberMapType, ToElseBB);
9176
9177 // TODO: call the corresponding mapper function if a user-defined mapper is
9178 // associated with this map clause.
9179 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9180 // data structure.
9181 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg,
9182 CurSizeArg, CurMapType};
9183 MapperCGF.EmitRuntimeCall(
9184 createRuntimeFunction(OMPRTL__tgt_push_mapper_component),
9185 OffloadingArgs);
9186 }
9187
9188 // Update the pointer to point to the next element that needs to be mapped,
9189 // and check whether we have mapped all elements.
9190 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32(
9191 PtrPHI, /*Idx0=*/1, "omp.arraymap.next");
9192 PtrPHI->addIncoming(PtrNext, BodyBB);
9193 llvm::Value *IsDone =
9194 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone");
9195 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit");
9196 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB);
9197
9198 MapperCGF.EmitBlock(ExitBB);
9199 // Emit array deletion if this is an array section and \p MapType indicates
9200 // that deletion is required.
9201 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType,
9202 ElementSize, DoneBB, /*IsInit=*/false);
9203
9204 // Emit the function exit block.
9205 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true);
9206 MapperCGF.FinishFunction();
9207 UDMMap.try_emplace(D, Fn);
9208 if (CGF) {
9209 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn);
9210 Decls.second.push_back(D);
9211 }
9212}
9213
9214/// Emit the array initialization or deletion portion for user-defined mapper
9215/// code generation. First, it evaluates whether an array section is mapped and
9216/// whether the \a MapType instructs to delete this section. If \a IsInit is
9217/// true, and \a MapType indicates to not delete this array, array
9218/// initialization code is generated. If \a IsInit is false, and \a MapType
9219/// indicates to not this array, array deletion code is generated.
9220void CGOpenMPRuntime::emitUDMapperArrayInitOrDel(
9221 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base,
9222 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType,
9223 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) {
9224 StringRef Prefix = IsInit ? ".init" : ".del";
9225
9226 // Evaluate if this is an array section.
9227 llvm::BasicBlock *IsDeleteBB =
9228 MapperCGF.createBasicBlock("omp.array" + Prefix + ".evaldelete");
9229 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.array" + Prefix);
9230 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE(
9231 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray");
9232 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB);
9233
9234 // Evaluate if we are going to delete this section.
9235 MapperCGF.EmitBlock(IsDeleteBB);
9236 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd(
9237 MapType,
9238 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE));
9239 llvm::Value *DeleteCond;
9240 if (IsInit) {
9241 DeleteCond = MapperCGF.Builder.CreateIsNull(
9242 DeleteBit, "omp.array" + Prefix + ".delete");
9243 } else {
9244 DeleteCond = MapperCGF.Builder.CreateIsNotNull(
9245 DeleteBit, "omp.array" + Prefix + ".delete");
9246 }
9247 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB);
9248
9249 MapperCGF.EmitBlock(BodyBB);
9250 // Get the array size by multiplying element size and element number (i.e., \p
9251 // Size).
9252 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul(
9253 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity()));
9254 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves
9255 // memory allocation/deletion purpose only.
9256 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd(
9257 MapType,
9258 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO |
9259 MappableExprsHandler::OMP_MAP_FROM)));
9260 // Call the runtime API __tgt_push_mapper_component to fill up the runtime
9261 // data structure.
9262 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg};
9263 MapperCGF.EmitRuntimeCall(
9264 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs);
9265}
9266
Alexey Bataev7bb33532019-01-07 21:30:43 +00009267void CGOpenMPRuntime::emitTargetNumIterationsCall(
Alexey Bataevec7946e2019-09-23 14:06:51 +00009268 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9269 llvm::Value *DeviceID,
9270 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9271 const OMPLoopDirective &D)>
9272 SizeEmitter) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00009273 OpenMPDirectiveKind Kind = D.getDirectiveKind();
9274 const OMPExecutableDirective *TD = &D;
9275 // Get nested teams distribute kind directive, if any.
9276 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind))
9277 TD = getNestedDistributeDirective(CGM.getContext(), D);
9278 if (!TD)
9279 return;
9280 const auto *LD = cast<OMPLoopDirective>(TD);
Alexey Bataevec7946e2019-09-23 14:06:51 +00009281 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF,
Alexey Bataev7bb33532019-01-07 21:30:43 +00009282 PrePostActionTy &) {
Alexey Bataevec7946e2019-09-23 14:06:51 +00009283 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) {
9284 llvm::Value *Args[] = {DeviceID, NumIterations};
9285 CGF.EmitRuntimeCall(
9286 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args);
9287 }
Alexey Bataev7bb33532019-01-07 21:30:43 +00009288 };
9289 emitInlinedDirective(CGF, OMPD_unknown, CodeGen);
9290}
9291
Alexey Bataevec7946e2019-09-23 14:06:51 +00009292void CGOpenMPRuntime::emitTargetCall(
9293 CodeGenFunction &CGF, const OMPExecutableDirective &D,
9294 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
9295 const Expr *Device,
9296 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
9297 const OMPLoopDirective &D)>
9298 SizeEmitter) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00009299 if (!CGF.HaveInsertPoint())
9300 return;
Samuel Antaobed3c462015-10-02 16:14:20 +00009301
Samuel Antaoee8fb302016-01-06 13:42:12 +00009302 assert(OutlinedFn && "Invalid outlined function!");
9303
Alexey Bataev8451efa2018-01-15 19:06:12 +00009304 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>();
9305 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
Alexey Bataev475a7442018-01-12 19:39:11 +00009306 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009307 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF,
9308 PrePostActionTy &) {
9309 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9310 };
9311 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen);
Samuel Antao86ace552016-04-27 22:40:57 +00009312
Alexey Bataev8451efa2018-01-15 19:06:12 +00009313 CodeGenFunction::OMPTargetDataInfo InputInfo;
9314 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobed3c462015-10-02 16:14:20 +00009315 // Fill up the pointer arrays and transfer execution to the device.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009316 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo,
Alexey Bataevec7946e2019-09-23 14:06:51 +00009317 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars,
9318 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobed3c462015-10-02 16:14:20 +00009319 // On top of the arrays that were filled up, the target offloading call
9320 // takes as arguments the device id as well as the host pointer. The host
9321 // pointer is used by the runtime library to identify the current target
9322 // region, so it only has to be unique and not necessarily point to
9323 // anything. It could be the pointer to the outlined function that
9324 // implements the target region, but we aren't using that so that the
9325 // compiler doesn't need to keep that, and could therefore inline the host
9326 // function if proven worthwhile during optimization.
9327
Samuel Antaoee8fb302016-01-06 13:42:12 +00009328 // From this point on, we need to have an ID of the target region defined.
9329 assert(OutlinedFnID && "Invalid outlined function ID!");
Samuel Antaobed3c462015-10-02 16:14:20 +00009330
9331 // Emit device ID if any.
9332 llvm::Value *DeviceID;
George Rokos63bc9d62017-11-21 18:25:12 +00009333 if (Device) {
Samuel Antaobed3c462015-10-02 16:14:20 +00009334 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009335 CGF.Int64Ty, /*isSigned=*/true);
9336 } else {
9337 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9338 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009339
Samuel Antaodf158d52016-04-27 22:58:19 +00009340 // Emit the number of elements in the offloading arrays.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009341 llvm::Value *PointerNum =
9342 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaodf158d52016-04-27 22:58:19 +00009343
Samuel Antaob68e2db2016-03-03 16:20:23 +00009344 // Return value of the runtime offloading call.
9345 llvm::Value *Return;
9346
Alexey Bataev5c427362019-04-10 19:11:33 +00009347 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D);
9348 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009349
Alexey Bataevec7946e2019-09-23 14:06:51 +00009350 // Emit tripcount for the target loop-based directive.
9351 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter);
9352
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009353 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00009354 // The target region is an outlined function launched by the runtime
9355 // via calls __tgt_target() or __tgt_target_teams().
9356 //
9357 // __tgt_target() launches a target region with one team and one thread,
9358 // executing a serial region. This master thread may in turn launch
9359 // more threads within its team upon encountering a parallel region,
9360 // however, no additional teams can be launched on the device.
9361 //
9362 // __tgt_target_teams() launches a target region with one or more teams,
9363 // each with one or more threads. This call is required for target
9364 // constructs such as:
9365 // 'target teams'
9366 // 'target' / 'teams'
9367 // 'target teams distribute parallel for'
9368 // 'target parallel'
9369 // and so on.
9370 //
9371 // Note that on the host and CPU targets, the runtime implementation of
9372 // these calls simply call the outlined function without forking threads.
9373 // The outlined functions themselves have runtime calls to
9374 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by
9375 // the compiler in emitTeamsCall() and emitParallelCall().
9376 //
9377 // In contrast, on the NVPTX target, the implementation of
9378 // __tgt_target_teams() launches a GPU kernel with the requested number
9379 // of teams and threads so no additional calls to the runtime are required.
Samuel Antaob68e2db2016-03-03 16:20:23 +00009380 if (NumTeams) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00009381 // If we have NumTeams defined this means that we have an enclosed teams
9382 // region. Therefore we also expect to have NumThreads defined. These two
9383 // values should be defined in the presence of a teams directive,
9384 // regardless of having any clauses associated. If the user is using teams
9385 // but no clauses, these two values will be the default that should be
9386 // passed to the runtime library - a 32-bit integer with the value zero.
9387 assert(NumThreads && "Thread limit expression should be available along "
9388 "with number of teams.");
Alexey Bataev8451efa2018-01-15 19:06:12 +00009389 llvm::Value *OffloadingArgs[] = {DeviceID,
9390 OutlinedFnID,
9391 PointerNum,
9392 InputInfo.BasePointersArray.getPointer(),
9393 InputInfo.PointersArray.getPointer(),
9394 InputInfo.SizesArray.getPointer(),
9395 MapTypesArray,
9396 NumTeams,
9397 NumThreads};
Samuel Antaob68e2db2016-03-03 16:20:23 +00009398 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00009399 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait
9400 : OMPRTL__tgt_target_teams),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009401 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009402 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009403 llvm::Value *OffloadingArgs[] = {DeviceID,
9404 OutlinedFnID,
9405 PointerNum,
9406 InputInfo.BasePointersArray.getPointer(),
9407 InputInfo.PointersArray.getPointer(),
9408 InputInfo.SizesArray.getPointer(),
9409 MapTypesArray};
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009410 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00009411 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait
9412 : OMPRTL__tgt_target),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00009413 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00009414 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009415
Alexey Bataev2a007e02017-10-02 14:20:58 +00009416 // Check the error code and execute the host version if required.
9417 llvm::BasicBlock *OffloadFailedBlock =
9418 CGF.createBasicBlock("omp_offload.failed");
9419 llvm::BasicBlock *OffloadContBlock =
9420 CGF.createBasicBlock("omp_offload.cont");
9421 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return);
9422 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
9423
9424 CGF.EmitBlock(OffloadFailedBlock);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009425 if (RequiresOuterTask) {
9426 CapturedVars.clear();
9427 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9428 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009429 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev2a007e02017-10-02 14:20:58 +00009430 CGF.EmitBranch(OffloadContBlock);
9431
9432 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00009433 };
9434
Samuel Antaoee8fb302016-01-06 13:42:12 +00009435 // Notify that the host version must be executed.
Alexey Bataev8451efa2018-01-15 19:06:12 +00009436 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars,
9437 RequiresOuterTask](CodeGenFunction &CGF,
9438 PrePostActionTy &) {
9439 if (RequiresOuterTask) {
9440 CapturedVars.clear();
9441 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
9442 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009443 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009444 };
9445
9446 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray,
9447 &CapturedVars, RequiresOuterTask,
9448 &CS](CodeGenFunction &CGF, PrePostActionTy &) {
9449 // Fill up the arrays with all the captured variables.
9450 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
9451 MappableExprsHandler::MapValuesArrayTy Pointers;
9452 MappableExprsHandler::MapValuesArrayTy Sizes;
9453 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9454
Alexey Bataev8451efa2018-01-15 19:06:12 +00009455 // Get mappable expression information.
9456 MappableExprsHandler MEHandler(D, CGF);
Alexey Bataev969dbc02018-11-08 15:47:39 +00009457 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
Alexey Bataev8451efa2018-01-15 19:06:12 +00009458
9459 auto RI = CS.getCapturedRecordDecl()->field_begin();
9460 auto CV = CapturedVars.begin();
9461 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
9462 CE = CS.capture_end();
9463 CI != CE; ++CI, ++RI, ++CV) {
Alexey Bataevb3638132018-07-19 16:34:13 +00009464 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers;
9465 MappableExprsHandler::MapValuesArrayTy CurPointers;
9466 MappableExprsHandler::MapValuesArrayTy CurSizes;
9467 MappableExprsHandler::MapFlagsArrayTy CurMapTypes;
9468 MappableExprsHandler::StructRangeInfoTy PartialStruct;
Alexey Bataev8451efa2018-01-15 19:06:12 +00009469
9470 // VLA sizes are passed to the outlined region by copy and do not have map
9471 // information associated.
9472 if (CI->capturesVariableArrayType()) {
9473 CurBasePointers.push_back(*CV);
9474 CurPointers.push_back(*CV);
Alexey Bataeva90fc662019-06-25 16:00:43 +00009475 CurSizes.push_back(CGF.Builder.CreateIntCast(
9476 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true));
Alexey Bataev8451efa2018-01-15 19:06:12 +00009477 // Copy to the device as an argument. No need to retrieve it.
9478 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL |
Alexey Bataevf288cf92019-06-27 18:53:07 +00009479 MappableExprsHandler::OMP_MAP_TARGET_PARAM |
9480 MappableExprsHandler::OMP_MAP_IMPLICIT);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009481 } else {
9482 // If we have any information in the map clause, we use it, otherwise we
9483 // just do a default mapping.
9484 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00009485 CurSizes, CurMapTypes, PartialStruct);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009486 if (CurBasePointers.empty())
9487 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers,
9488 CurPointers, CurSizes, CurMapTypes);
Alexey Bataev60705422018-10-30 15:50:12 +00009489 // Generate correct mapping for variables captured by reference in
9490 // lambdas.
9491 if (CI->capturesVariable())
Alexey Bataev969dbc02018-11-08 15:47:39 +00009492 MEHandler.generateInfoForLambdaCaptures(
9493 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes,
9494 CurMapTypes, LambdaPointers);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009495 }
9496 // We expect to have at least an element of information for this capture.
9497 assert(!CurBasePointers.empty() &&
9498 "Non-existing map pointer for capture!");
9499 assert(CurBasePointers.size() == CurPointers.size() &&
9500 CurBasePointers.size() == CurSizes.size() &&
9501 CurBasePointers.size() == CurMapTypes.size() &&
9502 "Inconsistent map information sizes!");
9503
Alexey Bataevb3638132018-07-19 16:34:13 +00009504 // If there is an entry in PartialStruct it means we have a struct with
9505 // individual members mapped. Emit an extra combined entry.
9506 if (PartialStruct.Base.isValid())
9507 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes,
9508 CurMapTypes, PartialStruct);
9509
Alexey Bataev8451efa2018-01-15 19:06:12 +00009510 // We need to append the results of this capture to what we already have.
9511 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
9512 Pointers.append(CurPointers.begin(), CurPointers.end());
9513 Sizes.append(CurSizes.begin(), CurSizes.end());
9514 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end());
9515 }
Alexey Bataev60705422018-10-30 15:50:12 +00009516 // Adjust MEMBER_OF flags for the lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00009517 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers,
9518 Pointers, MapTypes);
Alexey Bataev92327c52018-03-26 16:40:55 +00009519 // Map other list items in the map clause which are not captured variables
9520 // but "declare target link" global variables.
Alexey Bataevb3638132018-07-19 16:34:13 +00009521 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes,
9522 MapTypes);
Alexey Bataev8451efa2018-01-15 19:06:12 +00009523
9524 TargetDataInfo Info;
9525 // Fill up the arrays and create the arguments.
9526 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
9527 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
9528 Info.PointersArray, Info.SizesArray,
9529 Info.MapTypesArray, Info);
9530 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
9531 InputInfo.BasePointersArray =
9532 Address(Info.BasePointersArray, CGM.getPointerAlign());
9533 InputInfo.PointersArray =
9534 Address(Info.PointersArray, CGM.getPointerAlign());
9535 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign());
9536 MapTypesArray = Info.MapTypesArray;
9537 if (RequiresOuterTask)
9538 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
9539 else
9540 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
9541 };
9542
9543 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask](
9544 CodeGenFunction &CGF, PrePostActionTy &) {
9545 if (RequiresOuterTask) {
9546 CodeGenFunction::OMPTargetDataInfo InputInfo;
9547 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo);
9548 } else {
9549 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen);
9550 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009551 };
9552
9553 // If we have a target function ID it means that we need to support
9554 // offloading, otherwise, just execute on the host. We need to execute on host
9555 // regardless of the conditional in the if clause if, e.g., the user do not
9556 // specify target triples.
9557 if (OutlinedFnID) {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009558 if (IfCond) {
9559 emitOMPIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
9560 } else {
9561 RegionCodeGenTy ThenRCG(TargetThenGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00009562 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00009563 }
9564 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00009565 RegionCodeGenTy ElseRCG(TargetElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00009566 ElseRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00009567 }
Samuel Antaobed3c462015-10-02 16:14:20 +00009568}
Samuel Antaoee8fb302016-01-06 13:42:12 +00009569
9570void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
9571 StringRef ParentName) {
9572 if (!S)
9573 return;
9574
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009575 // Codegen OMP target directives that offload compute to the device.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009576 bool RequiresDeviceCodegen =
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009577 isa<OMPExecutableDirective>(S) &&
9578 isOpenMPTargetExecutionDirective(
9579 cast<OMPExecutableDirective>(S)->getDirectiveKind());
Samuel Antaoee8fb302016-01-06 13:42:12 +00009580
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009581 if (RequiresDeviceCodegen) {
9582 const auto &E = *cast<OMPExecutableDirective>(S);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009583 unsigned DeviceID;
9584 unsigned FileID;
9585 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00009586 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID,
Samuel Antao2de62b02016-02-13 23:35:10 +00009587 FileID, Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009588
9589 // Is this a target region that should not be emitted as an entry point? If
9590 // so just signal we are done with this target region.
Samuel Antao2de62b02016-02-13 23:35:10 +00009591 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
9592 ParentName, Line))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009593 return;
9594
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009595 switch (E.getDirectiveKind()) {
9596 case OMPD_target:
9597 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName,
9598 cast<OMPTargetDirective>(E));
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009599 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009600 case OMPD_target_parallel:
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009601 CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009602 CGM, ParentName, cast<OMPTargetParallelDirective>(E));
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00009603 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009604 case OMPD_target_teams:
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009605 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009606 CGM, ParentName, cast<OMPTargetTeamsDirective>(E));
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00009607 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009608 case OMPD_target_teams_distribute:
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009609 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009610 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E));
Alexey Bataevdfa430f2017-12-08 15:03:50 +00009611 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009612 case OMPD_target_teams_distribute_simd:
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009613 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009614 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E));
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00009615 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009616 case OMPD_target_parallel_for:
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009617 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009618 CGM, ParentName, cast<OMPTargetParallelForDirective>(E));
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00009619 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009620 case OMPD_target_parallel_for_simd:
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009621 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009622 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E));
Alexey Bataev5d7edca2017-11-09 17:32:15 +00009623 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009624 case OMPD_target_simd:
Alexey Bataevf8365372017-11-17 17:57:25 +00009625 CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009626 CGM, ParentName, cast<OMPTargetSimdDirective>(E));
Alexey Bataevf8365372017-11-17 17:57:25 +00009627 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009628 case OMPD_target_teams_distribute_parallel_for:
Carlo Bertolli52978c32018-01-03 21:12:44 +00009629 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
9630 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009631 cast<OMPTargetTeamsDistributeParallelForDirective>(E));
Carlo Bertolli52978c32018-01-03 21:12:44 +00009632 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009633 case OMPD_target_teams_distribute_parallel_for_simd:
Alexey Bataev647dd842018-01-15 20:59:40 +00009634 CodeGenFunction::
9635 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
9636 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009637 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E));
Alexey Bataev647dd842018-01-15 20:59:40 +00009638 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009639 case OMPD_parallel:
9640 case OMPD_for:
9641 case OMPD_parallel_for:
9642 case OMPD_parallel_sections:
9643 case OMPD_for_simd:
9644 case OMPD_parallel_for_simd:
9645 case OMPD_cancel:
9646 case OMPD_cancellation_point:
9647 case OMPD_ordered:
9648 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00009649 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009650 case OMPD_task:
9651 case OMPD_simd:
9652 case OMPD_sections:
9653 case OMPD_section:
9654 case OMPD_single:
9655 case OMPD_master:
9656 case OMPD_critical:
9657 case OMPD_taskyield:
9658 case OMPD_barrier:
9659 case OMPD_taskwait:
9660 case OMPD_taskgroup:
9661 case OMPD_atomic:
9662 case OMPD_flush:
9663 case OMPD_teams:
9664 case OMPD_target_data:
9665 case OMPD_target_exit_data:
9666 case OMPD_target_enter_data:
9667 case OMPD_distribute:
9668 case OMPD_distribute_simd:
9669 case OMPD_distribute_parallel_for:
9670 case OMPD_distribute_parallel_for_simd:
9671 case OMPD_teams_distribute:
9672 case OMPD_teams_distribute_simd:
9673 case OMPD_teams_distribute_parallel_for:
9674 case OMPD_teams_distribute_parallel_for_simd:
9675 case OMPD_target_update:
9676 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +00009677 case OMPD_declare_variant:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009678 case OMPD_declare_target:
9679 case OMPD_end_declare_target:
9680 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00009681 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009682 case OMPD_taskloop:
9683 case OMPD_taskloop_simd:
Kelvin Li1408f912018-09-26 04:28:39 +00009684 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009685 case OMPD_unknown:
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00009686 llvm_unreachable("Unknown target directive for OpenMP device codegen.");
9687 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009688 return;
9689 }
9690
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009691 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
Alexey Bataev475a7442018-01-12 19:39:11 +00009692 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009693 return;
9694
9695 scanForTargetRegionsFunctions(
Alexey Bataev475a7442018-01-12 19:39:11 +00009696 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009697 return;
9698 }
9699
9700 // If this is a lambda function, look into its body.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009701 if (const auto *L = dyn_cast<LambdaExpr>(S))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009702 S = L->getBody();
9703
9704 // Keep looking for target regions recursively.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009705 for (const Stmt *II : S->children())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009706 scanForTargetRegionsFunctions(II, ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009707}
9708
9709bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009710 // If emitting code for the host, we do not process FD here. Instead we do
9711 // the normal code generation.
Alexey Bataev729e2422019-08-23 16:11:14 +00009712 if (!CGM.getLangOpts().OpenMPIsDevice) {
9713 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) {
9714 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9715 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9716 // Do not emit device_type(nohost) functions for the host.
9717 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost)
9718 return true;
9719 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009720 return false;
Alexey Bataev729e2422019-08-23 16:11:14 +00009721 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009722
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009723 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009724 StringRef Name = CGM.getMangledName(GD);
9725 // Try to detect target regions in the function.
Alexey Bataev729e2422019-08-23 16:11:14 +00009726 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009727 scanForTargetRegionsFunctions(FD->getBody(), Name);
Alexey Bataev729e2422019-08-23 16:11:14 +00009728 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy =
9729 OMPDeclareTargetDeclAttr::getDeviceType(FD);
9730 // Do not emit device_type(nohost) functions for the host.
9731 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host)
9732 return true;
9733 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00009734
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009735 // Do not to emit function if it is not marked as declare target.
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009736 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009737 AlreadyEmittedTargetFunctions.count(Name) == 0;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009738}
9739
9740bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
9741 if (!CGM.getLangOpts().OpenMPIsDevice)
9742 return false;
9743
9744 // Check if there are Ctors/Dtors in this declaration and look for target
9745 // regions in it. We use the complete variant to produce the kernel name
9746 // mangling.
9747 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009748 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
9749 for (const CXXConstructorDecl *Ctor : RD->ctors()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009750 StringRef ParentName =
9751 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
9752 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
9753 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009754 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009755 StringRef ParentName =
9756 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
9757 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
9758 }
9759 }
9760
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009761 // Do not to emit variable if it is not marked as declare target.
Alexey Bataev92327c52018-03-26 16:40:55 +00009762 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009763 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
9764 cast<VarDecl>(GD.getDecl()));
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009765 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
9766 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9767 HasRequiresUnifiedSharedMemory)) {
Alexey Bataevd01b7492018-08-15 19:45:12 +00009768 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009769 return true;
9770 }
9771 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009772}
9773
Alexey Bataev1af5bd52019-03-05 17:47:18 +00009774llvm::Constant *
9775CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF,
9776 const VarDecl *VD) {
9777 assert(VD->getType().isConstant(CGM.getContext()) &&
9778 "Expected constant variable.");
9779 StringRef VarName;
9780 llvm::Constant *Addr;
9781 llvm::GlobalValue::LinkageTypes Linkage;
9782 QualType Ty = VD->getType();
9783 SmallString<128> Buffer;
9784 {
9785 unsigned DeviceID;
9786 unsigned FileID;
9787 unsigned Line;
9788 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID,
9789 FileID, Line);
9790 llvm::raw_svector_ostream OS(Buffer);
9791 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID)
9792 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
9793 VarName = OS.str();
9794 }
9795 Linkage = llvm::GlobalValue::InternalLinkage;
9796 Addr =
9797 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName,
9798 getDefaultFirstprivateAddressSpace());
9799 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage);
9800 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty);
9801 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr));
9802 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9803 VarName, Addr, VarSize,
9804 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage);
9805 return Addr;
9806}
9807
Alexey Bataev03f270c2018-03-30 18:31:07 +00009808void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
9809 llvm::Constant *Addr) {
Alexey Bataev36724b72019-10-03 16:46:49 +00009810 if (CGM.getLangOpts().OMPTargetTriples.empty() &&
9811 !CGM.getLangOpts().OpenMPIsDevice)
Alexey Bataev4db9dc62019-09-23 15:53:51 +00009812 return;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009813 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9814 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
9815 if (!Res) {
9816 if (CGM.getLangOpts().OpenMPIsDevice) {
9817 // Register non-target variables being emitted in device code (debug info
9818 // may cause this).
9819 StringRef VarName = CGM.getMangledName(VD);
9820 EmittedNonTargetVariables.try_emplace(VarName, Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009821 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009822 return;
Alexey Bataev03f270c2018-03-30 18:31:07 +00009823 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009824 // Register declare target variables.
9825 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
9826 StringRef VarName;
9827 CharUnits VarSize;
9828 llvm::GlobalValue::LinkageTypes Linkage;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009829
9830 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9831 !HasRequiresUnifiedSharedMemory) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009832 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9833 VarName = CGM.getMangledName(VD);
9834 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) {
9835 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType());
9836 assert(!VarSize.isZero() && "Expected non-zero size of the variable");
9837 } else {
9838 VarSize = CharUnits::Zero();
9839 }
9840 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
9841 // Temp solution to prevent optimizations of the internal variables.
9842 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) {
9843 std::string RefName = getName({VarName, "ref"});
9844 if (!CGM.GetGlobalValue(RefName)) {
9845 llvm::Constant *AddrRef =
9846 getOrCreateInternalVariable(Addr->getType(), RefName);
9847 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef);
9848 GVAddrRef->setConstant(/*Val=*/true);
9849 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage);
9850 GVAddrRef->setInitializer(Addr);
9851 CGM.addCompilerUsedGlobal(GVAddrRef);
9852 }
9853 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009854 } else {
9855 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
9856 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9857 HasRequiresUnifiedSharedMemory)) &&
9858 "Declare target attribute must link or to with unified memory.");
9859 if (*Res == OMPDeclareTargetDeclAttr::MT_Link)
9860 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink;
9861 else
9862 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9863
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009864 if (CGM.getLangOpts().OpenMPIsDevice) {
9865 VarName = Addr->getName();
9866 Addr = nullptr;
9867 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009868 VarName = getAddrOfDeclareTargetVar(VD).getName();
9869 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009870 }
9871 VarSize = CGM.getPointerSize();
9872 Linkage = llvm::GlobalValue::WeakAnyLinkage;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009873 }
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009874
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009875 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9876 VarName, Addr, VarSize, Flags, Linkage);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009877}
9878
Samuel Antaoee8fb302016-01-06 13:42:12 +00009879bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009880 if (isa<FunctionDecl>(GD.getDecl()) ||
9881 isa<OMPDeclareReductionDecl>(GD.getDecl()))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009882 return emitTargetFunctions(GD);
9883
9884 return emitTargetGlobalVariable(GD);
9885}
9886
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009887void CGOpenMPRuntime::emitDeferredTargetDecls() const {
9888 for (const VarDecl *VD : DeferredGlobalVariables) {
9889 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009890 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009891 if (!Res)
9892 continue;
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009893 if (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9894 !HasRequiresUnifiedSharedMemory) {
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009895 CGM.EmitGlobal(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009896 } else {
Gheorghe-Teodor Bercea0034e842019-06-20 18:04:47 +00009897 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
9898 (*Res == OMPDeclareTargetDeclAttr::MT_To &&
9899 HasRequiresUnifiedSharedMemory)) &&
9900 "Expected link clause or to clause with unified memory.");
9901 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009902 }
9903 }
9904}
9905
Alexey Bataev60705422018-10-30 15:50:12 +00009906void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas(
9907 CodeGenFunction &CGF, const OMPExecutableDirective &D) const {
9908 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) &&
9909 " Expected target-based directive.");
9910}
9911
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009912void CGOpenMPRuntime::checkArchForUnifiedAddressing(
9913 const OMPRequiresDecl *D) {
9914 for (const OMPClause *Clause : D->clauselists()) {
9915 if (Clause->getClauseKind() == OMPC_unified_shared_memory) {
9916 HasRequiresUnifiedSharedMemory = true;
9917 break;
9918 }
9919 }
9920}
9921
Alexey Bataevc5687252019-03-21 19:35:27 +00009922bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD,
9923 LangAS &AS) {
9924 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())
9925 return false;
9926 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
9927 switch(A->getAllocatorType()) {
9928 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
9929 // Not supported, fallback to the default mem space.
9930 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
9931 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
9932 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
9933 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
9934 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
9935 case OMPAllocateDeclAttr::OMPConstMemAlloc:
9936 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
9937 AS = LangAS::Default;
9938 return true;
9939 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
9940 llvm_unreachable("Expected predefined allocator for the variables with the "
9941 "static storage.");
9942 }
9943 return false;
9944}
9945
Gheorghe-Teodor Bercea5254f0a2019-06-14 17:58:26 +00009946bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const {
9947 return HasRequiresUnifiedSharedMemory;
9948}
9949
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009950CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
9951 CodeGenModule &CGM)
9952 : CGM(CGM) {
9953 if (CGM.getLangOpts().OpenMPIsDevice) {
9954 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
9955 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
9956 }
9957}
9958
9959CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() {
9960 if (CGM.getLangOpts().OpenMPIsDevice)
9961 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
9962}
9963
Alexey Bataev6d944102018-05-02 15:45:28 +00009964bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009965 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal)
9966 return true;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009967
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009968 StringRef Name = CGM.getMangledName(GD);
Alexey Bataev6d944102018-05-02 15:45:28 +00009969 const auto *D = cast<FunctionDecl>(GD.getDecl());
Alexey Bataev34f8a702018-03-28 14:28:54 +00009970 // Do not to emit function if it is marked as declare target as it was already
9971 // emitted.
Alexey Bataev97b72212018-08-14 18:31:20 +00009972 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009973 if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) {
9974 if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name)))
Alexey Bataev34f8a702018-03-28 14:28:54 +00009975 return !F->isDeclaration();
9976 return false;
9977 }
9978 return true;
9979 }
9980
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009981 return !AlreadyEmittedTargetFunctions.insert(Name).second;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009982}
9983
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +00009984llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() {
9985 // If we don't have entries or if we are emitting code for the device, we
9986 // don't need to do anything.
9987 if (CGM.getLangOpts().OMPTargetTriples.empty() ||
9988 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice ||
9989 (OffloadEntriesInfoManager.empty() &&
9990 !HasEmittedDeclareTargetRegion &&
9991 !HasEmittedTargetRegion))
9992 return nullptr;
9993
9994 // Create and register the function that handles the requires directives.
9995 ASTContext &C = CGM.getContext();
9996
9997 llvm::Function *RequiresRegFn;
9998 {
9999 CodeGenFunction CGF(CGM);
10000 const auto &FI = CGM.getTypes().arrangeNullaryFunction();
10001 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
10002 std::string ReqName = getName({"omp_offloading", "requires_reg"});
10003 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI);
10004 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {});
10005 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE;
10006 // TODO: check for other requires clauses.
10007 // The requires directive takes effect only when a target region is
10008 // present in the compilation unit. Otherwise it is ignored and not
10009 // passed to the runtime. This avoids the runtime from throwing an error
10010 // for mismatching requires clauses across compilation units that don't
10011 // contain at least 1 target region.
10012 assert((HasEmittedTargetRegion ||
10013 HasEmittedDeclareTargetRegion ||
10014 !OffloadEntriesInfoManager.empty()) &&
10015 "Target or declare target region expected.");
10016 if (HasRequiresUnifiedSharedMemory)
10017 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY;
10018 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires),
10019 llvm::ConstantInt::get(CGM.Int64Ty, Flags));
10020 CGF.FinishFunction();
10021 }
10022 return RequiresRegFn;
10023}
10024
Samuel Antaoee8fb302016-01-06 13:42:12 +000010025llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() {
10026 // If we have offloading in the current module, we need to emit the entries
10027 // now and register the offloading descriptor.
10028 createOffloadEntriesAndInfoMetadata();
10029
10030 // Create and register the offloading binary descriptors. This is the main
10031 // entity that captures all the information about offloading in the current
10032 // compilation unit.
10033 return createOffloadingBinaryDescriptorRegistration();
10034}
Carlo Bertolli430d8ec2016-03-03 20:34:23 +000010035
10036void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
10037 const OMPExecutableDirective &D,
10038 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000010039 llvm::Function *OutlinedFn,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +000010040 ArrayRef<llvm::Value *> CapturedVars) {
10041 if (!CGF.HaveInsertPoint())
10042 return;
10043
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010044 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +000010045 CodeGenFunction::RunCleanupsScope Scope(CGF);
10046
10047 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
10048 llvm::Value *Args[] = {
10049 RTLoc,
10050 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
10051 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
10052 llvm::SmallVector<llvm::Value *, 16> RealArgs;
10053 RealArgs.append(std::begin(Args), std::end(Args));
10054 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
10055
James Y Knight9871db02019-02-05 16:42:33 +000010056 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +000010057 CGF.EmitRuntimeCall(RTLFn, RealArgs);
10058}
10059
10060void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
Carlo Bertollic6872252016-04-04 15:55:02 +000010061 const Expr *NumTeams,
10062 const Expr *ThreadLimit,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +000010063 SourceLocation Loc) {
10064 if (!CGF.HaveInsertPoint())
10065 return;
10066
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010067 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +000010068
Carlo Bertollic6872252016-04-04 15:55:02 +000010069 llvm::Value *NumTeamsVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010070 NumTeams
Carlo Bertollic6872252016-04-04 15:55:02 +000010071 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
10072 CGF.CGM.Int32Ty, /* isSigned = */ true)
10073 : CGF.Builder.getInt32(0);
10074
10075 llvm::Value *ThreadLimitVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010076 ThreadLimit
Carlo Bertollic6872252016-04-04 15:55:02 +000010077 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
10078 CGF.CGM.Int32Ty, /* isSigned = */ true)
10079 : CGF.Builder.getInt32(0);
10080
Carlo Bertolli430d8ec2016-03-03 20:34:23 +000010081 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
Carlo Bertollic6872252016-04-04 15:55:02 +000010082 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
10083 ThreadLimitVal};
Carlo Bertolli430d8ec2016-03-03 20:34:23 +000010084 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams),
10085 PushNumTeamsArgs);
10086}
Samuel Antaodf158d52016-04-27 22:58:19 +000010087
Samuel Antaocc10b852016-07-28 14:23:26 +000010088void CGOpenMPRuntime::emitTargetDataCalls(
10089 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10090 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
Samuel Antaodf158d52016-04-27 22:58:19 +000010091 if (!CGF.HaveInsertPoint())
10092 return;
10093
Samuel Antaocc10b852016-07-28 14:23:26 +000010094 // Action used to replace the default codegen action and turn privatization
10095 // off.
10096 PrePostActionTy NoPrivAction;
Samuel Antaodf158d52016-04-27 22:58:19 +000010097
10098 // Generate the code for the opening of the data environment. Capture all the
10099 // arguments of the runtime call by reference because they are used in the
10100 // closing of the region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010101 auto &&BeginThenGen = [this, &D, Device, &Info,
10102 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaodf158d52016-04-27 22:58:19 +000010103 // Fill up the arrays with all the mapped variables.
Samuel Antaocc10b852016-07-28 14:23:26 +000010104 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
Samuel Antaodf158d52016-04-27 22:58:19 +000010105 MappableExprsHandler::MapValuesArrayTy Pointers;
10106 MappableExprsHandler::MapValuesArrayTy Sizes;
10107 MappableExprsHandler::MapFlagsArrayTy MapTypes;
10108
10109 // Get map clause information.
10110 MappableExprsHandler MCHandler(D, CGF);
10111 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
Samuel Antaodf158d52016-04-27 22:58:19 +000010112
10113 // Fill up the arrays and create the arguments.
Samuel Antaocc10b852016-07-28 14:23:26 +000010114 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +000010115
10116 llvm::Value *BasePointersArrayArg = nullptr;
10117 llvm::Value *PointersArrayArg = nullptr;
10118 llvm::Value *SizesArrayArg = nullptr;
10119 llvm::Value *MapTypesArrayArg = nullptr;
10120 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +000010121 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +000010122
10123 // Emit device ID if any.
10124 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010125 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +000010126 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010127 CGF.Int64Ty, /*isSigned=*/true);
10128 } else {
10129 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10130 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010131
10132 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010133 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +000010134
10135 llvm::Value *OffloadingArgs[] = {
10136 DeviceID, PointerNum, BasePointersArrayArg,
10137 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010138 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin),
Samuel Antaodf158d52016-04-27 22:58:19 +000010139 OffloadingArgs);
Samuel Antaocc10b852016-07-28 14:23:26 +000010140
10141 // If device pointer privatization is required, emit the body of the region
10142 // here. It will have to be duplicated: with and without privatization.
10143 if (!Info.CaptureDeviceAddrMap.empty())
10144 CodeGen(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010145 };
10146
10147 // Generate code for the closing of the data region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010148 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF,
10149 PrePostActionTy &) {
Samuel Antaocc10b852016-07-28 14:23:26 +000010150 assert(Info.isValid() && "Invalid data environment closing arguments.");
Samuel Antaodf158d52016-04-27 22:58:19 +000010151
10152 llvm::Value *BasePointersArrayArg = nullptr;
10153 llvm::Value *PointersArrayArg = nullptr;
10154 llvm::Value *SizesArrayArg = nullptr;
10155 llvm::Value *MapTypesArrayArg = nullptr;
10156 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +000010157 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +000010158
10159 // Emit device ID if any.
10160 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010161 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +000010162 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010163 CGF.Int64Ty, /*isSigned=*/true);
10164 } else {
10165 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10166 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010167
10168 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010169 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +000010170
10171 llvm::Value *OffloadingArgs[] = {
10172 DeviceID, PointerNum, BasePointersArrayArg,
10173 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010174 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end),
Samuel Antaodf158d52016-04-27 22:58:19 +000010175 OffloadingArgs);
10176 };
10177
Samuel Antaocc10b852016-07-28 14:23:26 +000010178 // If we need device pointer privatization, we need to emit the body of the
10179 // region with no privatization in the 'else' branch of the conditional.
10180 // Otherwise, we don't have to do anything.
10181 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF,
10182 PrePostActionTy &) {
10183 if (!Info.CaptureDeviceAddrMap.empty()) {
10184 CodeGen.setAction(NoPrivAction);
10185 CodeGen(CGF);
10186 }
10187 };
10188
10189 // We don't have to do anything to close the region if the if clause evaluates
10190 // to false.
10191 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
Samuel Antaodf158d52016-04-27 22:58:19 +000010192
10193 if (IfCond) {
Samuel Antaocc10b852016-07-28 14:23:26 +000010194 emitOMPIfClause(CGF, IfCond, BeginThenGen, BeginElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +000010195 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +000010196 RegionCodeGenTy RCG(BeginThenGen);
10197 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010198 }
10199
Samuel Antaocc10b852016-07-28 14:23:26 +000010200 // If we don't require privatization of device pointers, we emit the body in
10201 // between the runtime calls. This avoids duplicating the body code.
10202 if (Info.CaptureDeviceAddrMap.empty()) {
10203 CodeGen.setAction(NoPrivAction);
10204 CodeGen(CGF);
10205 }
Samuel Antaodf158d52016-04-27 22:58:19 +000010206
10207 if (IfCond) {
Samuel Antaocc10b852016-07-28 14:23:26 +000010208 emitOMPIfClause(CGF, IfCond, EndThenGen, EndElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +000010209 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +000010210 RegionCodeGenTy RCG(EndThenGen);
10211 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +000010212 }
10213}
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010214
Samuel Antao8d2d7302016-05-26 18:30:22 +000010215void CGOpenMPRuntime::emitTargetDataStandAloneCall(
Samuel Antao8dd66282016-04-27 23:14:30 +000010216 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10217 const Expr *Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010218 if (!CGF.HaveInsertPoint())
10219 return;
10220
Samuel Antao8dd66282016-04-27 23:14:30 +000010221 assert((isa<OMPTargetEnterDataDirective>(D) ||
Samuel Antao8d2d7302016-05-26 18:30:22 +000010222 isa<OMPTargetExitDataDirective>(D) ||
10223 isa<OMPTargetUpdateDirective>(D)) &&
10224 "Expecting either target enter, exit data, or update directives.");
Samuel Antao8dd66282016-04-27 23:14:30 +000010225
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010226 CodeGenFunction::OMPTargetDataInfo InputInfo;
10227 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010228 // Generate the code for the opening of the data environment.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010229 auto &&ThenGen = [this, &D, Device, &InputInfo,
10230 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010231 // Emit device ID if any.
10232 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +000010233 if (Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010234 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +000010235 CGF.Int64Ty, /*isSigned=*/true);
10236 } else {
10237 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
10238 }
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010239
10240 // Emit the number of elements in the offloading arrays.
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010241 llvm::Constant *PointerNum =
10242 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010243
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010244 llvm::Value *OffloadingArgs[] = {DeviceID,
10245 PointerNum,
10246 InputInfo.BasePointersArray.getPointer(),
10247 InputInfo.PointersArray.getPointer(),
10248 InputInfo.SizesArray.getPointer(),
10249 MapTypesArray};
Samuel Antao8d2d7302016-05-26 18:30:22 +000010250
Samuel Antao8d2d7302016-05-26 18:30:22 +000010251 // Select the right runtime function call for each expected standalone
10252 // directive.
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010253 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Samuel Antao8d2d7302016-05-26 18:30:22 +000010254 OpenMPRTLFunction RTLFn;
10255 switch (D.getDirectiveKind()) {
Samuel Antao8d2d7302016-05-26 18:30:22 +000010256 case OMPD_target_enter_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010257 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait
10258 : OMPRTL__tgt_target_data_begin;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010259 break;
10260 case OMPD_target_exit_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010261 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait
10262 : OMPRTL__tgt_target_data_end;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010263 break;
10264 case OMPD_target_update:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +000010265 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait
10266 : OMPRTL__tgt_target_data_update;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010267 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010268 case OMPD_parallel:
10269 case OMPD_for:
10270 case OMPD_parallel_for:
10271 case OMPD_parallel_sections:
10272 case OMPD_for_simd:
10273 case OMPD_parallel_for_simd:
10274 case OMPD_cancel:
10275 case OMPD_cancellation_point:
10276 case OMPD_ordered:
10277 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +000010278 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010279 case OMPD_task:
10280 case OMPD_simd:
10281 case OMPD_sections:
10282 case OMPD_section:
10283 case OMPD_single:
10284 case OMPD_master:
10285 case OMPD_critical:
10286 case OMPD_taskyield:
10287 case OMPD_barrier:
10288 case OMPD_taskwait:
10289 case OMPD_taskgroup:
10290 case OMPD_atomic:
10291 case OMPD_flush:
10292 case OMPD_teams:
10293 case OMPD_target_data:
10294 case OMPD_distribute:
10295 case OMPD_distribute_simd:
10296 case OMPD_distribute_parallel_for:
10297 case OMPD_distribute_parallel_for_simd:
10298 case OMPD_teams_distribute:
10299 case OMPD_teams_distribute_simd:
10300 case OMPD_teams_distribute_parallel_for:
10301 case OMPD_teams_distribute_parallel_for_simd:
10302 case OMPD_declare_simd:
Alexey Bataevd158cf62019-09-13 20:18:17 +000010303 case OMPD_declare_variant:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010304 case OMPD_declare_target:
10305 case OMPD_end_declare_target:
10306 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +000010307 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010308 case OMPD_taskloop:
10309 case OMPD_taskloop_simd:
10310 case OMPD_target:
10311 case OMPD_target_simd:
10312 case OMPD_target_teams_distribute:
10313 case OMPD_target_teams_distribute_simd:
10314 case OMPD_target_teams_distribute_parallel_for:
10315 case OMPD_target_teams_distribute_parallel_for_simd:
10316 case OMPD_target_teams:
10317 case OMPD_target_parallel:
10318 case OMPD_target_parallel_for:
10319 case OMPD_target_parallel_for_simd:
Kelvin Li1408f912018-09-26 04:28:39 +000010320 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010321 case OMPD_unknown:
10322 llvm_unreachable("Unexpected standalone target data directive.");
10323 break;
Samuel Antao8d2d7302016-05-26 18:30:22 +000010324 }
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010325 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010326 };
10327
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010328 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray](
10329 CodeGenFunction &CGF, PrePostActionTy &) {
10330 // Fill up the arrays with all the mapped variables.
10331 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
10332 MappableExprsHandler::MapValuesArrayTy Pointers;
10333 MappableExprsHandler::MapValuesArrayTy Sizes;
10334 MappableExprsHandler::MapFlagsArrayTy MapTypes;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010335
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010336 // Get map clause information.
10337 MappableExprsHandler MEHandler(D, CGF);
10338 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
10339
10340 TargetDataInfo Info;
10341 // Fill up the arrays and create the arguments.
10342 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
10343 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
10344 Info.PointersArray, Info.SizesArray,
10345 Info.MapTypesArray, Info);
10346 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
10347 InputInfo.BasePointersArray =
10348 Address(Info.BasePointersArray, CGM.getPointerAlign());
10349 InputInfo.PointersArray =
10350 Address(Info.PointersArray, CGM.getPointerAlign());
10351 InputInfo.SizesArray =
10352 Address(Info.SizesArray, CGM.getPointerAlign());
10353 MapTypesArray = Info.MapTypesArray;
10354 if (D.hasClausesOfKind<OMPDependClause>())
10355 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
10356 else
Alexey Bataev768f1f22018-01-09 19:59:25 +000010357 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010358 };
10359
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010360 if (IfCond) {
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010361 emitOMPIfClause(CGF, IfCond, TargetThenGen,
10362 [](CodeGenFunction &CGF, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010363 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +000010364 RegionCodeGenTy ThenRCG(TargetThenGen);
10365 ThenRCG(CGF);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +000010366 }
10367}
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010368
10369namespace {
10370 /// Kind of parameter in a function with 'declare simd' directive.
10371 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector };
10372 /// Attribute set of the parameter.
10373 struct ParamAttrTy {
10374 ParamKindTy Kind = Vector;
10375 llvm::APSInt StrideOrArg;
10376 llvm::APSInt Alignment;
10377 };
10378} // namespace
10379
10380static unsigned evaluateCDTSize(const FunctionDecl *FD,
10381 ArrayRef<ParamAttrTy> ParamAttrs) {
10382 // Every vector variant of a SIMD-enabled function has a vector length (VLEN).
10383 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument
10384 // of that clause. The VLEN value must be power of 2.
10385 // In other case the notion of the function`s "characteristic data type" (CDT)
10386 // is used to compute the vector length.
10387 // CDT is defined in the following order:
10388 // a) For non-void function, the CDT is the return type.
10389 // b) If the function has any non-uniform, non-linear parameters, then the
10390 // CDT is the type of the first such parameter.
10391 // c) If the CDT determined by a) or b) above is struct, union, or class
10392 // type which is pass-by-value (except for the type that maps to the
10393 // built-in complex data type), the characteristic data type is int.
10394 // d) If none of the above three cases is applicable, the CDT is int.
10395 // The VLEN is then determined based on the CDT and the size of vector
10396 // register of that ISA for which current vector version is generated. The
10397 // VLEN is computed using the formula below:
10398 // VLEN = sizeof(vector_register) / sizeof(CDT),
10399 // where vector register size specified in section 3.2.1 Registers and the
10400 // Stack Frame of original AMD64 ABI document.
10401 QualType RetType = FD->getReturnType();
10402 if (RetType.isNull())
10403 return 0;
10404 ASTContext &C = FD->getASTContext();
10405 QualType CDT;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010406 if (!RetType.isNull() && !RetType->isVoidType()) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010407 CDT = RetType;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010408 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010409 unsigned Offset = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010410 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010411 if (ParamAttrs[Offset].Kind == Vector)
10412 CDT = C.getPointerType(C.getRecordType(MD->getParent()));
10413 ++Offset;
10414 }
10415 if (CDT.isNull()) {
10416 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10417 if (ParamAttrs[I + Offset].Kind == Vector) {
10418 CDT = FD->getParamDecl(I)->getType();
10419 break;
10420 }
10421 }
10422 }
10423 }
10424 if (CDT.isNull())
10425 CDT = C.IntTy;
10426 CDT = CDT->getCanonicalTypeUnqualified();
10427 if (CDT->isRecordType() || CDT->isUnionType())
10428 CDT = C.IntTy;
10429 return C.getTypeSize(CDT);
10430}
10431
10432static void
10433emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
Benjamin Kramer81cb4b72016-11-24 16:01:20 +000010434 const llvm::APSInt &VLENVal,
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010435 ArrayRef<ParamAttrTy> ParamAttrs,
10436 OMPDeclareSimdDeclAttr::BranchStateTy State) {
10437 struct ISADataTy {
10438 char ISA;
10439 unsigned VecRegSize;
10440 };
10441 ISADataTy ISAData[] = {
10442 {
10443 'b', 128
10444 }, // SSE
10445 {
10446 'c', 256
10447 }, // AVX
10448 {
10449 'd', 256
10450 }, // AVX2
10451 {
10452 'e', 512
10453 }, // AVX512
10454 };
10455 llvm::SmallVector<char, 2> Masked;
10456 switch (State) {
10457 case OMPDeclareSimdDeclAttr::BS_Undefined:
10458 Masked.push_back('N');
10459 Masked.push_back('M');
10460 break;
10461 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10462 Masked.push_back('N');
10463 break;
10464 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10465 Masked.push_back('M');
10466 break;
10467 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010468 for (char Mask : Masked) {
10469 for (const ISADataTy &Data : ISAData) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010470 SmallString<256> Buffer;
10471 llvm::raw_svector_ostream Out(Buffer);
10472 Out << "_ZGV" << Data.ISA << Mask;
10473 if (!VLENVal) {
Simon Pilgrim823a99c2019-05-22 13:02:19 +000010474 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs);
10475 assert(NumElts && "Non-zero simdlen/cdtsize expected");
10476 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010477 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010478 Out << VLENVal;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010479 }
10480 for (const ParamAttrTy &ParamAttr : ParamAttrs) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010481 switch (ParamAttr.Kind){
10482 case LinearWithVarStride:
10483 Out << 's' << ParamAttr.StrideOrArg;
10484 break;
10485 case Linear:
10486 Out << 'l';
10487 if (!!ParamAttr.StrideOrArg)
10488 Out << ParamAttr.StrideOrArg;
10489 break;
10490 case Uniform:
10491 Out << 'u';
10492 break;
10493 case Vector:
10494 Out << 'v';
10495 break;
10496 }
10497 if (!!ParamAttr.Alignment)
10498 Out << 'a' << ParamAttr.Alignment;
10499 }
10500 Out << '_' << Fn->getName();
10501 Fn->addFnAttr(Out.str());
10502 }
10503 }
10504}
10505
Alexey Bataeva0a22642019-04-16 13:56:21 +000010506// This are the Functions that are needed to mangle the name of the
10507// vector functions generated by the compiler, according to the rules
10508// defined in the "Vector Function ABI specifications for AArch64",
10509// available at
10510// https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi.
10511
10512/// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI.
10513///
10514/// TODO: Need to implement the behavior for reference marked with a
10515/// var or no linear modifiers (1.b in the section). For this, we
10516/// need to extend ParamKindTy to support the linear modifiers.
10517static bool getAArch64MTV(QualType QT, ParamKindTy Kind) {
10518 QT = QT.getCanonicalType();
10519
10520 if (QT->isVoidType())
10521 return false;
10522
10523 if (Kind == ParamKindTy::Uniform)
10524 return false;
10525
10526 if (Kind == ParamKindTy::Linear)
10527 return false;
10528
10529 // TODO: Handle linear references with modifiers
10530
10531 if (Kind == ParamKindTy::LinearWithVarStride)
10532 return false;
10533
10534 return true;
10535}
10536
10537/// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
10538static bool getAArch64PBV(QualType QT, ASTContext &C) {
10539 QT = QT.getCanonicalType();
10540 unsigned Size = C.getTypeSize(QT);
10541
10542 // Only scalars and complex within 16 bytes wide set PVB to true.
10543 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
10544 return false;
10545
10546 if (QT->isFloatingType())
10547 return true;
10548
10549 if (QT->isIntegerType())
10550 return true;
10551
10552 if (QT->isPointerType())
10553 return true;
10554
10555 // TODO: Add support for complex types (section 3.1.2, item 2).
10556
10557 return false;
10558}
10559
10560/// Computes the lane size (LS) of a return type or of an input parameter,
10561/// as defined by `LS(P)` in 3.2.1 of the AAVFABI.
10562/// TODO: Add support for references, section 3.2.1, item 1.
10563static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) {
10564 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) {
10565 QualType PTy = QT.getCanonicalType()->getPointeeType();
10566 if (getAArch64PBV(PTy, C))
10567 return C.getTypeSize(PTy);
10568 }
10569 if (getAArch64PBV(QT, C))
10570 return C.getTypeSize(QT);
10571
10572 return C.getTypeSize(C.getUIntPtrType());
10573}
10574
10575// Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the
10576// signature of the scalar function, as defined in 3.2.2 of the
10577// AAVFABI.
10578static std::tuple<unsigned, unsigned, bool>
10579getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) {
10580 QualType RetType = FD->getReturnType().getCanonicalType();
10581
10582 ASTContext &C = FD->getASTContext();
10583
10584 bool OutputBecomesInput = false;
10585
10586 llvm::SmallVector<unsigned, 8> Sizes;
10587 if (!RetType->isVoidType()) {
10588 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C));
10589 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {}))
10590 OutputBecomesInput = true;
10591 }
10592 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
10593 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType();
10594 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C));
10595 }
10596
10597 assert(!Sizes.empty() && "Unable to determine NDS and WDS.");
10598 // The LS of a function parameter / return value can only be a power
10599 // of 2, starting from 8 bits, up to 128.
10600 assert(std::all_of(Sizes.begin(), Sizes.end(),
10601 [](unsigned Size) {
10602 return Size == 8 || Size == 16 || Size == 32 ||
10603 Size == 64 || Size == 128;
10604 }) &&
10605 "Invalid size");
10606
10607 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)),
10608 *std::max_element(std::begin(Sizes), std::end(Sizes)),
10609 OutputBecomesInput);
10610}
10611
10612/// Mangle the parameter part of the vector function name according to
10613/// their OpenMP classification. The mangling function is defined in
10614/// section 3.5 of the AAVFABI.
10615static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) {
10616 SmallString<256> Buffer;
10617 llvm::raw_svector_ostream Out(Buffer);
10618 for (const auto &ParamAttr : ParamAttrs) {
10619 switch (ParamAttr.Kind) {
10620 case LinearWithVarStride:
10621 Out << "ls" << ParamAttr.StrideOrArg;
10622 break;
10623 case Linear:
10624 Out << 'l';
10625 // Don't print the step value if it is not present or if it is
10626 // equal to 1.
10627 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1)
10628 Out << ParamAttr.StrideOrArg;
10629 break;
10630 case Uniform:
10631 Out << 'u';
10632 break;
10633 case Vector:
10634 Out << 'v';
10635 break;
10636 }
10637
10638 if (!!ParamAttr.Alignment)
10639 Out << 'a' << ParamAttr.Alignment;
10640 }
10641
10642 return Out.str();
10643}
10644
10645// Function used to add the attribute. The parameter `VLEN` is
10646// templated to allow the use of "x" when targeting scalable functions
10647// for SVE.
10648template <typename T>
10649static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix,
10650 char ISA, StringRef ParSeq,
10651 StringRef MangledName, bool OutputBecomesInput,
10652 llvm::Function *Fn) {
10653 SmallString<256> Buffer;
10654 llvm::raw_svector_ostream Out(Buffer);
10655 Out << Prefix << ISA << LMask << VLEN;
10656 if (OutputBecomesInput)
10657 Out << "v";
10658 Out << ParSeq << "_" << MangledName;
10659 Fn->addFnAttr(Out.str());
10660}
10661
10662// Helper function to generate the Advanced SIMD names depending on
10663// the value of the NDS when simdlen is not present.
10664static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask,
10665 StringRef Prefix, char ISA,
10666 StringRef ParSeq, StringRef MangledName,
10667 bool OutputBecomesInput,
10668 llvm::Function *Fn) {
10669 switch (NDS) {
10670 case 8:
10671 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10672 OutputBecomesInput, Fn);
10673 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName,
10674 OutputBecomesInput, Fn);
10675 break;
10676 case 16:
10677 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10678 OutputBecomesInput, Fn);
10679 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
10680 OutputBecomesInput, Fn);
10681 break;
10682 case 32:
10683 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10684 OutputBecomesInput, Fn);
10685 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
10686 OutputBecomesInput, Fn);
10687 break;
10688 case 64:
10689 case 128:
10690 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
10691 OutputBecomesInput, Fn);
10692 break;
10693 default:
10694 llvm_unreachable("Scalar type is too wide.");
10695 }
10696}
10697
10698/// Emit vector function attributes for AArch64, as defined in the AAVFABI.
10699static void emitAArch64DeclareSimdFunction(
10700 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN,
10701 ArrayRef<ParamAttrTy> ParamAttrs,
10702 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
10703 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) {
10704
10705 // Get basic data for building the vector signature.
10706 const auto Data = getNDSWDS(FD, ParamAttrs);
10707 const unsigned NDS = std::get<0>(Data);
10708 const unsigned WDS = std::get<1>(Data);
10709 const bool OutputBecomesInput = std::get<2>(Data);
10710
10711 // Check the values provided via `simdlen` by the user.
10712 // 1. A `simdlen(1)` doesn't produce vector signatures,
10713 if (UserVLEN == 1) {
10714 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10715 DiagnosticsEngine::Warning,
10716 "The clause simdlen(1) has no effect when targeting aarch64.");
10717 CGM.getDiags().Report(SLoc, DiagID);
10718 return;
10719 }
10720
10721 // 2. Section 3.3.1, item 1: user input must be a power of 2 for
10722 // Advanced SIMD output.
10723 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
10724 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10725 DiagnosticsEngine::Warning, "The value specified in simdlen must be a "
10726 "power of 2 when targeting Advanced SIMD.");
10727 CGM.getDiags().Report(SLoc, DiagID);
10728 return;
10729 }
10730
10731 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural
10732 // limits.
10733 if (ISA == 's' && UserVLEN != 0) {
10734 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
10735 unsigned DiagID = CGM.getDiags().getCustomDiagID(
10736 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit "
10737 "lanes in the architectural constraints "
10738 "for SVE (min is 128-bit, max is "
10739 "2048-bit, by steps of 128-bit)");
10740 CGM.getDiags().Report(SLoc, DiagID) << WDS;
10741 return;
10742 }
10743 }
10744
10745 // Sort out parameter sequence.
10746 const std::string ParSeq = mangleVectorParameters(ParamAttrs);
10747 StringRef Prefix = "_ZGV";
10748 // Generate simdlen from user input (if any).
10749 if (UserVLEN) {
10750 if (ISA == 's') {
10751 // SVE generates only a masked function.
10752 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10753 OutputBecomesInput, Fn);
10754 } else {
10755 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10756 // Advanced SIMD generates one or two functions, depending on
10757 // the `[not]inbranch` clause.
10758 switch (State) {
10759 case OMPDeclareSimdDeclAttr::BS_Undefined:
10760 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10761 OutputBecomesInput, Fn);
10762 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10763 OutputBecomesInput, Fn);
10764 break;
10765 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10766 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
10767 OutputBecomesInput, Fn);
10768 break;
10769 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10770 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
10771 OutputBecomesInput, Fn);
10772 break;
10773 }
10774 }
10775 } else {
10776 // If no user simdlen is provided, follow the AAVFABI rules for
10777 // generating the vector length.
10778 if (ISA == 's') {
10779 // SVE, section 3.4.1, item 1.
10780 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName,
10781 OutputBecomesInput, Fn);
10782 } else {
10783 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10784 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or
10785 // two vector names depending on the use of the clause
10786 // `[not]inbranch`.
10787 switch (State) {
10788 case OMPDeclareSimdDeclAttr::BS_Undefined:
10789 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10790 OutputBecomesInput, Fn);
10791 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10792 OutputBecomesInput, Fn);
10793 break;
10794 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10795 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10796 OutputBecomesInput, Fn);
10797 break;
10798 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10799 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10800 OutputBecomesInput, Fn);
10801 break;
10802 }
10803 }
10804 }
10805}
10806
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010807void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
10808 llvm::Function *Fn) {
10809 ASTContext &C = CGM.getContext();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010810 FD = FD->getMostRecentDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010811 // Map params to their positions in function decl.
10812 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
10813 if (isa<CXXMethodDecl>(FD))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010814 ParamPositions.try_emplace(FD, 0);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010815 unsigned ParamPos = ParamPositions.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010816 for (const ParmVarDecl *P : FD->parameters()) {
10817 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010818 ++ParamPos;
10819 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010820 while (FD) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010821 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010822 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
10823 // Mark uniform parameters.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010824 for (const Expr *E : Attr->uniforms()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010825 E = E->IgnoreParenImpCasts();
10826 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010827 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010828 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010829 } else {
10830 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10831 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010832 Pos = ParamPositions[PVD];
10833 }
10834 ParamAttrs[Pos].Kind = Uniform;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010835 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010836 // Get alignment info.
10837 auto NI = Attr->alignments_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010838 for (const Expr *E : Attr->aligneds()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010839 E = E->IgnoreParenImpCasts();
10840 unsigned Pos;
10841 QualType ParmTy;
10842 if (isa<CXXThisExpr>(E)) {
10843 Pos = ParamPositions[FD];
10844 ParmTy = E->getType();
10845 } else {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010846 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10847 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010848 Pos = ParamPositions[PVD];
10849 ParmTy = PVD->getType();
10850 }
10851 ParamAttrs[Pos].Alignment =
10852 (*NI)
10853 ? (*NI)->EvaluateKnownConstInt(C)
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010854 : llvm::APSInt::getUnsigned(
10855 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy))
10856 .getQuantity());
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010857 ++NI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010858 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010859 // Mark linear parameters.
10860 auto SI = Attr->steps_begin();
10861 auto MI = Attr->modifiers_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010862 for (const Expr *E : Attr->linears()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010863 E = E->IgnoreParenImpCasts();
10864 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010865 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010866 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010867 } else {
10868 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10869 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010870 Pos = ParamPositions[PVD];
10871 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010872 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010873 ParamAttr.Kind = Linear;
10874 if (*SI) {
Fangrui Song407659a2018-11-30 23:41:18 +000010875 Expr::EvalResult Result;
10876 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010877 if (const auto *DRE =
10878 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
10879 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010880 ParamAttr.Kind = LinearWithVarStride;
10881 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(
10882 ParamPositions[StridePVD->getCanonicalDecl()]);
10883 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010884 }
Fangrui Song407659a2018-11-30 23:41:18 +000010885 } else {
10886 ParamAttr.StrideOrArg = Result.Val.getInt();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010887 }
10888 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010889 ++SI;
10890 ++MI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010891 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010892 llvm::APSInt VLENVal;
Alexey Bataeva0a22642019-04-16 13:56:21 +000010893 SourceLocation ExprLoc;
10894 const Expr *VLENExpr = Attr->getSimdlen();
10895 if (VLENExpr) {
10896 VLENVal = VLENExpr->EvaluateKnownConstInt(C);
10897 ExprLoc = VLENExpr->getExprLoc();
10898 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010899 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
10900 if (CGM.getTriple().getArch() == llvm::Triple::x86 ||
Alexey Bataeva0a22642019-04-16 13:56:21 +000010901 CGM.getTriple().getArch() == llvm::Triple::x86_64) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010902 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
Alexey Bataeva0a22642019-04-16 13:56:21 +000010903 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) {
10904 unsigned VLEN = VLENVal.getExtValue();
10905 StringRef MangledName = Fn->getName();
10906 if (CGM.getTarget().hasFeature("sve"))
10907 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10908 MangledName, 's', 128, Fn, ExprLoc);
10909 if (CGM.getTarget().hasFeature("neon"))
10910 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10911 MangledName, 'n', 128, Fn, ExprLoc);
10912 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010913 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010914 FD = FD->getPreviousDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010915 }
10916}
Alexey Bataev8b427062016-05-25 12:36:08 +000010917
10918namespace {
10919/// Cleanup action for doacross support.
10920class DoacrossCleanupTy final : public EHScopeStack::Cleanup {
10921public:
10922 static const int DoacrossFinArgs = 2;
10923
10924private:
James Y Knight9871db02019-02-05 16:42:33 +000010925 llvm::FunctionCallee RTLFn;
Alexey Bataev8b427062016-05-25 12:36:08 +000010926 llvm::Value *Args[DoacrossFinArgs];
10927
10928public:
James Y Knight9871db02019-02-05 16:42:33 +000010929 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
10930 ArrayRef<llvm::Value *> CallArgs)
Alexey Bataev8b427062016-05-25 12:36:08 +000010931 : RTLFn(RTLFn) {
10932 assert(CallArgs.size() == DoacrossFinArgs);
10933 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10934 }
10935 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10936 if (!CGF.HaveInsertPoint())
10937 return;
10938 CGF.EmitRuntimeCall(RTLFn, Args);
10939 }
10940};
10941} // namespace
10942
10943void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000010944 const OMPLoopDirective &D,
10945 ArrayRef<Expr *> NumIterations) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010946 if (!CGF.HaveInsertPoint())
10947 return;
10948
10949 ASTContext &C = CGM.getContext();
10950 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
10951 RecordDecl *RD;
10952 if (KmpDimTy.isNull()) {
10953 // Build struct kmp_dim { // loop bounds info casted to kmp_int64
10954 // kmp_int64 lo; // lower
10955 // kmp_int64 up; // upper
10956 // kmp_int64 st; // stride
10957 // };
10958 RD = C.buildImplicitRecord("kmp_dim");
10959 RD->startDefinition();
10960 addFieldToRecordDecl(C, RD, Int64Ty);
10961 addFieldToRecordDecl(C, RD, Int64Ty);
10962 addFieldToRecordDecl(C, RD, Int64Ty);
10963 RD->completeDefinition();
10964 KmpDimTy = C.getRecordType(RD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010965 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010966 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010967 }
Alexey Bataevf138fda2018-08-13 19:04:24 +000010968 llvm::APInt Size(/*numBits=*/32, NumIterations.size());
10969 QualType ArrayTy =
Richard Smith772e2662019-10-04 01:25:59 +000010970 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0);
Alexey Bataev8b427062016-05-25 12:36:08 +000010971
Alexey Bataevf138fda2018-08-13 19:04:24 +000010972 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
10973 CGF.EmitNullInitialization(DimsAddr, ArrayTy);
Alexey Bataev8b427062016-05-25 12:36:08 +000010974 enum { LowerFD = 0, UpperFD, StrideFD };
10975 // Fill dims with data.
Alexey Bataevf138fda2018-08-13 19:04:24 +000010976 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +000010977 LValue DimsLVal = CGF.MakeAddrLValue(
10978 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010979 // dims.upper = num_iterations;
10980 LValue UpperLVal = CGF.EmitLValueForField(
10981 DimsLVal, *std::next(RD->field_begin(), UpperFD));
10982 llvm::Value *NumIterVal =
10983 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]),
10984 D.getNumIterations()->getType(), Int64Ty,
10985 D.getNumIterations()->getExprLoc());
10986 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
10987 // dims.stride = 1;
10988 LValue StrideLVal = CGF.EmitLValueForField(
10989 DimsLVal, *std::next(RD->field_begin(), StrideFD));
10990 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
10991 StrideLVal);
10992 }
Alexey Bataev8b427062016-05-25 12:36:08 +000010993
10994 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
10995 // kmp_int32 num_dims, struct kmp_dim * dims);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010996 llvm::Value *Args[] = {
10997 emitUpdateLocation(CGF, D.getBeginLoc()),
10998 getThreadID(CGF, D.getBeginLoc()),
10999 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()),
11000 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knight751fe282019-02-09 22:22:28 +000011001 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(),
Alexey Bataevf138fda2018-08-13 19:04:24 +000011002 CGM.VoidPtrTy)};
Alexey Bataev8b427062016-05-25 12:36:08 +000011003
James Y Knight9871db02019-02-05 16:42:33 +000011004 llvm::FunctionCallee RTLFn =
11005 createRuntimeFunction(OMPRTL__kmpc_doacross_init);
Alexey Bataev8b427062016-05-25 12:36:08 +000011006 CGF.EmitRuntimeCall(RTLFn, Args);
11007 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
Stephen Kelly1c301dc2018-08-09 21:09:38 +000011008 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())};
James Y Knight9871db02019-02-05 16:42:33 +000011009 llvm::FunctionCallee FiniRTLFn =
11010 createRuntimeFunction(OMPRTL__kmpc_doacross_fini);
Alexey Bataev8b427062016-05-25 12:36:08 +000011011 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
11012 llvm::makeArrayRef(FiniArgs));
11013}
11014
11015void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
11016 const OMPDependClause *C) {
11017 QualType Int64Ty =
11018 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Alexey Bataevf138fda2018-08-13 19:04:24 +000011019 llvm::APInt Size(/*numBits=*/32, C->getNumLoops());
11020 QualType ArrayTy = CGM.getContext().getConstantArrayType(
Richard Smith772e2662019-10-04 01:25:59 +000011021 Int64Ty, Size, nullptr, ArrayType::Normal, 0);
Alexey Bataevf138fda2018-08-13 19:04:24 +000011022 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr");
11023 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) {
11024 const Expr *CounterVal = C->getLoopData(I);
11025 assert(CounterVal);
11026 llvm::Value *CntVal = CGF.EmitScalarConversion(
11027 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
11028 CounterVal->getExprLoc());
James Y Knight751fe282019-02-09 22:22:28 +000011029 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I),
11030 /*Volatile=*/false, Int64Ty);
Alexey Bataevf138fda2018-08-13 19:04:24 +000011031 }
11032 llvm::Value *Args[] = {
11033 emitUpdateLocation(CGF, C->getBeginLoc()),
11034 getThreadID(CGF, C->getBeginLoc()),
James Y Knight751fe282019-02-09 22:22:28 +000011035 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()};
James Y Knight9871db02019-02-05 16:42:33 +000011036 llvm::FunctionCallee RTLFn;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000011037 if (C->getDependencyKind() == OMPC_DEPEND_source) {
Alexey Bataev8b427062016-05-25 12:36:08 +000011038 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000011039 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000011040 assert(C->getDependencyKind() == OMPC_DEPEND_sink);
11041 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait);
11042 }
11043 CGF.EmitRuntimeCall(RTLFn, Args);
11044}
11045
Alexey Bataev7ef47a62018-02-22 18:33:31 +000011046void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000011047 llvm::FunctionCallee Callee,
Alexey Bataev7ef47a62018-02-22 18:33:31 +000011048 ArrayRef<llvm::Value *> Args) const {
11049 assert(Loc.isValid() && "Outlined function call location must be valid.");
Alexey Bataev3c595a62017-08-14 15:01:03 +000011050 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
11051
James Y Knight9871db02019-02-05 16:42:33 +000011052 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
Alexey Bataev2c7eee52017-08-04 19:10:54 +000011053 if (Fn->doesNotThrow()) {
Alexey Bataev3c595a62017-08-14 15:01:03 +000011054 CGF.EmitNounwindRuntimeCall(Fn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000011055 return;
11056 }
11057 }
Alexey Bataev3c595a62017-08-14 15:01:03 +000011058 CGF.EmitRuntimeCall(Callee, Args);
11059}
11060
11061void CGOpenMPRuntime::emitOutlinedFunctionCall(
James Y Knight9871db02019-02-05 16:42:33 +000011062 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn,
Alexey Bataev3c595a62017-08-14 15:01:03 +000011063 ArrayRef<llvm::Value *> Args) const {
Alexey Bataev7ef47a62018-02-22 18:33:31 +000011064 emitCall(CGF, Loc, OutlinedFn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000011065}
Alexey Bataev3b8d5582017-08-08 18:04:06 +000011066
Gheorghe-Teodor Bercea66cdbb472019-05-21 19:42:01 +000011067void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) {
11068 if (const auto *FD = dyn_cast<FunctionDecl>(D))
11069 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD))
11070 HasEmittedDeclareTargetRegion = true;
11071}
11072
Alexey Bataev3b8d5582017-08-08 18:04:06 +000011073Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
11074 const VarDecl *NativeParam,
11075 const VarDecl *TargetParam) const {
11076 return CGF.GetAddrOfLocalVar(NativeParam);
11077}
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011078
Alexey Bataev4f680db2019-03-19 16:41:16 +000011079namespace {
11080/// Cleanup action for allocate support.
11081class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup {
11082public:
11083 static const int CleanupArgs = 3;
11084
11085private:
11086 llvm::FunctionCallee RTLFn;
11087 llvm::Value *Args[CleanupArgs];
11088
11089public:
11090 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
11091 ArrayRef<llvm::Value *> CallArgs)
11092 : RTLFn(RTLFn) {
11093 assert(CallArgs.size() == CleanupArgs &&
11094 "Size of arguments does not match.");
11095 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
11096 }
11097 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
11098 if (!CGF.HaveInsertPoint())
11099 return;
11100 CGF.EmitRuntimeCall(RTLFn, Args);
11101 }
11102};
11103} // namespace
11104
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000011105Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF,
11106 const VarDecl *VD) {
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011107 if (!VD)
11108 return Address::invalid();
Alexey Bataev4f680db2019-03-19 16:41:16 +000011109 const VarDecl *CVD = VD->getCanonicalDecl();
11110 if (!CVD->hasAttr<OMPAllocateDeclAttr>())
11111 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011112 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
11113 // Use the default allocation.
Alexey Bataev0fd3c682019-04-02 19:44:46 +000011114 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
11115 !AA->getAllocator())
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011116 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011117 llvm::Value *Size;
11118 CharUnits Align = CGM.getContext().getDeclAlign(CVD);
11119 if (CVD->getType()->isVariablyModifiedType()) {
11120 Size = CGF.getTypeSize(CVD->getType());
Alexey Bataev9c397812019-04-03 17:57:06 +000011121 // Align the size: ((size + align - 1) / align) * align
11122 Size = CGF.Builder.CreateNUWAdd(
11123 Size, CGM.getSize(Align - CharUnits::fromQuantity(1)));
11124 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align));
11125 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align));
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011126 } else {
11127 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType());
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011128 Size = CGM.getSize(Sz.alignTo(Align));
Alexey Bataev4f680db2019-03-19 16:41:16 +000011129 }
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011130 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc());
11131 assert(AA->getAllocator() &&
11132 "Expected allocator expression for non-default allocator.");
11133 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator());
Alexey Bataev6cf7b712019-04-08 19:06:42 +000011134 // According to the standard, the original allocator type is a enum (integer).
11135 // Convert to pointer type, if required.
11136 if (Allocator->getType()->isIntegerTy())
11137 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy);
11138 else if (Allocator->getType()->isPointerTy())
11139 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator,
11140 CGM.VoidPtrTy);
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000011141 llvm::Value *Args[] = {ThreadID, Size, Allocator};
11142
11143 llvm::Value *Addr =
11144 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args,
11145 CVD->getName() + ".void.addr");
11146 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr,
11147 Allocator};
11148 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free);
11149
11150 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
11151 llvm::makeArrayRef(FiniArgs));
11152 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
11153 Addr,
11154 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())),
11155 CVD->getName() + ".addr");
11156 return Address(Addr, Align);
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000011157}
11158
Alexey Bataev2df5f122019-10-01 20:18:32 +000011159/// Checks current context and returns true if it matches the context selector.
11160template <OMPDeclareVariantAttr::CtxSelectorSetType CtxSet,
11161 OMPDeclareVariantAttr::CtxSelectorType Ctx>
11162static bool checkContext(const OMPDeclareVariantAttr *A) {
11163 assert(CtxSet != OMPDeclareVariantAttr::CtxSetUnknown &&
11164 Ctx != OMPDeclareVariantAttr::CtxUnknown &&
11165 "Unknown context selector or context selector set.");
11166 return false;
11167}
11168
11169/// Checks for implementation={vendor(<vendor>)} context selector.
11170/// \returns true iff <vendor>="llvm", false otherwise.
11171template <>
11172bool checkContext<OMPDeclareVariantAttr::CtxSetImplementation,
11173 OMPDeclareVariantAttr::CtxVendor>(
11174 const OMPDeclareVariantAttr *A) {
11175 return !A->getImplVendor().compare("llvm");
11176}
11177
Alexey Bataev0364c762019-10-03 20:49:48 +000011178static bool greaterCtxScore(ASTContext &Ctx, const Expr *LHS, const Expr *RHS) {
11179 // If both scores are unknown, choose the very first one.
11180 if (!LHS && !RHS)
11181 return true;
11182 // If only one is known, return this one.
11183 if (LHS && !RHS)
11184 return true;
11185 if (!LHS && RHS)
11186 return false;
11187 llvm::APSInt LHSVal = LHS->EvaluateKnownConstInt(Ctx);
11188 llvm::APSInt RHSVal = RHS->EvaluateKnownConstInt(Ctx);
11189 return llvm::APSInt::compareValues(LHSVal, RHSVal) <= 0;
11190}
11191
11192namespace {
11193/// Comparator for the priority queue for context selector.
11194class OMPDeclareVariantAttrComparer
11195 : public std::greater<const OMPDeclareVariantAttr *> {
11196private:
11197 ASTContext &Ctx;
11198
11199public:
11200 OMPDeclareVariantAttrComparer(ASTContext &Ctx) : Ctx(Ctx) {}
11201 bool operator()(const OMPDeclareVariantAttr *LHS,
11202 const OMPDeclareVariantAttr *RHS) const {
11203 const Expr *LHSExpr = nullptr;
11204 const Expr *RHSExpr = nullptr;
11205 if (LHS->getCtxScore() == OMPDeclareVariantAttr::ScoreSpecified)
11206 LHSExpr = LHS->getScore();
11207 if (RHS->getCtxScore() == OMPDeclareVariantAttr::ScoreSpecified)
11208 RHSExpr = RHS->getScore();
11209 return greaterCtxScore(Ctx, LHSExpr, RHSExpr);
11210 }
11211};
11212} // anonymous namespace
11213
Alexey Bataev2df5f122019-10-01 20:18:32 +000011214/// Finds the variant function that matches current context with its context
11215/// selector.
Alexey Bataev0364c762019-10-03 20:49:48 +000011216static const FunctionDecl *getDeclareVariantFunction(ASTContext &Ctx,
11217 const FunctionDecl *FD) {
Alexey Bataev2df5f122019-10-01 20:18:32 +000011218 if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>())
11219 return FD;
11220 // Iterate through all DeclareVariant attributes and check context selectors.
Alexey Bataev0364c762019-10-03 20:49:48 +000011221 auto &&Comparer = [&Ctx](const OMPDeclareVariantAttr *LHS,
11222 const OMPDeclareVariantAttr *RHS) {
11223 const Expr *LHSExpr = nullptr;
11224 const Expr *RHSExpr = nullptr;
11225 if (LHS->getCtxScore() == OMPDeclareVariantAttr::ScoreSpecified)
11226 LHSExpr = LHS->getScore();
11227 if (RHS->getCtxScore() == OMPDeclareVariantAttr::ScoreSpecified)
11228 RHSExpr = RHS->getScore();
11229 return greaterCtxScore(Ctx, LHSExpr, RHSExpr);
11230 };
11231 const OMPDeclareVariantAttr *TopMostAttr = nullptr;
11232 for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) {
11233 const OMPDeclareVariantAttr *SelectedAttr = nullptr;
Alexey Bataev2df5f122019-10-01 20:18:32 +000011234 switch (A->getCtxSelectorSet()) {
11235 case OMPDeclareVariantAttr::CtxSetImplementation:
11236 switch (A->getCtxSelector()) {
11237 case OMPDeclareVariantAttr::CtxVendor:
11238 if (checkContext<OMPDeclareVariantAttr::CtxSetImplementation,
11239 OMPDeclareVariantAttr::CtxVendor>(A))
Alexey Bataev0364c762019-10-03 20:49:48 +000011240 SelectedAttr = A;
Alexey Bataev2df5f122019-10-01 20:18:32 +000011241 break;
11242 case OMPDeclareVariantAttr::CtxUnknown:
11243 llvm_unreachable(
Alexey Bataev0364c762019-10-03 20:49:48 +000011244 "Unknown context selector in implementation selector set.");
Alexey Bataev2df5f122019-10-01 20:18:32 +000011245 }
11246 break;
11247 case OMPDeclareVariantAttr::CtxSetUnknown:
11248 llvm_unreachable("Unknown context selector set.");
11249 }
Alexey Bataev0364c762019-10-03 20:49:48 +000011250 // If the attribute matches the context, find the attribute with the highest
11251 // score.
11252 if (SelectedAttr && (!TopMostAttr || Comparer(TopMostAttr, SelectedAttr)))
11253 TopMostAttr = SelectedAttr;
Alexey Bataev2df5f122019-10-01 20:18:32 +000011254 }
Alexey Bataev0364c762019-10-03 20:49:48 +000011255 if (!TopMostAttr)
Alexey Bataev2df5f122019-10-01 20:18:32 +000011256 return FD;
Alexey Bataev2df5f122019-10-01 20:18:32 +000011257 return cast<FunctionDecl>(
Alexey Bataev0364c762019-10-03 20:49:48 +000011258 cast<DeclRefExpr>(TopMostAttr->getVariantFuncRef()->IgnoreParenImpCasts())
Alexey Bataev2df5f122019-10-01 20:18:32 +000011259 ->getDecl());
11260}
11261
11262bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) {
11263 const auto *D = cast<FunctionDecl>(GD.getDecl());
11264 // If the original function is defined already, use its definition.
11265 StringRef MangledName = CGM.getMangledName(GD);
11266 llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName);
11267 if (Orig && !Orig->isDeclaration())
11268 return false;
Alexey Bataev0364c762019-10-03 20:49:48 +000011269 const FunctionDecl *NewFD = getDeclareVariantFunction(CGM.getContext(), D);
Alexey Bataev2df5f122019-10-01 20:18:32 +000011270 // Emit original function if it does not have declare variant attribute or the
11271 // context does not match.
11272 if (NewFD == D)
11273 return false;
11274 GlobalDecl NewGD = GD.getWithDecl(NewFD);
11275 if (tryEmitAlias(CGM, NewGD, GD, Orig, IsForDefinition)) {
11276 DeferredVariantFunction.erase(D);
11277 return true;
11278 }
11279 DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD)));
11280 return true;
11281}
11282
James Y Knight9871db02019-02-05 16:42:33 +000011283llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011284 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11285 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11286 llvm_unreachable("Not supported in SIMD-only mode");
11287}
11288
James Y Knight9871db02019-02-05 16:42:33 +000011289llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011290 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11291 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
11292 llvm_unreachable("Not supported in SIMD-only mode");
11293}
11294
James Y Knight9871db02019-02-05 16:42:33 +000011295llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011296 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
11297 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
11298 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
11299 bool Tied, unsigned &NumberOfParts) {
11300 llvm_unreachable("Not supported in SIMD-only mode");
11301}
11302
11303void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF,
11304 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000011305 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011306 ArrayRef<llvm::Value *> CapturedVars,
11307 const Expr *IfCond) {
11308 llvm_unreachable("Not supported in SIMD-only mode");
11309}
11310
11311void CGOpenMPSIMDRuntime::emitCriticalRegion(
11312 CodeGenFunction &CGF, StringRef CriticalName,
11313 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
11314 const Expr *Hint) {
11315 llvm_unreachable("Not supported in SIMD-only mode");
11316}
11317
11318void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF,
11319 const RegionCodeGenTy &MasterOpGen,
11320 SourceLocation Loc) {
11321 llvm_unreachable("Not supported in SIMD-only mode");
11322}
11323
11324void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
11325 SourceLocation Loc) {
11326 llvm_unreachable("Not supported in SIMD-only mode");
11327}
11328
11329void CGOpenMPSIMDRuntime::emitTaskgroupRegion(
11330 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen,
11331 SourceLocation Loc) {
11332 llvm_unreachable("Not supported in SIMD-only mode");
11333}
11334
11335void CGOpenMPSIMDRuntime::emitSingleRegion(
11336 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen,
11337 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars,
11338 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs,
11339 ArrayRef<const Expr *> AssignmentOps) {
11340 llvm_unreachable("Not supported in SIMD-only mode");
11341}
11342
11343void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF,
11344 const RegionCodeGenTy &OrderedOpGen,
11345 SourceLocation Loc,
11346 bool IsThreads) {
11347 llvm_unreachable("Not supported in SIMD-only mode");
11348}
11349
11350void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF,
11351 SourceLocation Loc,
11352 OpenMPDirectiveKind Kind,
11353 bool EmitChecks,
11354 bool ForceSimpleCall) {
11355 llvm_unreachable("Not supported in SIMD-only mode");
11356}
11357
11358void CGOpenMPSIMDRuntime::emitForDispatchInit(
11359 CodeGenFunction &CGF, SourceLocation Loc,
11360 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
11361 bool Ordered, const DispatchRTInput &DispatchValues) {
11362 llvm_unreachable("Not supported in SIMD-only mode");
11363}
11364
11365void CGOpenMPSIMDRuntime::emitForStaticInit(
11366 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind,
11367 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) {
11368 llvm_unreachable("Not supported in SIMD-only mode");
11369}
11370
11371void CGOpenMPSIMDRuntime::emitDistributeStaticInit(
11372 CodeGenFunction &CGF, SourceLocation Loc,
11373 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) {
11374 llvm_unreachable("Not supported in SIMD-only mode");
11375}
11376
11377void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
11378 SourceLocation Loc,
11379 unsigned IVSize,
11380 bool IVSigned) {
11381 llvm_unreachable("Not supported in SIMD-only mode");
11382}
11383
11384void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF,
11385 SourceLocation Loc,
11386 OpenMPDirectiveKind DKind) {
11387 llvm_unreachable("Not supported in SIMD-only mode");
11388}
11389
11390llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF,
11391 SourceLocation Loc,
11392 unsigned IVSize, bool IVSigned,
11393 Address IL, Address LB,
11394 Address UB, Address ST) {
11395 llvm_unreachable("Not supported in SIMD-only mode");
11396}
11397
11398void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
11399 llvm::Value *NumThreads,
11400 SourceLocation Loc) {
11401 llvm_unreachable("Not supported in SIMD-only mode");
11402}
11403
11404void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF,
11405 OpenMPProcBindClauseKind ProcBind,
11406 SourceLocation Loc) {
11407 llvm_unreachable("Not supported in SIMD-only mode");
11408}
11409
11410Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
11411 const VarDecl *VD,
11412 Address VDAddr,
11413 SourceLocation Loc) {
11414 llvm_unreachable("Not supported in SIMD-only mode");
11415}
11416
11417llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition(
11418 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit,
11419 CodeGenFunction *CGF) {
11420 llvm_unreachable("Not supported in SIMD-only mode");
11421}
11422
11423Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate(
11424 CodeGenFunction &CGF, QualType VarType, StringRef Name) {
11425 llvm_unreachable("Not supported in SIMD-only mode");
11426}
11427
11428void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF,
11429 ArrayRef<const Expr *> Vars,
11430 SourceLocation Loc) {
11431 llvm_unreachable("Not supported in SIMD-only mode");
11432}
11433
11434void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
11435 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000011436 llvm::Function *TaskFunction,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011437 QualType SharedsTy, Address Shareds,
11438 const Expr *IfCond,
11439 const OMPTaskDataTy &Data) {
11440 llvm_unreachable("Not supported in SIMD-only mode");
11441}
11442
11443void CGOpenMPSIMDRuntime::emitTaskLoopCall(
11444 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000011445 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011446 const Expr *IfCond, const OMPTaskDataTy &Data) {
11447 llvm_unreachable("Not supported in SIMD-only mode");
11448}
11449
11450void CGOpenMPSIMDRuntime::emitReduction(
11451 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates,
11452 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
11453 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) {
11454 assert(Options.SimpleReduction && "Only simple reduction is expected.");
11455 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
11456 ReductionOps, Options);
11457}
11458
11459llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit(
11460 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
11461 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
11462 llvm_unreachable("Not supported in SIMD-only mode");
11463}
11464
11465void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
11466 SourceLocation Loc,
11467 ReductionCodeGen &RCG,
11468 unsigned N) {
11469 llvm_unreachable("Not supported in SIMD-only mode");
11470}
11471
11472Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
11473 SourceLocation Loc,
11474 llvm::Value *ReductionsPtr,
11475 LValue SharedLVal) {
11476 llvm_unreachable("Not supported in SIMD-only mode");
11477}
11478
11479void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
11480 SourceLocation Loc) {
11481 llvm_unreachable("Not supported in SIMD-only mode");
11482}
11483
11484void CGOpenMPSIMDRuntime::emitCancellationPointCall(
11485 CodeGenFunction &CGF, SourceLocation Loc,
11486 OpenMPDirectiveKind CancelRegion) {
11487 llvm_unreachable("Not supported in SIMD-only mode");
11488}
11489
11490void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF,
11491 SourceLocation Loc, const Expr *IfCond,
11492 OpenMPDirectiveKind CancelRegion) {
11493 llvm_unreachable("Not supported in SIMD-only mode");
11494}
11495
11496void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction(
11497 const OMPExecutableDirective &D, StringRef ParentName,
11498 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
11499 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
11500 llvm_unreachable("Not supported in SIMD-only mode");
11501}
11502
Alexey Bataevec7946e2019-09-23 14:06:51 +000011503void CGOpenMPSIMDRuntime::emitTargetCall(
11504 CodeGenFunction &CGF, const OMPExecutableDirective &D,
11505 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond,
11506 const Expr *Device,
11507 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF,
11508 const OMPLoopDirective &D)>
11509 SizeEmitter) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011510 llvm_unreachable("Not supported in SIMD-only mode");
11511}
11512
11513bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) {
11514 llvm_unreachable("Not supported in SIMD-only mode");
11515}
11516
11517bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
11518 llvm_unreachable("Not supported in SIMD-only mode");
11519}
11520
11521bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) {
11522 return false;
11523}
11524
11525llvm::Function *CGOpenMPSIMDRuntime::emitRegistrationFunction() {
11526 return nullptr;
11527}
11528
11529void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF,
11530 const OMPExecutableDirective &D,
11531 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000011532 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011533 ArrayRef<llvm::Value *> CapturedVars) {
11534 llvm_unreachable("Not supported in SIMD-only mode");
11535}
11536
11537void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
11538 const Expr *NumTeams,
11539 const Expr *ThreadLimit,
11540 SourceLocation Loc) {
11541 llvm_unreachable("Not supported in SIMD-only mode");
11542}
11543
11544void CGOpenMPSIMDRuntime::emitTargetDataCalls(
11545 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
11546 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
11547 llvm_unreachable("Not supported in SIMD-only mode");
11548}
11549
11550void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
11551 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
11552 const Expr *Device) {
11553 llvm_unreachable("Not supported in SIMD-only mode");
11554}
11555
11556void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000011557 const OMPLoopDirective &D,
11558 ArrayRef<Expr *> NumIterations) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000011559 llvm_unreachable("Not supported in SIMD-only mode");
11560}
11561
11562void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
11563 const OMPDependClause *C) {
11564 llvm_unreachable("Not supported in SIMD-only mode");
11565}
11566
11567const VarDecl *
11568CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD,
11569 const VarDecl *NativeParam) const {
11570 llvm_unreachable("Not supported in SIMD-only mode");
11571}
11572
11573Address
11574CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF,
11575 const VarDecl *NativeParam,
11576 const VarDecl *TargetParam) const {
11577 llvm_unreachable("Not supported in SIMD-only mode");
11578}