blob: c3f60d7f60effa820c0e226894abffc883be1dde [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
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000460/// Describes ident structure that describes a source location.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000461/// All descriptions are taken from
James Y Knight5d71fc52019-01-29 16:37:27 +0000462/// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h
Alexey Bataev50b3c952016-02-19 10:38:26 +0000463/// Original structure:
464/// typedef struct ident {
465/// kmp_int32 reserved_1; /**< might be used in Fortran;
466/// see above */
467/// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags;
468/// KMP_IDENT_KMPC identifies this union
469/// member */
470/// kmp_int32 reserved_2; /**< not really used in Fortran any more;
471/// see above */
472///#if USE_ITT_BUILD
473/// /* but currently used for storing
474/// region-specific ITT */
475/// /* contextual information. */
476///#endif /* USE_ITT_BUILD */
477/// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for
478/// C++ */
479/// char const *psource; /**< String describing the source location.
480/// The string is composed of semi-colon separated
481// fields which describe the source file,
482/// the function and a pair of line numbers that
483/// delimit the construct.
484/// */
485/// } ident_t;
486enum IdentFieldIndex {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000487 /// might be used in Fortran
Alexey Bataev50b3c952016-02-19 10:38:26 +0000488 IdentField_Reserved_1,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000489 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000490 IdentField_Flags,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000491 /// Not really used in Fortran any more
Alexey Bataev50b3c952016-02-19 10:38:26 +0000492 IdentField_Reserved_2,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000493 /// Source[4] in Fortran, do not use for C++
Alexey Bataev50b3c952016-02-19 10:38:26 +0000494 IdentField_Reserved_3,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000495 /// String describing the source location. The string is composed of
Alexey Bataev50b3c952016-02-19 10:38:26 +0000496 /// semi-colon separated fields which describe the source file, the function
497 /// and a pair of line numbers that delimit the construct.
498 IdentField_PSource
499};
500
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000501/// Schedule types for 'omp for' loops (these enumerators are taken from
Alexey Bataev50b3c952016-02-19 10:38:26 +0000502/// the enum sched_type in kmp.h).
503enum OpenMPSchedType {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000504 /// Lower bound for default (unordered) versions.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000505 OMP_sch_lower = 32,
506 OMP_sch_static_chunked = 33,
507 OMP_sch_static = 34,
508 OMP_sch_dynamic_chunked = 35,
509 OMP_sch_guided_chunked = 36,
510 OMP_sch_runtime = 37,
511 OMP_sch_auto = 38,
Alexey Bataev6cff6242016-05-30 13:05:14 +0000512 /// static with chunk adjustment (e.g., simd)
Samuel Antao4c8035b2016-12-12 18:00:20 +0000513 OMP_sch_static_balanced_chunked = 45,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000514 /// Lower bound for 'ordered' versions.
Alexey Bataev50b3c952016-02-19 10:38:26 +0000515 OMP_ord_lower = 64,
516 OMP_ord_static_chunked = 65,
517 OMP_ord_static = 66,
518 OMP_ord_dynamic_chunked = 67,
519 OMP_ord_guided_chunked = 68,
520 OMP_ord_runtime = 69,
521 OMP_ord_auto = 70,
522 OMP_sch_default = OMP_sch_static,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000523 /// dist_schedule types
Carlo Bertollifc35ad22016-03-07 16:04:49 +0000524 OMP_dist_sch_static_chunked = 91,
525 OMP_dist_sch_static = 92,
Alexey Bataev9ebd7422016-05-10 09:57:36 +0000526 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers.
527 /// Set if the monotonic schedule modifier was present.
528 OMP_sch_modifier_monotonic = (1 << 29),
529 /// Set if the nonmonotonic schedule modifier was present.
530 OMP_sch_modifier_nonmonotonic = (1 << 30),
Alexey Bataev50b3c952016-02-19 10:38:26 +0000531};
532
533enum OpenMPRTLFunction {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000534 /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000535 /// kmpc_micro microtask, ...);
536 OMPRTL__kmpc_fork_call,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000537 /// Call to void *__kmpc_threadprivate_cached(ident_t *loc,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000538 /// kmp_int32 global_tid, void *data, size_t size, void ***cache);
539 OMPRTL__kmpc_threadprivate_cached,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000540 /// Call to void __kmpc_threadprivate_register( ident_t *,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000541 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
542 OMPRTL__kmpc_threadprivate_register,
543 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc);
544 OMPRTL__kmpc_global_thread_num,
545 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
546 // kmp_critical_name *crit);
547 OMPRTL__kmpc_critical,
548 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32
549 // global_tid, kmp_critical_name *crit, uintptr_t hint);
550 OMPRTL__kmpc_critical_with_hint,
551 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
552 // kmp_critical_name *crit);
553 OMPRTL__kmpc_end_critical,
554 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
555 // global_tid);
556 OMPRTL__kmpc_cancel_barrier,
557 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
558 OMPRTL__kmpc_barrier,
559 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
560 OMPRTL__kmpc_for_static_fini,
561 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
562 // global_tid);
563 OMPRTL__kmpc_serialized_parallel,
564 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
565 // global_tid);
566 OMPRTL__kmpc_end_serialized_parallel,
567 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
568 // kmp_int32 num_threads);
569 OMPRTL__kmpc_push_num_threads,
570 // Call to void __kmpc_flush(ident_t *loc);
571 OMPRTL__kmpc_flush,
572 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid);
573 OMPRTL__kmpc_master,
574 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid);
575 OMPRTL__kmpc_end_master,
576 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
577 // int end_part);
578 OMPRTL__kmpc_omp_taskyield,
579 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid);
580 OMPRTL__kmpc_single,
581 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid);
582 OMPRTL__kmpc_end_single,
583 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
584 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
585 // kmp_routine_entry_t *task_entry);
586 OMPRTL__kmpc_omp_task_alloc,
587 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t *
588 // new_task);
589 OMPRTL__kmpc_omp_task,
590 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
591 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
592 // kmp_int32 didit);
593 OMPRTL__kmpc_copyprivate,
594 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
595 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
596 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
597 OMPRTL__kmpc_reduce,
598 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
599 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
600 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
601 // *lck);
602 OMPRTL__kmpc_reduce_nowait,
603 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
604 // kmp_critical_name *lck);
605 OMPRTL__kmpc_end_reduce,
606 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
607 // kmp_critical_name *lck);
608 OMPRTL__kmpc_end_reduce_nowait,
609 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
610 // kmp_task_t * new_task);
611 OMPRTL__kmpc_omp_task_begin_if0,
612 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
613 // kmp_task_t * new_task);
614 OMPRTL__kmpc_omp_task_complete_if0,
615 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
616 OMPRTL__kmpc_ordered,
617 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
618 OMPRTL__kmpc_end_ordered,
619 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
620 // global_tid);
621 OMPRTL__kmpc_omp_taskwait,
622 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
623 OMPRTL__kmpc_taskgroup,
624 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
625 OMPRTL__kmpc_end_taskgroup,
626 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
627 // int proc_bind);
628 OMPRTL__kmpc_push_proc_bind,
629 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32
630 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t
631 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
632 OMPRTL__kmpc_omp_task_with_deps,
633 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32
634 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
635 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
636 OMPRTL__kmpc_omp_wait_deps,
637 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
638 // global_tid, kmp_int32 cncl_kind);
639 OMPRTL__kmpc_cancellationpoint,
640 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
641 // kmp_int32 cncl_kind);
642 OMPRTL__kmpc_cancel,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000643 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid,
644 // kmp_int32 num_teams, kmp_int32 thread_limit);
645 OMPRTL__kmpc_push_num_teams,
Alexey Bataev7292c292016-04-25 12:22:29 +0000646 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
647 // microtask, ...);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +0000648 OMPRTL__kmpc_fork_teams,
Alexey Bataev7292c292016-04-25 12:22:29 +0000649 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
650 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
651 // sched, kmp_uint64 grainsize, void *task_dup);
652 OMPRTL__kmpc_taskloop,
Alexey Bataev8b427062016-05-25 12:36:08 +0000653 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32
654 // num_dims, struct kmp_dim *dims);
655 OMPRTL__kmpc_doacross_init,
656 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid);
657 OMPRTL__kmpc_doacross_fini,
658 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64
659 // *vec);
660 OMPRTL__kmpc_doacross_post,
661 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64
662 // *vec);
663 OMPRTL__kmpc_doacross_wait,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000664 // Call to void *__kmpc_task_reduction_init(int gtid, int num_data, void
665 // *data);
666 OMPRTL__kmpc_task_reduction_init,
667 // Call to void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
668 // *d);
669 OMPRTL__kmpc_task_reduction_get_th_data,
Alexey Bataev6cf7b712019-04-08 19:06:42 +0000670 // Call to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al);
Alexey Bataev4f680db2019-03-19 16:41:16 +0000671 OMPRTL__kmpc_alloc,
Alexey Bataev6cf7b712019-04-08 19:06:42 +0000672 // Call to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al);
Alexey Bataev4f680db2019-03-19 16:41:16 +0000673 OMPRTL__kmpc_free,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000674
675 //
676 // Offloading related calls
677 //
Alexey Bataev7bb33532019-01-07 21:30:43 +0000678 // Call to void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64
679 // size);
680 OMPRTL__kmpc_push_target_tripcount,
George Rokos63bc9d62017-11-21 18:25:12 +0000681 // Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t
682 // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
Alexey Bataev50b3c952016-02-19 10:38:26 +0000683 // *arg_types);
684 OMPRTL__tgt_target,
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000685 // Call to int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr,
686 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
687 // *arg_types);
688 OMPRTL__tgt_target_nowait,
George Rokos63bc9d62017-11-21 18:25:12 +0000689 // Call to int32_t __tgt_target_teams(int64_t device_id, void *host_ptr,
690 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
691 // *arg_types, int32_t num_teams, int32_t thread_limit);
Samuel Antaob68e2db2016-03-03 16:20:23 +0000692 OMPRTL__tgt_target_teams,
Alexey Bataeva9f77c62017-12-13 21:04:20 +0000693 // Call to int32_t __tgt_target_teams_nowait(int64_t device_id, void
694 // *host_ptr, int32_t arg_num, void** args_base, void **args, size_t
695 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
696 OMPRTL__tgt_target_teams_nowait,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000697 // Call to void __tgt_register_lib(__tgt_bin_desc *desc);
698 OMPRTL__tgt_register_lib,
699 // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc);
700 OMPRTL__tgt_unregister_lib,
George Rokos63bc9d62017-11-21 18:25:12 +0000701 // Call to void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
702 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types);
Samuel Antaodf158d52016-04-27 22:58:19 +0000703 OMPRTL__tgt_target_data_begin,
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000704 // Call to void __tgt_target_data_begin_nowait(int64_t device_id, int32_t
705 // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
706 // *arg_types);
707 OMPRTL__tgt_target_data_begin_nowait,
George Rokos63bc9d62017-11-21 18:25:12 +0000708 // Call to void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
709 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types);
Samuel Antaodf158d52016-04-27 22:58:19 +0000710 OMPRTL__tgt_target_data_end,
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000711 // Call to void __tgt_target_data_end_nowait(int64_t device_id, int32_t
712 // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
713 // *arg_types);
714 OMPRTL__tgt_target_data_end_nowait,
George Rokos63bc9d62017-11-21 18:25:12 +0000715 // Call to void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
716 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types);
Samuel Antao8d2d7302016-05-26 18:30:22 +0000717 OMPRTL__tgt_target_data_update,
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +0000718 // Call to void __tgt_target_data_update_nowait(int64_t device_id, int32_t
719 // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
720 // *arg_types);
721 OMPRTL__tgt_target_data_update_nowait,
Alexey Bataev50b3c952016-02-19 10:38:26 +0000722};
723
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000724/// A basic class for pre|post-action for advanced codegen sequence for OpenMP
725/// region.
726class CleanupTy final : public EHScopeStack::Cleanup {
727 PrePostActionTy *Action;
728
729public:
730 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {}
731 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
732 if (!CGF.HaveInsertPoint())
733 return;
734 Action->Exit(CGF);
735 }
736};
737
Hans Wennborg7eb54642015-09-10 17:07:54 +0000738} // anonymous namespace
Alexey Bataev18095712014-10-10 12:19:54 +0000739
Alexey Bataev14fa1c62016-03-29 05:34:15 +0000740void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const {
741 CodeGenFunction::RunCleanupsScope Scope(CGF);
742 if (PrePostAction) {
743 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction);
744 Callback(CodeGen, CGF, *PrePostAction);
745 } else {
746 PrePostActionTy Action;
747 Callback(CodeGen, CGF, Action);
748 }
749}
750
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000751/// Check if the combiner is a call to UDR combiner and if it is so return the
752/// UDR decl used for reduction.
753static const OMPDeclareReductionDecl *
754getReductionInit(const Expr *ReductionOp) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000755 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
756 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
757 if (const auto *DRE =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000758 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000759 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl()))
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000760 return DRD;
761 return nullptr;
762}
763
764static void emitInitWithReductionInitializer(CodeGenFunction &CGF,
765 const OMPDeclareReductionDecl *DRD,
766 const Expr *InitOp,
767 Address Private, Address Original,
768 QualType Ty) {
769 if (DRD->getInitializer()) {
770 std::pair<llvm::Function *, llvm::Function *> Reduction =
771 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000772 const auto *CE = cast<CallExpr>(InitOp);
773 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000774 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
775 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000776 const auto *LHSDRE =
777 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr());
778 const auto *RHSDRE =
779 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000780 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
781 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000782 [=]() { return Private; });
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000783 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000784 [=]() { return Original; });
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000785 (void)PrivateScope.Privatize();
786 RValue Func = RValue::get(Reduction.second);
787 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
788 CGF.EmitIgnoredExpr(InitOp);
789 } else {
790 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty);
Alexey Bataev18fa2322018-05-02 14:20:50 +0000791 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"});
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000792 auto *GV = new llvm::GlobalVariable(
793 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true,
Alexey Bataev18fa2322018-05-02 14:20:50 +0000794 llvm::GlobalValue::PrivateLinkage, Init, Name);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000795 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty);
796 RValue InitRVal;
797 switch (CGF.getEvaluationKind(Ty)) {
798 case TEK_Scalar:
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000799 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000800 break;
801 case TEK_Complex:
802 InitRVal =
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000803 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation()));
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000804 break;
805 case TEK_Aggregate:
806 InitRVal = RValue::getAggregate(LV.getAddress());
807 break;
808 }
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000809 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000810 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal);
811 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(),
812 /*IsInitializer=*/false);
813 }
814}
815
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000816/// Emit initialization of arrays of complex types.
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000817/// \param DestAddr Address of the array.
818/// \param Type Type of array.
819/// \param Init Initial expression of array.
820/// \param SrcAddr Address of the original array.
821static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr,
Alexey Bataeva7b19152017-10-12 20:03:39 +0000822 QualType Type, bool EmitDeclareReductionInit,
823 const Expr *Init,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000824 const OMPDeclareReductionDecl *DRD,
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000825 Address SrcAddr = Address::invalid()) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000826 // Perform element-by-element initialization.
827 QualType ElementTy;
828
829 // Drill down to the base element type on both arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000830 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
831 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000832 DestAddr =
833 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType());
834 if (DRD)
835 SrcAddr =
836 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType());
837
838 llvm::Value *SrcBegin = nullptr;
839 if (DRD)
840 SrcBegin = SrcAddr.getPointer();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000841 llvm::Value *DestBegin = DestAddr.getPointer();
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000842 // Cast from pointer to array type to pointer to single element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000843 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000844 // The basic structure here is a while-do loop.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000845 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body");
846 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done");
847 llvm::Value *IsEmpty =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000848 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty");
849 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
850
851 // Enter the loop body, making that address the current address.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000852 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000853 CGF.EmitBlock(BodyBB);
854
855 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
856
857 llvm::PHINode *SrcElementPHI = nullptr;
858 Address SrcElementCurrent = Address::invalid();
859 if (DRD) {
860 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2,
861 "omp.arraycpy.srcElementPast");
862 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
863 SrcElementCurrent =
864 Address(SrcElementPHI,
865 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
866 }
867 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI(
868 DestBegin->getType(), 2, "omp.arraycpy.destElementPast");
869 DestElementPHI->addIncoming(DestBegin, EntryBB);
870 Address DestElementCurrent =
871 Address(DestElementPHI,
872 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize));
873
874 // Emit copy.
875 {
876 CodeGenFunction::RunCleanupsScope InitScope(CGF);
Alexey Bataeva7b19152017-10-12 20:03:39 +0000877 if (EmitDeclareReductionInit) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000878 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent,
879 SrcElementCurrent, ElementTy);
880 } else
881 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(),
882 /*IsInitializer=*/false);
883 }
884
885 if (DRD) {
886 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000887 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000888 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
889 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock());
890 }
891
892 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000893 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000894 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
895 // Check whether we've reached the end.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000896 llvm::Value *Done =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000897 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
898 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
899 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock());
900
901 // Done.
902 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
903}
904
905LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) {
Alexey Bataevf47c4b42017-09-26 13:47:31 +0000906 return CGF.EmitOMPSharedLValue(E);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000907}
908
909LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF,
910 const Expr *E) {
911 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E))
912 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false);
913 return LValue();
914}
915
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000916void ReductionCodeGen::emitAggregateInitialization(
917 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal,
918 const OMPDeclareReductionDecl *DRD) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000919 // Emit VarDecl with copy init for arrays.
920 // Get the address of the original variable captured in current
921 // captured region.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000922 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000923 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
Alexey Bataeva7b19152017-10-12 20:03:39 +0000924 bool EmitDeclareReductionInit =
925 DRD && (DRD->getInitializer() || !PrivateVD->hasInit());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000926 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(),
Alexey Bataeva7b19152017-10-12 20:03:39 +0000927 EmitDeclareReductionInit,
928 EmitDeclareReductionInit ? ClausesData[N].ReductionOp
929 : PrivateVD->getInit(),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000930 DRD, SharedLVal.getAddress());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000931}
932
933ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds,
934 ArrayRef<const Expr *> Privates,
935 ArrayRef<const Expr *> ReductionOps) {
936 ClausesData.reserve(Shareds.size());
937 SharedAddresses.reserve(Shareds.size());
938 Sizes.reserve(Shareds.size());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000939 BaseDecls.reserve(Shareds.size());
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000940 auto IPriv = Privates.begin();
941 auto IRed = ReductionOps.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000942 for (const Expr *Ref : Shareds) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000943 ClausesData.emplace_back(Ref, *IPriv, *IRed);
944 std::advance(IPriv, 1);
945 std::advance(IRed, 1);
946 }
947}
948
949void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) {
950 assert(SharedAddresses.size() == N &&
951 "Number of generated lvalues must be exactly N.");
Jonas Hahnfeld4525c822017-10-23 19:01:35 +0000952 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref);
953 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref);
954 SharedAddresses.emplace_back(First, Second);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000955}
956
957void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000958 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000959 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
960 QualType PrivateType = PrivateVD->getType();
961 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref);
Jonas Hahnfeld4525c822017-10-23 19:01:35 +0000962 if (!PrivateType->isVariablyModifiedType()) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000963 Sizes.emplace_back(
964 CGF.getTypeSize(
965 SharedAddresses[N].first.getType().getNonReferenceType()),
966 nullptr);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000967 return;
968 }
969 llvm::Value *Size;
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000970 llvm::Value *SizeInChars;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000971 auto *ElemType =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000972 cast<llvm::PointerType>(SharedAddresses[N].first.getPointer()->getType())
973 ->getElementType();
974 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000975 if (AsArraySection) {
976 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(),
977 SharedAddresses[N].first.getPointer());
978 Size = CGF.Builder.CreateNUWAdd(
979 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000980 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000981 } else {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000982 SizeInChars = CGF.getTypeSize(
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000983 SharedAddresses[N].first.getType().getNonReferenceType());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000984 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000985 }
Alexey Bataevbe5a8b42017-07-17 13:30:36 +0000986 Sizes.emplace_back(SizeInChars, Size);
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000987 CodeGenFunction::OpaqueValueMapping OpaqueMap(
988 CGF,
989 cast<OpaqueValueExpr>(
990 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),
991 RValue::get(Size));
992 CGF.EmitVariablyModifiedType(PrivateType);
993}
994
995void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N,
996 llvm::Value *Size) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +0000997 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +0000998 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
999 QualType PrivateType = PrivateVD->getType();
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001000 if (!PrivateType->isVariablyModifiedType()) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001001 assert(!Size && !Sizes[N].second &&
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001002 "Size should be nullptr for non-variably modified reduction "
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001003 "items.");
1004 return;
1005 }
1006 CodeGenFunction::OpaqueValueMapping OpaqueMap(
1007 CGF,
1008 cast<OpaqueValueExpr>(
1009 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()),
1010 RValue::get(Size));
1011 CGF.EmitVariablyModifiedType(PrivateType);
1012}
1013
1014void ReductionCodeGen::emitInitialization(
1015 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal,
1016 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) {
1017 assert(SharedAddresses.size() > N && "No variable was generated");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001018 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001019 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001020 const OMPDeclareReductionDecl *DRD =
1021 getReductionInit(ClausesData[N].ReductionOp);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001022 QualType PrivateType = PrivateVD->getType();
1023 PrivateAddr = CGF.Builder.CreateElementBitCast(
1024 PrivateAddr, CGF.ConvertTypeForMem(PrivateType));
1025 QualType SharedType = SharedAddresses[N].first.getType();
1026 SharedLVal = CGF.MakeAddrLValue(
1027 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(),
1028 CGF.ConvertTypeForMem(SharedType)),
Ivan A. Kosarevf5f20462017-10-12 11:29:46 +00001029 SharedType, SharedAddresses[N].first.getBaseInfo(),
Ivan A. Kosarevb9c59f32017-10-31 11:05:34 +00001030 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType));
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001031 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001032 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001033 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) {
1034 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp,
1035 PrivateAddr, SharedLVal.getAddress(),
1036 SharedLVal.getType());
1037 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() &&
1038 !CGF.isTrivialInitializer(PrivateVD->getInit())) {
1039 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr,
1040 PrivateVD->getType().getQualifiers(),
1041 /*IsInitializer=*/false);
1042 }
1043}
1044
1045bool ReductionCodeGen::needCleanups(unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001046 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001047 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1048 QualType PrivateType = PrivateVD->getType();
1049 QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
1050 return DTorKind != QualType::DK_none;
1051}
1052
1053void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N,
1054 Address PrivateAddr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001055 const auto *PrivateVD =
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001056 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl());
1057 QualType PrivateType = PrivateVD->getType();
1058 QualType::DestructionKind DTorKind = PrivateType.isDestructedType();
1059 if (needCleanups(N)) {
1060 PrivateAddr = CGF.Builder.CreateElementBitCast(
1061 PrivateAddr, CGF.ConvertTypeForMem(PrivateType));
1062 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType);
1063 }
1064}
1065
1066static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
1067 LValue BaseLV) {
1068 BaseTy = BaseTy.getNonReferenceType();
1069 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
1070 !CGF.getContext().hasSameType(BaseTy, ElTy)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001071 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001072 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(), PtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001073 } else {
Ivan A. Kosarev9f9d1572017-10-30 11:49:31 +00001074 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(), BaseTy);
1075 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001076 }
1077 BaseTy = BaseTy->getPointeeType();
1078 }
1079 return CGF.MakeAddrLValue(
1080 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(),
1081 CGF.ConvertTypeForMem(ElTy)),
Ivan A. Kosarevf5f20462017-10-12 11:29:46 +00001082 BaseLV.getType(), BaseLV.getBaseInfo(),
Ivan A. Kosarevb9c59f32017-10-31 11:05:34 +00001083 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType()));
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001084}
1085
1086static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy,
1087 llvm::Type *BaseLVType, CharUnits BaseLVAlignment,
1088 llvm::Value *Addr) {
1089 Address Tmp = Address::invalid();
1090 Address TopTmp = Address::invalid();
1091 Address MostTopTmp = Address::invalid();
1092 BaseTy = BaseTy.getNonReferenceType();
1093 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) &&
1094 !CGF.getContext().hasSameType(BaseTy, ElTy)) {
1095 Tmp = CGF.CreateMemTemp(BaseTy);
1096 if (TopTmp.isValid())
1097 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp);
1098 else
1099 MostTopTmp = Tmp;
1100 TopTmp = Tmp;
1101 BaseTy = BaseTy->getPointeeType();
1102 }
1103 llvm::Type *Ty = BaseLVType;
1104 if (Tmp.isValid())
1105 Ty = Tmp.getElementType();
1106 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty);
1107 if (Tmp.isValid()) {
1108 CGF.Builder.CreateStore(Addr, Tmp);
1109 return MostTopTmp;
1110 }
1111 return Address(Addr, BaseLVAlignment);
1112}
1113
Alexey Bataev1c44e152018-03-06 18:59:43 +00001114static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001115 const VarDecl *OrigVD = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001116 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) {
1117 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts();
1118 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base))
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001119 Base = TempOASE->getBase()->IgnoreParenImpCasts();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001120 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001121 Base = TempASE->getBase()->IgnoreParenImpCasts();
1122 DE = cast<DeclRefExpr>(Base);
1123 OrigVD = cast<VarDecl>(DE->getDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001124 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) {
1125 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts();
1126 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base))
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001127 Base = TempASE->getBase()->IgnoreParenImpCasts();
1128 DE = cast<DeclRefExpr>(Base);
1129 OrigVD = cast<VarDecl>(DE->getDecl());
1130 }
Alexey Bataev1c44e152018-03-06 18:59:43 +00001131 return OrigVD;
1132}
1133
1134Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N,
1135 Address PrivateAddr) {
1136 const DeclRefExpr *DE;
1137 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001138 BaseDecls.emplace_back(OrigVD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001139 LValue OriginalBaseLValue = CGF.EmitLValue(DE);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001140 LValue BaseLValue =
1141 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(),
1142 OriginalBaseLValue);
1143 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff(
1144 BaseLValue.getPointer(), SharedAddresses[N].first.getPointer());
Jonas Hahnfeld273d2612017-12-06 19:15:28 +00001145 llvm::Value *PrivatePointer =
1146 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
1147 PrivateAddr.getPointer(),
1148 SharedAddresses[N].first.getAddress().getType());
1149 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001150 return castToBase(CGF, OrigVD->getType(),
1151 SharedAddresses[N].first.getType(),
Jonas Hahnfeld273d2612017-12-06 19:15:28 +00001152 OriginalBaseLValue.getAddress().getType(),
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001153 OriginalBaseLValue.getAlignment(), Ptr);
1154 }
1155 BaseDecls.emplace_back(
1156 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl()));
1157 return PrivateAddr;
1158}
1159
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001160bool ReductionCodeGen::usesReductionInitializer(unsigned N) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001161 const OMPDeclareReductionDecl *DRD =
1162 getReductionInit(ClausesData[N].ReductionOp);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00001163 return DRD && DRD->getInitializer();
1164}
1165
Alexey Bataev18095712014-10-10 12:19:54 +00001166LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) {
Alexey Bataev31300ed2016-02-04 11:27:03 +00001167 return CGF.EmitLoadOfPointerLValue(
1168 CGF.GetAddrOfLocalVar(getThreadIDVariable()),
1169 getThreadIDVariable()->getType()->castAs<PointerType>());
Alexey Bataev18095712014-10-10 12:19:54 +00001170}
1171
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001172void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001173 if (!CGF.HaveInsertPoint())
1174 return;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001175 // 1.2.2 OpenMP Language Terminology
1176 // Structured block - An executable statement with a single entry at the
1177 // top and a single exit at the bottom.
1178 // The point of exit cannot be a branch out of the structured block.
1179 // longjmp() and throw() must not violate the entry/exit criteria.
1180 CGF.EHStack.pushTerminate();
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001181 CodeGen(CGF);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001182 CGF.EHStack.popTerminate();
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001183}
1184
Alexey Bataev62b63b12015-03-10 07:28:44 +00001185LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue(
1186 CodeGenFunction &CGF) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00001187 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()),
1188 getThreadIDVariable()->getType(),
Ivan A. Kosarev5f8c0ca2017-10-10 09:39:32 +00001189 AlignmentSource::Decl);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001190}
1191
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001192static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC,
1193 QualType FieldTy) {
1194 auto *Field = FieldDecl::Create(
1195 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy,
1196 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()),
1197 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit);
1198 Field->setAccess(AS_public);
1199 DC->addDecl(Field);
1200 return Field;
1201}
1202
Alexey Bataev18fa2322018-05-02 14:20:50 +00001203CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator,
1204 StringRef Separator)
1205 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator),
1206 OffloadEntriesInfoManager(CGM) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001207 ASTContext &C = CGM.getContext();
1208 RecordDecl *RD = C.buildImplicitRecord("ident_t");
1209 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
1210 RD->startDefinition();
1211 // reserved_1
1212 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1213 // flags
1214 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1215 // reserved_2
1216 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1217 // reserved_3
1218 addFieldToRecordDecl(C, RD, KmpInt32Ty);
1219 // psource
1220 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
1221 RD->completeDefinition();
1222 IdentQTy = C.getRecordType(RD);
1223 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001224 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8);
Samuel Antaoee8fb302016-01-06 13:42:12 +00001225
1226 loadOffloadInfoMetadata();
Alexey Bataev9959db52014-05-06 10:08:46 +00001227}
1228
Alexey Bataev91797552015-03-18 04:13:55 +00001229void CGOpenMPRuntime::clear() {
1230 InternalVars.clear();
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00001231 // Clean non-target variable declarations possibly used only in debug info.
1232 for (const auto &Data : EmittedNonTargetVariables) {
1233 if (!Data.getValue().pointsToAliveValue())
1234 continue;
1235 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue());
1236 if (!GV)
1237 continue;
1238 if (!GV->isDeclaration() || GV->getNumUses() > 0)
1239 continue;
1240 GV->eraseFromParent();
1241 }
Alexey Bataev91797552015-03-18 04:13:55 +00001242}
1243
Alexey Bataev18fa2322018-05-02 14:20:50 +00001244std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const {
1245 SmallString<128> Buffer;
1246 llvm::raw_svector_ostream OS(Buffer);
1247 StringRef Sep = FirstSeparator;
1248 for (StringRef Part : Parts) {
1249 OS << Sep << Part;
1250 Sep = Separator;
1251 }
1252 return OS.str();
1253}
1254
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001255static llvm::Function *
1256emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty,
1257 const Expr *CombinerInitializer, const VarDecl *In,
1258 const VarDecl *Out, bool IsCombiner) {
1259 // void .omp_combiner.(Ty *in, Ty *out);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001260 ASTContext &C = CGM.getContext();
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001261 QualType PtrTy = C.getPointerType(Ty).withRestrict();
1262 FunctionArgList Args;
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001263 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(),
Alexey Bataev56223232017-06-09 13:40:18 +00001264 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001265 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(),
Alexey Bataev56223232017-06-09 13:40:18 +00001266 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001267 Args.push_back(&OmpOutParm);
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001268 Args.push_back(&OmpInParm);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001269 const CGFunctionInfo &FnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00001270 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001271 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00001272 std::string Name = CGM.getOpenMPRuntime().getName(
1273 {IsCombiner ? "omp_combiner" : "omp_initializer", ""});
1274 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
1275 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00001276 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Chandler Carruthfcd33142016-12-23 01:24:49 +00001277 Fn->removeFnAttr(llvm::Attribute::NoInline);
Mehdi Amini6aa9e9b2017-05-29 05:38:20 +00001278 Fn->removeFnAttr(llvm::Attribute::OptimizeNone);
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001279 Fn->addFnAttr(llvm::Attribute::AlwaysInline);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001280 CodeGenFunction CGF(CGM);
1281 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions.
1282 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions.
Alexey Bataev7cae94e2018-01-04 19:45:16 +00001283 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(),
1284 Out->getLocation());
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001285 CodeGenFunction::OMPPrivateScope Scope(CGF);
1286 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001287 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() {
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001288 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>())
1289 .getAddress();
1290 });
1291 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001292 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() {
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001293 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>())
1294 .getAddress();
1295 });
1296 (void)Scope.Privatize();
Alexey Bataev070f43a2017-09-06 14:49:58 +00001297 if (!IsCombiner && Out->hasInit() &&
1298 !CGF.isTrivialInitializer(Out->getInit())) {
1299 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out),
1300 Out->getType().getQualifiers(),
1301 /*IsInitializer=*/true);
1302 }
1303 if (CombinerInitializer)
1304 CGF.EmitIgnoredExpr(CombinerInitializer);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001305 Scope.ForceCleanup();
1306 CGF.FinishFunction();
1307 return Fn;
1308}
1309
1310void CGOpenMPRuntime::emitUserDefinedReduction(
1311 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) {
1312 if (UDRMap.count(D) > 0)
1313 return;
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001314 llvm::Function *Combiner = emitCombinerOrInitializer(
Alexey Bataeve6aa4692018-09-13 16:54:05 +00001315 CGM, D->getType(), D->getCombiner(),
1316 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()),
1317 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()),
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001318 /*IsCombiner=*/true);
1319 llvm::Function *Initializer = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001320 if (const Expr *Init = D->getInitializer()) {
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001321 Initializer = emitCombinerOrInitializer(
Alexey Bataev070f43a2017-09-06 14:49:58 +00001322 CGM, D->getType(),
1323 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init
1324 : nullptr,
Alexey Bataeve6aa4692018-09-13 16:54:05 +00001325 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()),
1326 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()),
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001327 /*IsCombiner=*/false);
1328 }
Alexey Bataev43a919f2018-04-13 17:48:43 +00001329 UDRMap.try_emplace(D, Combiner, Initializer);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001330 if (CGF) {
1331 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn);
1332 Decls.second.push_back(D);
1333 }
1334}
1335
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001336std::pair<llvm::Function *, llvm::Function *>
1337CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) {
1338 auto I = UDRMap.find(D);
1339 if (I != UDRMap.end())
1340 return I->second;
1341 emitUserDefinedReduction(/*CGF=*/nullptr, D);
1342 return UDRMap.lookup(D);
1343}
1344
James Y Knight9871db02019-02-05 16:42:33 +00001345static llvm::Function *emitParallelOrTeamsOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001346 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS,
1347 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind,
1348 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00001349 assert(ThreadIDVar->getType()->isPointerType() &&
1350 "thread id variable must be of type kmp_int32 *");
Alexey Bataev18095712014-10-10 12:19:54 +00001351 CodeGenFunction CGF(CGM, true);
Alexey Bataev25e5b442015-09-15 12:52:43 +00001352 bool HasCancel = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001353 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001354 HasCancel = OPD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001355 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001356 HasCancel = OPSD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001357 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D))
Alexey Bataev25e5b442015-09-15 12:52:43 +00001358 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001359 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D))
Alexey Bataev2139ed62017-11-16 18:20:21 +00001360 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001361 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D))
Alexey Bataev10a54312017-11-27 16:54:08 +00001362 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001363 else if (const auto *OPFD =
1364 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D))
Alexey Bataev10a54312017-11-27 16:54:08 +00001365 HasCancel = OPFD->hasCancel();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001366 else if (const auto *OPFD =
Alexey Bataev10a54312017-11-27 16:54:08 +00001367 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D))
1368 HasCancel = OPFD->hasCancel();
Alexey Bataev25e5b442015-09-15 12:52:43 +00001369 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind,
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001370 HasCancel, OutlinedHelperName);
Alexey Bataevd157d472015-06-24 03:35:38 +00001371 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Alexey Bataev2377fe92015-09-10 08:12:02 +00001372 return CGF.GenerateOpenMPCapturedStmtFunction(*CS);
Alexey Bataev18095712014-10-10 12:19:54 +00001373}
1374
James Y Knight9871db02019-02-05 16:42:33 +00001375llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001376 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1377 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1378 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel);
1379 return emitParallelOrTeamsOutlinedFunction(
1380 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1381}
1382
James Y Knight9871db02019-02-05 16:42:33 +00001383llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction(
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001384 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
1385 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
1386 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams);
1387 return emitParallelOrTeamsOutlinedFunction(
1388 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen);
1389}
1390
James Y Knight9871db02019-02-05 16:42:33 +00001391llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001392 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
Alexey Bataev48591dd2016-04-20 04:01:36 +00001393 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
1394 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
1395 bool Tied, unsigned &NumberOfParts) {
1396 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF,
1397 PrePostActionTy &) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00001398 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc());
1399 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc());
Alexey Bataev48591dd2016-04-20 04:01:36 +00001400 llvm::Value *TaskArgs[] = {
1401 UpLoc, ThreadID,
1402 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar),
1403 TaskTVar->getType()->castAs<PointerType>())
1404 .getPointer()};
1405 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs);
1406 };
1407 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar,
1408 UntiedCodeGen);
1409 CodeGen.setAction(Action);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001410 assert(!ThreadIDVar->getType()->isPointerType() &&
1411 "thread id variable must be of type kmp_int32 for tasks");
Alexey Bataev475a7442018-01-12 19:39:11 +00001412 const OpenMPDirectiveKind Region =
1413 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop
1414 : OMPD_task;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001415 const CapturedStmt *CS = D.getCapturedStmt(Region);
1416 const auto *TD = dyn_cast<OMPTaskDirective>(&D);
Alexey Bataev62b63b12015-03-10 07:28:44 +00001417 CodeGenFunction CGF(CGM, true);
Alexey Bataev7292c292016-04-25 12:22:29 +00001418 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen,
1419 InnermostKind,
1420 TD ? TD->hasCancel() : false, Action);
Alexey Bataevd157d472015-06-24 03:35:38 +00001421 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
James Y Knight9871db02019-02-05 16:42:33 +00001422 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS);
Alexey Bataev48591dd2016-04-20 04:01:36 +00001423 if (!Tied)
1424 NumberOfParts = Action.getNumberOfParts();
1425 return Res;
Alexey Bataev62b63b12015-03-10 07:28:44 +00001426}
1427
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001428static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM,
1429 const RecordDecl *RD, const CGRecordLayout &RL,
1430 ArrayRef<llvm::Constant *> Data) {
1431 llvm::StructType *StructTy = RL.getLLVMType();
1432 unsigned PrevIdx = 0;
1433 ConstantInitBuilder CIBuilder(CGM);
1434 auto DI = Data.begin();
1435 for (const FieldDecl *FD : RD->fields()) {
1436 unsigned Idx = RL.getLLVMFieldNo(FD);
1437 // Fill the alignment.
1438 for (unsigned I = PrevIdx; I < Idx; ++I)
1439 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I)));
1440 PrevIdx = Idx + 1;
1441 Fields.add(*DI);
1442 ++DI;
1443 }
1444}
1445
1446template <class... As>
1447static llvm::GlobalVariable *
Mike Ricee1ca7b62018-08-29 15:45:11 +00001448createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant,
1449 ArrayRef<llvm::Constant *> Data, const Twine &Name,
1450 As &&... Args) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001451 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1452 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1453 ConstantInitBuilder CIBuilder(CGM);
1454 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType());
1455 buildStructValue(Fields, CGM, RD, RL, Data);
1456 return Fields.finishAndCreateGlobal(
Mike Ricee1ca7b62018-08-29 15:45:11 +00001457 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant,
1458 std::forward<As>(Args)...);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001459}
1460
1461template <typename T>
Benjamin Kramer651d0bf2018-05-15 21:26:47 +00001462static void
1463createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty,
1464 ArrayRef<llvm::Constant *> Data,
1465 T &Parent) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001466 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl());
1467 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD);
1468 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType());
1469 buildStructValue(Fields, CGM, RD, RL, Data);
1470 Fields.finishAndAddTo(Parent);
1471}
1472
Alexey Bataev50b3c952016-02-19 10:38:26 +00001473Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001474 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy);
Alexey Bataevceeaa482018-11-21 21:04:34 +00001475 unsigned Reserved2Flags = getDefaultLocationReserved2Flags();
1476 FlagsTy FlagsKey(Flags, Reserved2Flags);
1477 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey);
Alexey Bataev9959db52014-05-06 10:08:46 +00001478 if (!Entry) {
1479 if (!DefaultOpenMPPSource) {
1480 // Initialize default location for psource field of ident_t structure of
1481 // all ident_t objects. Format is ";file;function;line;column;;".
1482 // Taken from
James Y Knight5d71fc52019-01-29 16:37:27 +00001483 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp
Alexey Bataev9959db52014-05-06 10:08:46 +00001484 DefaultOpenMPPSource =
John McCall7f416cc2015-09-08 08:05:57 +00001485 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001486 DefaultOpenMPPSource =
1487 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
1488 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001489
Alexey Bataevceeaa482018-11-21 21:04:34 +00001490 llvm::Constant *Data[] = {
1491 llvm::ConstantInt::getNullValue(CGM.Int32Ty),
1492 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
1493 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags),
1494 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource};
Mike Ricee1ca7b62018-08-29 15:45:11 +00001495 llvm::GlobalValue *DefaultOpenMPLocation =
Alexey Bataevceeaa482018-11-21 21:04:34 +00001496 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "",
Mike Ricee1ca7b62018-08-29 15:45:11 +00001497 llvm::GlobalValue::PrivateLinkage);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001498 DefaultOpenMPLocation->setUnnamedAddr(
1499 llvm::GlobalValue::UnnamedAddr::Global);
John McCall6c9f1fdb2016-11-19 08:17:24 +00001500
Alexey Bataevceeaa482018-11-21 21:04:34 +00001501 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation;
Alexey Bataev9959db52014-05-06 10:08:46 +00001502 }
John McCall7f416cc2015-09-08 08:05:57 +00001503 return Address(Entry, Align);
Alexey Bataev9959db52014-05-06 10:08:46 +00001504}
1505
Alexey Bataevfd006c42018-10-05 15:08:53 +00001506void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF,
1507 bool AtCurrentPoint) {
1508 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1509 assert(!Elem.second.ServiceInsertPt && "Insert point is set already.");
1510
1511 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty);
1512 if (AtCurrentPoint) {
1513 Elem.second.ServiceInsertPt = new llvm::BitCastInst(
1514 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock());
1515 } else {
1516 Elem.second.ServiceInsertPt =
1517 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt");
1518 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt);
1519 }
1520}
1521
1522void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) {
1523 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1524 if (Elem.second.ServiceInsertPt) {
1525 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt;
1526 Elem.second.ServiceInsertPt = nullptr;
1527 Ptr->eraseFromParent();
1528 }
1529}
1530
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001531llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF,
1532 SourceLocation Loc,
Alexey Bataev50b3c952016-02-19 10:38:26 +00001533 unsigned Flags) {
1534 Flags |= OMP_IDENT_KMPC;
Alexey Bataev9959db52014-05-06 10:08:46 +00001535 // If no debug info is generated - return global default location.
Benjamin Kramer8c305922016-02-02 11:06:51 +00001536 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo ||
Alexey Bataev9959db52014-05-06 10:08:46 +00001537 Loc.isInvalid())
John McCall7f416cc2015-09-08 08:05:57 +00001538 return getOrCreateDefaultLocation(Flags).getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001539
1540 assert(CGF.CurFn && "No function in current CodeGenFunction.");
1541
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001542 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy);
John McCall7f416cc2015-09-08 08:05:57 +00001543 Address LocValue = Address::invalid();
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001544 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
1545 if (I != OpenMPLocThreadIDMap.end())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001546 LocValue = Address(I->second.DebugLoc, Align);
John McCall7f416cc2015-09-08 08:05:57 +00001547
Alexander Musmanc6388682014-12-15 07:07:06 +00001548 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if
1549 // GetOpenMPThreadID was called before this routine.
John McCall7f416cc2015-09-08 08:05:57 +00001550 if (!LocValue.isValid()) {
Alexey Bataev15007ba2014-05-07 06:18:01 +00001551 // Generate "ident_t .kmpc_loc.addr;"
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001552 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr");
Alexey Bataev18095712014-10-10 12:19:54 +00001553 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
John McCall7f416cc2015-09-08 08:05:57 +00001554 Elem.second.DebugLoc = AI.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001555 LocValue = AI;
1556
Alexey Bataevfd006c42018-10-05 15:08:53 +00001557 if (!Elem.second.ServiceInsertPt)
1558 setLocThreadIdInsertPt(CGF);
Alexey Bataev9959db52014-05-06 10:08:46 +00001559 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001560 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001561 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001562 CGF.getTypeSize(IdentQTy));
Alexey Bataev9959db52014-05-06 10:08:46 +00001563 }
1564
1565 // char **psource = &.kmpc_loc_<flags>.addr.psource;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001566 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy);
1567 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin();
1568 LValue PSource =
1569 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource));
Alexey Bataev9959db52014-05-06 10:08:46 +00001570
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001571 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding());
Alexey Bataevf002aca2014-05-30 05:48:40 +00001572 if (OMPDebugLoc == nullptr) {
1573 SmallString<128> Buffer2;
1574 llvm::raw_svector_ostream OS2(Buffer2);
1575 // Build debug location
1576 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc);
1577 OS2 << ";" << PLoc.getFilename() << ";";
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001578 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl))
Alexey Bataevf002aca2014-05-30 05:48:40 +00001579 OS2 << FD->getQualifiedNameAsString();
Alexey Bataevf002aca2014-05-30 05:48:40 +00001580 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;";
1581 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str());
1582 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc;
Alexey Bataev9959db52014-05-06 10:08:46 +00001583 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001584 // *psource = ";<File>;<Function>;<Line>;<Column>;;";
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001585 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource);
Alexey Bataevf002aca2014-05-30 05:48:40 +00001586
John McCall7f416cc2015-09-08 08:05:57 +00001587 // Our callers always pass this to a runtime function, so for
1588 // convenience, go ahead and return a naked pointer.
1589 return LocValue.getPointer();
Alexey Bataev9959db52014-05-06 10:08:46 +00001590}
1591
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001592llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF,
1593 SourceLocation Loc) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001594 assert(CGF.CurFn && "No function in current CodeGenFunction.");
1595
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001596 llvm::Value *ThreadID = nullptr;
Alexey Bataev18095712014-10-10 12:19:54 +00001597 // Check whether we've already cached a load of the thread id in this
1598 // function.
Alexey Bataev1e4b7132014-12-03 12:11:24 +00001599 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn);
Alexey Bataev18095712014-10-10 12:19:54 +00001600 if (I != OpenMPLocThreadIDMap.end()) {
1601 ThreadID = I->second.ThreadID;
Alexey Bataev03b340a2014-10-21 03:16:40 +00001602 if (ThreadID != nullptr)
1603 return ThreadID;
1604 }
Alexey Bataevaee18552017-08-16 14:01:00 +00001605 // If exceptions are enabled, do not use parameter to avoid possible crash.
Alexey Bataev5d2c9a42017-11-02 18:55:05 +00001606 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions ||
1607 !CGF.getLangOpts().CXXExceptions ||
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001608 CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
Alexey Bataevaee18552017-08-16 14:01:00 +00001609 if (auto *OMPRegionInfo =
1610 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
1611 if (OMPRegionInfo->getThreadIDVariable()) {
1612 // Check if this an outlined function with thread id passed as argument.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001613 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF);
Alexey Bataev1e491372018-01-23 18:44:14 +00001614 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc);
Alexey Bataevaee18552017-08-16 14:01:00 +00001615 // If value loaded in entry block, cache it and use it everywhere in
1616 // function.
1617 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) {
1618 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1619 Elem.second.ThreadID = ThreadID;
1620 }
1621 return ThreadID;
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001622 }
Alexey Bataevd6c57552014-07-25 07:55:17 +00001623 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001624 }
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001625
1626 // This is not an outlined function region - need to call __kmpc_int32
1627 // kmpc_global_thread_num(ident_t *loc).
1628 // Generate thread id value and cache this value for use across the
1629 // function.
Alexey Bataevfd006c42018-10-05 15:08:53 +00001630 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn);
1631 if (!Elem.second.ServiceInsertPt)
1632 setLocThreadIdInsertPt(CGF);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00001633 CGBuilderTy::InsertPointGuard IPG(CGF.Builder);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001634 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001635 llvm::CallInst *Call = CGF.Builder.CreateCall(
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001636 createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
1637 emitUpdateLocation(CGF, Loc));
1638 Call->setCallingConv(CGF.getRuntimeCC());
Alexey Bataev0e1b4582017-11-02 14:25:34 +00001639 Elem.second.ThreadID = Call;
1640 return Call;
Alexey Bataev9959db52014-05-06 10:08:46 +00001641}
1642
Alexey Bataev3eff5f42015-02-25 08:32:46 +00001643void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001644 assert(CGF.CurFn && "No function in current CodeGenFunction.");
Alexey Bataevfd006c42018-10-05 15:08:53 +00001645 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) {
1646 clearLocThreadIdInsertPt(CGF);
Alexey Bataev03b340a2014-10-21 03:16:40 +00001647 OpenMPLocThreadIDMap.erase(CGF.CurFn);
Alexey Bataevfd006c42018-10-05 15:08:53 +00001648 }
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001649 if (FunctionUDRMap.count(CGF.CurFn) > 0) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001650 for(auto *D : FunctionUDRMap[CGF.CurFn])
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001651 UDRMap.erase(D);
Alexey Bataevc5b1d322016-03-04 09:22:22 +00001652 FunctionUDRMap.erase(CGF.CurFn);
1653 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001654}
1655
1656llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001657 return IdentTy->getPointerTo();
Alexey Bataev9959db52014-05-06 10:08:46 +00001658}
1659
1660llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001661 if (!Kmpc_MicroTy) {
1662 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...)
1663 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty),
1664 llvm::PointerType::getUnqual(CGM.Int32Ty)};
1665 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true);
1666 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001667 return llvm::PointerType::getUnqual(Kmpc_MicroTy);
1668}
1669
James Y Knight9871db02019-02-05 16:42:33 +00001670llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) {
1671 llvm::FunctionCallee RTLFn = nullptr;
Alexey Bataev50b3c952016-02-19 10:38:26 +00001672 switch (static_cast<OpenMPRTLFunction>(Function)) {
Alexey Bataev9959db52014-05-06 10:08:46 +00001673 case OMPRTL__kmpc_fork_call: {
1674 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro
1675 // microtask, ...);
Alexey Bataev23b69422014-06-18 07:08:49 +00001676 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1677 getKmpc_MicroPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001678 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001679 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
Alexey Bataev9959db52014-05-06 10:08:46 +00001680 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call");
James Y Knight9871db02019-02-05 16:42:33 +00001681 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) {
Johannes Doerfertac991bb2019-01-19 05:36:54 +00001682 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
1683 llvm::LLVMContext &Ctx = F->getContext();
1684 llvm::MDBuilder MDB(Ctx);
1685 // Annotate the callback behavior of the __kmpc_fork_call:
1686 // - The callback callee is argument number 2 (microtask).
1687 // - The first two arguments of the callback callee are unknown (-1).
1688 // - All variadic arguments to the __kmpc_fork_call are passed to the
1689 // callback callee.
1690 F->addMetadata(
1691 llvm::LLVMContext::MD_callback,
1692 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
1693 2, {-1, -1},
1694 /* VarArgsArePassed */ true)}));
1695 }
1696 }
Alexey Bataev9959db52014-05-06 10:08:46 +00001697 break;
1698 }
1699 case OMPRTL__kmpc_global_thread_num: {
1700 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc);
Alexey Bataev23b69422014-06-18 07:08:49 +00001701 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001702 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001703 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
Alexey Bataev9959db52014-05-06 10:08:46 +00001704 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num");
1705 break;
1706 }
Alexey Bataev97720002014-11-11 04:05:39 +00001707 case OMPRTL__kmpc_threadprivate_cached: {
1708 // Build void *__kmpc_threadprivate_cached(ident_t *loc,
1709 // kmp_int32 global_tid, void *data, size_t size, void ***cache);
1710 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1711 CGM.VoidPtrTy, CGM.SizeTy,
1712 CGM.VoidPtrTy->getPointerTo()->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001713 auto *FnTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001714 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false);
1715 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached");
1716 break;
1717 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001718 case OMPRTL__kmpc_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001719 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid,
1720 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001721 llvm::Type *TypeParams[] = {
1722 getIdentTyPointerTy(), CGM.Int32Ty,
1723 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001724 auto *FnTy =
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001725 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1726 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical");
1727 break;
1728 }
Alexey Bataevfc57d162015-12-15 10:55:09 +00001729 case OMPRTL__kmpc_critical_with_hint: {
1730 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid,
1731 // kmp_critical_name *crit, uintptr_t hint);
1732 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1733 llvm::PointerType::getUnqual(KmpCriticalNameTy),
1734 CGM.IntPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001735 auto *FnTy =
Alexey Bataevfc57d162015-12-15 10:55:09 +00001736 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1737 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint");
1738 break;
1739 }
Alexey Bataev97720002014-11-11 04:05:39 +00001740 case OMPRTL__kmpc_threadprivate_register: {
1741 // Build void __kmpc_threadprivate_register(ident_t *, void *data,
1742 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor);
1743 // typedef void *(*kmpc_ctor)(void *);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001744 auto *KmpcCtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001745 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
1746 /*isVarArg*/ false)->getPointerTo();
1747 // typedef void *(*kmpc_cctor)(void *, void *);
1748 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001749 auto *KmpcCopyCtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001750 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001751 /*isVarArg*/ false)
1752 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00001753 // typedef void (*kmpc_dtor)(void *);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001754 auto *KmpcDtorTy =
Alexey Bataev97720002014-11-11 04:05:39 +00001755 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false)
1756 ->getPointerTo();
1757 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy,
1758 KmpcCopyCtorTy, KmpcDtorTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001759 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs,
Alexey Bataev97720002014-11-11 04:05:39 +00001760 /*isVarArg*/ false);
1761 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register");
1762 break;
1763 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001764 case OMPRTL__kmpc_end_critical: {
Alexey Bataevf9472182014-09-22 12:32:31 +00001765 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid,
1766 // kmp_critical_name *crit);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001767 llvm::Type *TypeParams[] = {
1768 getIdentTyPointerTy(), CGM.Int32Ty,
1769 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001770 auto *FnTy =
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00001771 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1772 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical");
1773 break;
1774 }
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001775 case OMPRTL__kmpc_cancel_barrier: {
1776 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32
1777 // global_tid);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001778 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001779 auto *FnTy =
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00001780 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
1781 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier");
Alexey Bataev4a5bb772014-10-08 14:01:46 +00001782 break;
1783 }
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001784 case OMPRTL__kmpc_barrier: {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00001785 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001786 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001787 auto *FnTy =
Alexey Bataev81c7ea02015-07-03 09:56:58 +00001788 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1789 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier");
1790 break;
1791 }
Alexander Musmanc6388682014-12-15 07:07:06 +00001792 case OMPRTL__kmpc_for_static_fini: {
1793 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid);
1794 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001795 auto *FnTy =
Alexander Musmanc6388682014-12-15 07:07:06 +00001796 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1797 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini");
1798 break;
1799 }
Alexey Bataevb2059782014-10-13 08:23:51 +00001800 case OMPRTL__kmpc_push_num_threads: {
1801 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid,
1802 // kmp_int32 num_threads)
1803 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1804 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001805 auto *FnTy =
Alexey Bataevb2059782014-10-13 08:23:51 +00001806 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1807 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads");
1808 break;
1809 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00001810 case OMPRTL__kmpc_serialized_parallel: {
1811 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32
1812 // global_tid);
1813 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001814 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001815 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1816 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel");
1817 break;
1818 }
1819 case OMPRTL__kmpc_end_serialized_parallel: {
1820 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32
1821 // global_tid);
1822 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001823 auto *FnTy =
Alexey Bataevd74d0602014-10-13 06:02:40 +00001824 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
1825 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel");
1826 break;
1827 }
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001828 case OMPRTL__kmpc_flush: {
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001829 // Build void __kmpc_flush(ident_t *loc);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001830 llvm::Type *TypeParams[] = {getIdentTyPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001831 auto *FnTy =
Alexey Bataevd76df6d2015-02-24 12:55:09 +00001832 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
Alexey Bataevcc37cc12014-11-20 04:34:54 +00001833 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush");
1834 break;
1835 }
Alexey Bataev8d690652014-12-04 07:23:53 +00001836 case OMPRTL__kmpc_master: {
1837 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid);
1838 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001839 auto *FnTy =
Alexey Bataev8d690652014-12-04 07:23:53 +00001840 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1841 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master");
1842 break;
1843 }
1844 case OMPRTL__kmpc_end_master: {
1845 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid);
1846 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001847 auto *FnTy =
Alexey Bataev8d690652014-12-04 07:23:53 +00001848 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1849 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master");
1850 break;
1851 }
Alexey Bataev9f797f32015-02-05 05:57:51 +00001852 case OMPRTL__kmpc_omp_taskyield: {
1853 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid,
1854 // int end_part);
1855 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001856 auto *FnTy =
Alexey Bataev9f797f32015-02-05 05:57:51 +00001857 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1858 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield");
1859 break;
1860 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001861 case OMPRTL__kmpc_single: {
1862 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid);
1863 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001864 auto *FnTy =
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001865 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1866 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single");
1867 break;
1868 }
1869 case OMPRTL__kmpc_end_single: {
1870 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid);
1871 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001872 auto *FnTy =
Alexey Bataev6956e2e2015-02-05 06:35:41 +00001873 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1874 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single");
1875 break;
1876 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00001877 case OMPRTL__kmpc_omp_task_alloc: {
1878 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
1879 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
1880 // kmp_routine_entry_t *task_entry);
1881 assert(KmpRoutineEntryPtrTy != nullptr &&
1882 "Type kmp_routine_entry_t must be created.");
1883 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
1884 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy};
1885 // Return void * and then cast to particular kmp_task_t type.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001886 auto *FnTy =
Alexey Bataev62b63b12015-03-10 07:28:44 +00001887 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
1888 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc");
1889 break;
1890 }
1891 case OMPRTL__kmpc_omp_task: {
1892 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1893 // *new_task);
1894 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1895 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001896 auto *FnTy =
Alexey Bataev62b63b12015-03-10 07:28:44 +00001897 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1898 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task");
1899 break;
1900 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00001901 case OMPRTL__kmpc_copyprivate: {
1902 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid,
Alexey Bataev66beaa92015-04-30 03:47:32 +00001903 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *),
Alexey Bataeva63048e2015-03-23 06:18:07 +00001904 // kmp_int32 didit);
1905 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1906 auto *CpyFnTy =
1907 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false);
Alexey Bataev66beaa92015-04-30 03:47:32 +00001908 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy,
Alexey Bataeva63048e2015-03-23 06:18:07 +00001909 CGM.VoidPtrTy, CpyFnTy->getPointerTo(),
1910 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001911 auto *FnTy =
Alexey Bataeva63048e2015-03-23 06:18:07 +00001912 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1913 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate");
1914 break;
1915 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001916 case OMPRTL__kmpc_reduce: {
1917 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid,
1918 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void
1919 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck);
1920 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1921 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
1922 /*isVarArg=*/false);
1923 llvm::Type *TypeParams[] = {
1924 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
1925 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
1926 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001927 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001928 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1929 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce");
1930 break;
1931 }
1932 case OMPRTL__kmpc_reduce_nowait: {
1933 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32
1934 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data,
1935 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name
1936 // *lck);
1937 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
1938 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams,
1939 /*isVarArg=*/false);
1940 llvm::Type *TypeParams[] = {
1941 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy,
1942 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(),
1943 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001944 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001945 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
1946 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait");
1947 break;
1948 }
1949 case OMPRTL__kmpc_end_reduce: {
1950 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid,
1951 // kmp_critical_name *lck);
1952 llvm::Type *TypeParams[] = {
1953 getIdentTyPointerTy(), CGM.Int32Ty,
1954 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001955 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001956 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1957 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce");
1958 break;
1959 }
1960 case OMPRTL__kmpc_end_reduce_nowait: {
1961 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid,
1962 // kmp_critical_name *lck);
1963 llvm::Type *TypeParams[] = {
1964 getIdentTyPointerTy(), CGM.Int32Ty,
1965 llvm::PointerType::getUnqual(KmpCriticalNameTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001966 auto *FnTy =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001967 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1968 RTLFn =
1969 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait");
1970 break;
1971 }
Alexey Bataev1d677132015-04-22 13:57:31 +00001972 case OMPRTL__kmpc_omp_task_begin_if0: {
1973 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1974 // *new_task);
1975 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1976 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001977 auto *FnTy =
Alexey Bataev1d677132015-04-22 13:57:31 +00001978 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1979 RTLFn =
1980 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0");
1981 break;
1982 }
1983 case OMPRTL__kmpc_omp_task_complete_if0: {
1984 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t
1985 // *new_task);
1986 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
1987 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001988 auto *FnTy =
Alexey Bataev1d677132015-04-22 13:57:31 +00001989 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1990 RTLFn = CGM.CreateRuntimeFunction(FnTy,
1991 /*Name=*/"__kmpc_omp_task_complete_if0");
1992 break;
1993 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001994 case OMPRTL__kmpc_ordered: {
1995 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid);
1996 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00001997 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001998 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
1999 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered");
2000 break;
2001 }
2002 case OMPRTL__kmpc_end_ordered: {
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002003 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002004 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002005 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002006 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2007 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered");
2008 break;
2009 }
Alexey Bataev8b8e2022015-04-27 05:22:09 +00002010 case OMPRTL__kmpc_omp_taskwait: {
2011 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid);
2012 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002013 auto *FnTy =
Alexey Bataev8b8e2022015-04-27 05:22:09 +00002014 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2015 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait");
2016 break;
2017 }
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002018 case OMPRTL__kmpc_taskgroup: {
2019 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid);
2020 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002021 auto *FnTy =
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002022 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2023 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup");
2024 break;
2025 }
2026 case OMPRTL__kmpc_end_taskgroup: {
2027 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid);
2028 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002029 auto *FnTy =
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00002030 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2031 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup");
2032 break;
2033 }
Alexey Bataev7f210c62015-06-18 13:40:03 +00002034 case OMPRTL__kmpc_push_proc_bind: {
2035 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid,
2036 // int proc_bind)
2037 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002038 auto *FnTy =
Alexey Bataev7f210c62015-06-18 13:40:03 +00002039 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2040 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind");
2041 break;
2042 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002043 case OMPRTL__kmpc_omp_task_with_deps: {
2044 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
2045 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
2046 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list);
2047 llvm::Type *TypeParams[] = {
2048 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty,
2049 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002050 auto *FnTy =
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002051 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false);
2052 RTLFn =
2053 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps");
2054 break;
2055 }
2056 case OMPRTL__kmpc_omp_wait_deps: {
2057 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
2058 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias,
2059 // kmp_depend_info_t *noalias_dep_list);
2060 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2061 CGM.Int32Ty, CGM.VoidPtrTy,
2062 CGM.Int32Ty, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002063 auto *FnTy =
Alexey Bataev1d2353d2015-06-24 11:01:36 +00002064 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2065 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps");
2066 break;
2067 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00002068 case OMPRTL__kmpc_cancellationpoint: {
2069 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
2070 // global_tid, kmp_int32 cncl_kind)
2071 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002072 auto *FnTy =
Alexey Bataev0f34da12015-07-02 04:17:07 +00002073 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2074 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint");
2075 break;
2076 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002077 case OMPRTL__kmpc_cancel: {
2078 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
2079 // kmp_int32 cncl_kind)
2080 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002081 auto *FnTy =
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00002082 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2083 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel");
2084 break;
2085 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002086 case OMPRTL__kmpc_push_num_teams: {
2087 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid,
2088 // kmp_int32 num_teams, kmp_int32 num_threads)
2089 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty,
2090 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002091 auto *FnTy =
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002092 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2093 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams");
2094 break;
2095 }
2096 case OMPRTL__kmpc_fork_teams: {
2097 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro
2098 // microtask, ...);
2099 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2100 getKmpc_MicroPointerTy()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002101 auto *FnTy =
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002102 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true);
2103 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams");
James Y Knight9871db02019-02-05 16:42:33 +00002104 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) {
Johannes Doerfertac991bb2019-01-19 05:36:54 +00002105 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) {
2106 llvm::LLVMContext &Ctx = F->getContext();
2107 llvm::MDBuilder MDB(Ctx);
2108 // Annotate the callback behavior of the __kmpc_fork_teams:
2109 // - The callback callee is argument number 2 (microtask).
2110 // - The first two arguments of the callback callee are unknown (-1).
2111 // - All variadic arguments to the __kmpc_fork_teams are passed to the
2112 // callback callee.
2113 F->addMetadata(
2114 llvm::LLVMContext::MD_callback,
2115 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding(
2116 2, {-1, -1},
2117 /* VarArgsArePassed */ true)}));
2118 }
2119 }
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00002120 break;
2121 }
Alexey Bataev7292c292016-04-25 12:22:29 +00002122 case OMPRTL__kmpc_taskloop: {
2123 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
2124 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
2125 // sched, kmp_uint64 grainsize, void *task_dup);
2126 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
2127 CGM.IntTy,
2128 CGM.VoidPtrTy,
2129 CGM.IntTy,
2130 CGM.Int64Ty->getPointerTo(),
2131 CGM.Int64Ty->getPointerTo(),
2132 CGM.Int64Ty,
2133 CGM.IntTy,
2134 CGM.IntTy,
2135 CGM.Int64Ty,
2136 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002137 auto *FnTy =
Alexey Bataev7292c292016-04-25 12:22:29 +00002138 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2139 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop");
2140 break;
2141 }
Alexey Bataev8b427062016-05-25 12:36:08 +00002142 case OMPRTL__kmpc_doacross_init: {
2143 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32
2144 // num_dims, struct kmp_dim *dims);
2145 llvm::Type *TypeParams[] = {getIdentTyPointerTy(),
2146 CGM.Int32Ty,
2147 CGM.Int32Ty,
2148 CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002149 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002150 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2151 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init");
2152 break;
2153 }
2154 case OMPRTL__kmpc_doacross_fini: {
2155 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid);
2156 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002157 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002158 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2159 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini");
2160 break;
2161 }
2162 case OMPRTL__kmpc_doacross_post: {
2163 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64
2164 // *vec);
2165 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2166 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002167 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002168 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2169 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post");
2170 break;
2171 }
2172 case OMPRTL__kmpc_doacross_wait: {
2173 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64
2174 // *vec);
2175 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty,
2176 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002177 auto *FnTy =
Alexey Bataev8b427062016-05-25 12:36:08 +00002178 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2179 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait");
2180 break;
2181 }
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002182 case OMPRTL__kmpc_task_reduction_init: {
2183 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void
2184 // *data);
2185 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002186 auto *FnTy =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002187 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2188 RTLFn =
2189 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init");
2190 break;
2191 }
2192 case OMPRTL__kmpc_task_reduction_get_th_data: {
2193 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
2194 // *d);
2195 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002196 auto *FnTy =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002197 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2198 RTLFn = CGM.CreateRuntimeFunction(
2199 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data");
2200 break;
2201 }
Alexey Bataev4f680db2019-03-19 16:41:16 +00002202 case OMPRTL__kmpc_alloc: {
Alexey Bataev6cf7b712019-04-08 19:06:42 +00002203 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t
2204 // al); omp_allocator_handle_t type is void *.
2205 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy};
Alexey Bataev4f680db2019-03-19 16:41:16 +00002206 auto *FnTy =
2207 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false);
2208 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc");
2209 break;
2210 }
2211 case OMPRTL__kmpc_free: {
Alexey Bataev6cf7b712019-04-08 19:06:42 +00002212 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t
2213 // al); omp_allocator_handle_t type is void *.
2214 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataev4f680db2019-03-19 16:41:16 +00002215 auto *FnTy =
2216 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2217 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free");
2218 break;
2219 }
Alexey Bataev7bb33532019-01-07 21:30:43 +00002220 case OMPRTL__kmpc_push_target_tripcount: {
2221 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64
2222 // size);
2223 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty};
2224 llvm::FunctionType *FnTy =
2225 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2226 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount");
2227 break;
2228 }
Samuel Antaobed3c462015-10-02 16:14:20 +00002229 case OMPRTL__tgt_target: {
George Rokos63bc9d62017-11-21 18:25:12 +00002230 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t
2231 // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
Samuel Antaobed3c462015-10-02 16:14:20 +00002232 // *arg_types);
George Rokos63bc9d62017-11-21 18:25:12 +00002233 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaobed3c462015-10-02 16:14:20 +00002234 CGM.VoidPtrTy,
2235 CGM.Int32Ty,
2236 CGM.VoidPtrPtrTy,
2237 CGM.VoidPtrPtrTy,
2238 CGM.SizeTy->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002239 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002240 auto *FnTy =
Samuel Antaobed3c462015-10-02 16:14:20 +00002241 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2242 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target");
2243 break;
2244 }
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002245 case OMPRTL__tgt_target_nowait: {
2246 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr,
2247 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes,
2248 // int64_t *arg_types);
2249 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2250 CGM.VoidPtrTy,
2251 CGM.Int32Ty,
2252 CGM.VoidPtrPtrTy,
2253 CGM.VoidPtrPtrTy,
2254 CGM.SizeTy->getPointerTo(),
2255 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002256 auto *FnTy =
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002257 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2258 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait");
2259 break;
2260 }
Samuel Antaob68e2db2016-03-03 16:20:23 +00002261 case OMPRTL__tgt_target_teams: {
George Rokos63bc9d62017-11-21 18:25:12 +00002262 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr,
Samuel Antaob68e2db2016-03-03 16:20:23 +00002263 // int32_t arg_num, void** args_base, void **args, size_t *arg_sizes,
George Rokos63bc9d62017-11-21 18:25:12 +00002264 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
2265 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaob68e2db2016-03-03 16:20:23 +00002266 CGM.VoidPtrTy,
2267 CGM.Int32Ty,
2268 CGM.VoidPtrPtrTy,
2269 CGM.VoidPtrPtrTy,
2270 CGM.SizeTy->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002271 CGM.Int64Ty->getPointerTo(),
Samuel Antaob68e2db2016-03-03 16:20:23 +00002272 CGM.Int32Ty,
2273 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002274 auto *FnTy =
Samuel Antaob68e2db2016-03-03 16:20:23 +00002275 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2276 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams");
2277 break;
2278 }
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002279 case OMPRTL__tgt_target_teams_nowait: {
2280 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void
2281 // *host_ptr, int32_t arg_num, void** args_base, void **args, size_t
2282 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit);
2283 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2284 CGM.VoidPtrTy,
2285 CGM.Int32Ty,
2286 CGM.VoidPtrPtrTy,
2287 CGM.VoidPtrPtrTy,
2288 CGM.SizeTy->getPointerTo(),
2289 CGM.Int64Ty->getPointerTo(),
2290 CGM.Int32Ty,
2291 CGM.Int32Ty};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002292 auto *FnTy =
Alexey Bataeva9f77c62017-12-13 21:04:20 +00002293 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2294 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait");
2295 break;
2296 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00002297 case OMPRTL__tgt_register_lib: {
2298 // Build void __tgt_register_lib(__tgt_bin_desc *desc);
2299 QualType ParamTy =
2300 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
2301 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002302 auto *FnTy =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002303 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2304 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib");
2305 break;
2306 }
2307 case OMPRTL__tgt_unregister_lib: {
2308 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc);
2309 QualType ParamTy =
2310 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy());
2311 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002312 auto *FnTy =
Samuel Antaoee8fb302016-01-06 13:42:12 +00002313 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2314 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib");
2315 break;
2316 }
Samuel Antaodf158d52016-04-27 22:58:19 +00002317 case OMPRTL__tgt_target_data_begin: {
George Rokos63bc9d62017-11-21 18:25:12 +00002318 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num,
2319 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types);
2320 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaodf158d52016-04-27 22:58:19 +00002321 CGM.Int32Ty,
2322 CGM.VoidPtrPtrTy,
2323 CGM.VoidPtrPtrTy,
2324 CGM.SizeTy->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002325 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002326 auto *FnTy =
Samuel Antaodf158d52016-04-27 22:58:19 +00002327 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2328 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin");
2329 break;
2330 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002331 case OMPRTL__tgt_target_data_begin_nowait: {
2332 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t
2333 // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
2334 // *arg_types);
2335 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2336 CGM.Int32Ty,
2337 CGM.VoidPtrPtrTy,
2338 CGM.VoidPtrPtrTy,
2339 CGM.SizeTy->getPointerTo(),
2340 CGM.Int64Ty->getPointerTo()};
2341 auto *FnTy =
2342 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2343 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait");
2344 break;
2345 }
Samuel Antaodf158d52016-04-27 22:58:19 +00002346 case OMPRTL__tgt_target_data_end: {
George Rokos63bc9d62017-11-21 18:25:12 +00002347 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num,
2348 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types);
2349 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antaodf158d52016-04-27 22:58:19 +00002350 CGM.Int32Ty,
2351 CGM.VoidPtrPtrTy,
2352 CGM.VoidPtrPtrTy,
2353 CGM.SizeTy->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002354 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002355 auto *FnTy =
Samuel Antaodf158d52016-04-27 22:58:19 +00002356 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2357 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end");
2358 break;
2359 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002360 case OMPRTL__tgt_target_data_end_nowait: {
2361 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t
2362 // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
2363 // *arg_types);
2364 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2365 CGM.Int32Ty,
2366 CGM.VoidPtrPtrTy,
2367 CGM.VoidPtrPtrTy,
2368 CGM.SizeTy->getPointerTo(),
2369 CGM.Int64Ty->getPointerTo()};
2370 auto *FnTy =
2371 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2372 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait");
2373 break;
2374 }
Samuel Antao8d2d7302016-05-26 18:30:22 +00002375 case OMPRTL__tgt_target_data_update: {
George Rokos63bc9d62017-11-21 18:25:12 +00002376 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num,
2377 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types);
2378 llvm::Type *TypeParams[] = {CGM.Int64Ty,
Samuel Antao8d2d7302016-05-26 18:30:22 +00002379 CGM.Int32Ty,
2380 CGM.VoidPtrPtrTy,
2381 CGM.VoidPtrPtrTy,
2382 CGM.SizeTy->getPointerTo(),
George Rokos63bc9d62017-11-21 18:25:12 +00002383 CGM.Int64Ty->getPointerTo()};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002384 auto *FnTy =
Samuel Antao8d2d7302016-05-26 18:30:22 +00002385 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2386 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update");
2387 break;
2388 }
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00002389 case OMPRTL__tgt_target_data_update_nowait: {
2390 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t
2391 // arg_num, void** args_base, void **args, size_t *arg_sizes, int64_t
2392 // *arg_types);
2393 llvm::Type *TypeParams[] = {CGM.Int64Ty,
2394 CGM.Int32Ty,
2395 CGM.VoidPtrPtrTy,
2396 CGM.VoidPtrPtrTy,
2397 CGM.SizeTy->getPointerTo(),
2398 CGM.Int64Ty->getPointerTo()};
2399 auto *FnTy =
2400 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2401 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait");
2402 break;
2403 }
Alexey Bataev9959db52014-05-06 10:08:46 +00002404 }
Alexey Bataev50b3c952016-02-19 10:38:26 +00002405 assert(RTLFn && "Unable to find OpenMP runtime function");
Alexey Bataev9959db52014-05-06 10:08:46 +00002406 return RTLFn;
2407}
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00002408
James Y Knight9871db02019-02-05 16:42:33 +00002409llvm::FunctionCallee
2410CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman21212e42015-03-13 10:38:23 +00002411 assert((IVSize == 32 || IVSize == 64) &&
2412 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002413 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4"
2414 : "__kmpc_for_static_init_4u")
2415 : (IVSigned ? "__kmpc_for_static_init_8"
2416 : "__kmpc_for_static_init_8u");
2417 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
2418 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
Alexander Musman21212e42015-03-13 10:38:23 +00002419 llvm::Type *TypeParams[] = {
2420 getIdentTyPointerTy(), // loc
2421 CGM.Int32Ty, // tid
2422 CGM.Int32Ty, // schedtype
2423 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
2424 PtrTy, // p_lower
2425 PtrTy, // p_upper
2426 PtrTy, // p_stride
2427 ITy, // incr
2428 ITy // chunk
2429 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002430 auto *FnTy =
Alexander Musman21212e42015-03-13 10:38:23 +00002431 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2432 return CGM.CreateRuntimeFunction(FnTy, Name);
2433}
2434
James Y Knight9871db02019-02-05 16:42:33 +00002435llvm::FunctionCallee
2436CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002437 assert((IVSize == 32 || IVSize == 64) &&
2438 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002439 StringRef Name =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002440 IVSize == 32
2441 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u")
2442 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002443 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
Alexander Musman92bdaab2015-03-12 13:37:50 +00002444 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc
2445 CGM.Int32Ty, // tid
2446 CGM.Int32Ty, // schedtype
2447 ITy, // lower
2448 ITy, // upper
2449 ITy, // stride
2450 ITy // chunk
2451 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002452 auto *FnTy =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002453 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false);
2454 return CGM.CreateRuntimeFunction(FnTy, Name);
2455}
2456
James Y Knight9871db02019-02-05 16:42:33 +00002457llvm::FunctionCallee
2458CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002459 assert((IVSize == 32 || IVSize == 64) &&
2460 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002461 StringRef Name =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002462 IVSize == 32
2463 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u")
2464 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u");
2465 llvm::Type *TypeParams[] = {
2466 getIdentTyPointerTy(), // loc
2467 CGM.Int32Ty, // tid
2468 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002469 auto *FnTy =
Alexey Bataev98eb6e32015-04-22 11:15:40 +00002470 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false);
2471 return CGM.CreateRuntimeFunction(FnTy, Name);
2472}
2473
James Y Knight9871db02019-02-05 16:42:33 +00002474llvm::FunctionCallee
2475CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002476 assert((IVSize == 32 || IVSize == 64) &&
2477 "IV size is not compatible with the omp runtime");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002478 StringRef Name =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002479 IVSize == 32
2480 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u")
2481 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002482 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty;
2483 auto *PtrTy = llvm::PointerType::getUnqual(ITy);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002484 llvm::Type *TypeParams[] = {
2485 getIdentTyPointerTy(), // loc
2486 CGM.Int32Ty, // tid
2487 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter
2488 PtrTy, // p_lower
2489 PtrTy, // p_upper
2490 PtrTy // p_stride
2491 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002492 auto *FnTy =
Alexander Musman92bdaab2015-03-12 13:37:50 +00002493 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false);
2494 return CGM.CreateRuntimeFunction(FnTy, Name);
2495}
2496
Alexey Bataev03f270c2018-03-30 18:31:07 +00002497Address CGOpenMPRuntime::getAddrOfDeclareTargetLink(const VarDecl *VD) {
2498 if (CGM.getLangOpts().OpenMPSimd)
2499 return Address::invalid();
Alexey Bataev92327c52018-03-26 16:40:55 +00002500 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00002501 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Alexey Bataev92327c52018-03-26 16:40:55 +00002502 if (Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
2503 SmallString<64> PtrName;
2504 {
2505 llvm::raw_svector_ostream OS(PtrName);
2506 OS << CGM.getMangledName(GlobalDecl(VD)) << "_decl_tgt_link_ptr";
2507 }
2508 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName);
2509 if (!Ptr) {
2510 QualType PtrTy = CGM.getContext().getPointerType(VD->getType());
2511 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy),
2512 PtrName);
Alexey Bataev03f270c2018-03-30 18:31:07 +00002513 if (!CGM.getLangOpts().OpenMPIsDevice) {
2514 auto *GV = cast<llvm::GlobalVariable>(Ptr);
2515 GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
2516 GV->setInitializer(CGM.GetAddrOfGlobal(VD));
2517 }
2518 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ptr));
2519 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr));
Alexey Bataev92327c52018-03-26 16:40:55 +00002520 }
2521 return Address(Ptr, CGM.getContext().getDeclAlign(VD));
2522 }
2523 return Address::invalid();
2524}
2525
Alexey Bataev97720002014-11-11 04:05:39 +00002526llvm::Constant *
2527CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002528 assert(!CGM.getLangOpts().OpenMPUseTLS ||
2529 !CGM.getContext().getTargetInfo().isTLSSupported());
Alexey Bataev97720002014-11-11 04:05:39 +00002530 // Lookup the entry, lazily creating it if necessary.
Alexey Bataev18fa2322018-05-02 14:20:50 +00002531 std::string Suffix = getName({"cache", ""});
2532 return getOrCreateInternalVariable(
2533 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix));
Alexey Bataev97720002014-11-11 04:05:39 +00002534}
2535
John McCall7f416cc2015-09-08 08:05:57 +00002536Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
2537 const VarDecl *VD,
2538 Address VDAddr,
2539 SourceLocation Loc) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002540 if (CGM.getLangOpts().OpenMPUseTLS &&
2541 CGM.getContext().getTargetInfo().isTLSSupported())
2542 return VDAddr;
2543
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002544 llvm::Type *VarTy = VDAddr.getElementType();
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002545 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00002546 CGF.Builder.CreatePointerCast(VDAddr.getPointer(),
2547 CGM.Int8PtrTy),
Alexey Bataev97720002014-11-11 04:05:39 +00002548 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)),
2549 getOrCreateThreadPrivateCache(VD)};
John McCall7f416cc2015-09-08 08:05:57 +00002550 return Address(CGF.EmitRuntimeCall(
2551 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
2552 VDAddr.getAlignment());
Alexey Bataev97720002014-11-11 04:05:39 +00002553}
2554
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002555void CGOpenMPRuntime::emitThreadPrivateVarInit(
John McCall7f416cc2015-09-08 08:05:57 +00002556 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor,
Alexey Bataev97720002014-11-11 04:05:39 +00002557 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) {
2558 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime
2559 // library.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002560 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002561 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num),
Alexey Bataev97720002014-11-11 04:05:39 +00002562 OMPLoc);
2563 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor)
2564 // to register constructor/destructor for variable.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002565 llvm::Value *Args[] = {
2566 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy),
2567 Ctor, CopyCtor, Dtor};
Alexey Bataev1e4b7132014-12-03 12:11:24 +00002568 CGF.EmitRuntimeCall(
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002569 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args);
Alexey Bataev97720002014-11-11 04:05:39 +00002570}
2571
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002572llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition(
John McCall7f416cc2015-09-08 08:05:57 +00002573 const VarDecl *VD, Address VDAddr, SourceLocation Loc,
Alexey Bataev97720002014-11-11 04:05:39 +00002574 bool PerformInit, CodeGenFunction *CGF) {
Samuel Antaof8b50122015-07-13 22:54:53 +00002575 if (CGM.getLangOpts().OpenMPUseTLS &&
2576 CGM.getContext().getTargetInfo().isTLSSupported())
2577 return nullptr;
2578
Alexey Bataev97720002014-11-11 04:05:39 +00002579 VD = VD->getDefinition(CGM.getContext());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00002580 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) {
Alexey Bataev97720002014-11-11 04:05:39 +00002581 QualType ASTTy = VD->getType();
2582
2583 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002584 const Expr *Init = VD->getAnyInitializer();
Alexey Bataev97720002014-11-11 04:05:39 +00002585 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
2586 // Generate function that re-emits the declaration's initializer into the
2587 // threadprivate copy of the variable VD
2588 CodeGenFunction CtorCGF(CGM);
2589 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002590 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
2591 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
Alexey Bataev56223232017-06-09 13:40:18 +00002592 ImplicitParamDecl::Other);
Alexey Bataev97720002014-11-11 04:05:39 +00002593 Args.push_back(&Dst);
2594
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002595 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
John McCallc56a8b32016-03-11 04:30:31 +00002596 CGM.getContext().VoidPtrTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002597 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002598 std::string Name = getName({"__kmpc_global_ctor_", ""});
2599 llvm::Function *Fn =
2600 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002601 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002602 Args, Loc, Loc);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002603 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002604 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00002605 CGM.getContext().VoidPtrTy, Dst.getLocation());
John McCall7f416cc2015-09-08 08:05:57 +00002606 Address Arg = Address(ArgVal, VDAddr.getAlignment());
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002607 Arg = CtorCGF.Builder.CreateElementBitCast(
2608 Arg, CtorCGF.ConvertTypeForMem(ASTTy));
Alexey Bataev97720002014-11-11 04:05:39 +00002609 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(),
2610 /*IsInitializer=*/true);
2611 ArgVal = CtorCGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00002612 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false,
Alexey Bataev97720002014-11-11 04:05:39 +00002613 CGM.getContext().VoidPtrTy, Dst.getLocation());
2614 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue);
2615 CtorCGF.FinishFunction();
2616 Ctor = Fn;
2617 }
2618 if (VD->getType().isDestructedType() != QualType::DK_none) {
2619 // Generate function that emits destructor call for the threadprivate copy
2620 // of the variable VD
2621 CodeGenFunction DtorCGF(CGM);
2622 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002623 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc,
2624 /*Id=*/nullptr, CGM.getContext().VoidPtrTy,
Alexey Bataev56223232017-06-09 13:40:18 +00002625 ImplicitParamDecl::Other);
Alexey Bataev97720002014-11-11 04:05:39 +00002626 Args.push_back(&Dst);
2627
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002628 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration(
John McCallc56a8b32016-03-11 04:30:31 +00002629 CGM.getContext().VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002630 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002631 std::string Name = getName({"__kmpc_global_dtor_", ""});
2632 llvm::Function *Fn =
2633 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc);
Adrian Prantl1858c662016-04-24 22:22:29 +00002634 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
Alexey Bataev97720002014-11-11 04:05:39 +00002635 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002636 Loc, Loc);
Adrian Prantl1858c662016-04-24 22:22:29 +00002637 // Create a scope with an artificial location for the body of this function.
2638 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002639 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar(
Alexey Bataev97720002014-11-11 04:05:39 +00002640 DtorCGF.GetAddrOfLocalVar(&Dst),
John McCall7f416cc2015-09-08 08:05:57 +00002641 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation());
2642 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy,
Alexey Bataev97720002014-11-11 04:05:39 +00002643 DtorCGF.getDestroyer(ASTTy.isDestructedType()),
2644 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
2645 DtorCGF.FinishFunction();
2646 Dtor = Fn;
2647 }
2648 // Do not emit init function if it is not required.
2649 if (!Ctor && !Dtor)
2650 return nullptr;
2651
2652 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002653 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs,
2654 /*isVarArg=*/false)
2655 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002656 // Copying constructor for the threadprivate variable.
2657 // Must be NULL - reserved by runtime, but currently it requires that this
2658 // parameter is always NULL. Otherwise it fires assertion.
2659 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy);
2660 if (Ctor == nullptr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002661 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy,
2662 /*isVarArg=*/false)
2663 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002664 Ctor = llvm::Constant::getNullValue(CtorTy);
2665 }
2666 if (Dtor == nullptr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002667 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy,
2668 /*isVarArg=*/false)
2669 ->getPointerTo();
Alexey Bataev97720002014-11-11 04:05:39 +00002670 Dtor = llvm::Constant::getNullValue(DtorTy);
2671 }
2672 if (!CGF) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002673 auto *InitFunctionTy =
Alexey Bataev97720002014-11-11 04:05:39 +00002674 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002675 std::string Name = getName({"__omp_threadprivate_init_", ""});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002676 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction(
Alexey Bataev18fa2322018-05-02 14:20:50 +00002677 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction());
Alexey Bataev97720002014-11-11 04:05:39 +00002678 CodeGenFunction InitCGF(CGM);
2679 FunctionArgList ArgList;
2680 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction,
2681 CGM.getTypes().arrangeNullaryFunction(), ArgList,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00002682 Loc, Loc);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002683 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002684 InitCGF.FinishFunction();
2685 return InitFunction;
2686 }
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002687 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc);
Alexey Bataev97720002014-11-11 04:05:39 +00002688 }
2689 return nullptr;
2690}
2691
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002692/// Obtain information that uniquely identifies a target entry. This
Alexey Bataev34f8a702018-03-28 14:28:54 +00002693/// consists of the file and device IDs as well as line number associated with
2694/// the relevant entry source location.
2695static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc,
2696 unsigned &DeviceID, unsigned &FileID,
2697 unsigned &LineNum) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002698 SourceManager &SM = C.getSourceManager();
Alexey Bataev34f8a702018-03-28 14:28:54 +00002699
2700 // The loc should be always valid and have a file ID (the user cannot use
2701 // #pragma directives in macros)
2702
2703 assert(Loc.isValid() && "Source location is expected to be always valid.");
Alexey Bataev34f8a702018-03-28 14:28:54 +00002704
2705 PresumedLoc PLoc = SM.getPresumedLoc(Loc);
2706 assert(PLoc.isValid() && "Source location is expected to be always valid.");
2707
2708 llvm::sys::fs::UniqueID ID;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00002709 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID))
2710 SM.getDiagnostics().Report(diag::err_cannot_open_file)
2711 << PLoc.getFilename() << EC.message();
Alexey Bataev34f8a702018-03-28 14:28:54 +00002712
2713 DeviceID = ID.getDevice();
2714 FileID = ID.getFile();
2715 LineNum = PLoc.getLine();
2716}
2717
2718bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD,
2719 llvm::GlobalVariable *Addr,
2720 bool PerformInit) {
2721 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00002722 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Alexey Bataev34f8a702018-03-28 14:28:54 +00002723 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link)
Alexey Bataevd01b7492018-08-15 19:45:12 +00002724 return CGM.getLangOpts().OpenMPIsDevice;
Alexey Bataev34f8a702018-03-28 14:28:54 +00002725 VD = VD->getDefinition(CGM.getContext());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00002726 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second)
Alexey Bataev34f8a702018-03-28 14:28:54 +00002727 return CGM.getLangOpts().OpenMPIsDevice;
2728
2729 QualType ASTTy = VD->getType();
2730
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002731 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc();
Alexey Bataev34f8a702018-03-28 14:28:54 +00002732 // Produce the unique prefix to identify the new target regions. We use
2733 // the source location of the variable declaration which we know to not
2734 // conflict with any target region.
2735 unsigned DeviceID;
2736 unsigned FileID;
2737 unsigned Line;
2738 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line);
2739 SmallString<128> Buffer, Out;
2740 {
2741 llvm::raw_svector_ostream OS(Buffer);
2742 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID)
2743 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
2744 }
2745
2746 const Expr *Init = VD->getAnyInitializer();
2747 if (CGM.getLangOpts().CPlusPlus && PerformInit) {
2748 llvm::Constant *Ctor;
2749 llvm::Constant *ID;
2750 if (CGM.getLangOpts().OpenMPIsDevice) {
2751 // Generate function that re-emits the declaration's initializer into
2752 // the threadprivate copy of the variable VD
2753 CodeGenFunction CtorCGF(CGM);
2754
2755 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2756 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2757 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
2758 FTy, Twine(Buffer, "_ctor"), FI, Loc);
2759 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF);
2760 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
2761 FunctionArgList(), Loc, Loc);
2762 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF);
2763 CtorCGF.EmitAnyExprToMem(Init,
2764 Address(Addr, CGM.getContext().getDeclAlign(VD)),
2765 Init->getType().getQualifiers(),
2766 /*IsInitializer=*/true);
2767 CtorCGF.FinishFunction();
2768 Ctor = Fn;
2769 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
Alexey Bataeve253f2f2018-05-09 14:15:18 +00002770 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor));
Alexey Bataev34f8a702018-03-28 14:28:54 +00002771 } else {
2772 Ctor = new llvm::GlobalVariable(
2773 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
2774 llvm::GlobalValue::PrivateLinkage,
2775 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor"));
2776 ID = Ctor;
2777 }
2778
2779 // Register the information for the entry associated with the constructor.
2780 Out.clear();
2781 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
2782 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor,
Alexey Bataev03f270c2018-03-30 18:31:07 +00002783 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor);
Alexey Bataev34f8a702018-03-28 14:28:54 +00002784 }
2785 if (VD->getType().isDestructedType() != QualType::DK_none) {
2786 llvm::Constant *Dtor;
2787 llvm::Constant *ID;
2788 if (CGM.getLangOpts().OpenMPIsDevice) {
2789 // Generate function that emits destructor call for the threadprivate
2790 // copy of the variable VD
2791 CodeGenFunction DtorCGF(CGM);
2792
2793 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction();
2794 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
2795 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction(
2796 FTy, Twine(Buffer, "_dtor"), FI, Loc);
2797 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF);
2798 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI,
2799 FunctionArgList(), Loc, Loc);
2800 // Create a scope with an artificial location for the body of this
2801 // function.
2802 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF);
2803 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)),
2804 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()),
2805 DtorCGF.needsEHCleanup(ASTTy.isDestructedType()));
2806 DtorCGF.FinishFunction();
2807 Dtor = Fn;
2808 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);
Alexey Bataeve253f2f2018-05-09 14:15:18 +00002809 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor));
Alexey Bataev34f8a702018-03-28 14:28:54 +00002810 } else {
2811 Dtor = new llvm::GlobalVariable(
2812 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
2813 llvm::GlobalValue::PrivateLinkage,
2814 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor"));
2815 ID = Dtor;
2816 }
2817 // Register the information for the entry associated with the destructor.
2818 Out.clear();
2819 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
2820 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor,
Alexey Bataev03f270c2018-03-30 18:31:07 +00002821 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor);
Alexey Bataev34f8a702018-03-28 14:28:54 +00002822 }
2823 return CGM.getLangOpts().OpenMPIsDevice;
2824}
2825
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002826Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF,
2827 QualType VarType,
2828 StringRef Name) {
Alexey Bataev18fa2322018-05-02 14:20:50 +00002829 std::string Suffix = getName({"artificial", ""});
2830 std::string CacheSuffix = getName({"cache", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002831 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002832 llvm::Value *GAddr =
2833 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002834 llvm::Value *Args[] = {
2835 emitUpdateLocation(CGF, SourceLocation()),
2836 getThreadID(CGF, SourceLocation()),
2837 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy),
2838 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy,
2839 /*IsSigned=*/false),
Alexey Bataev18fa2322018-05-02 14:20:50 +00002840 getOrCreateInternalVariable(
2841 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))};
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00002842 return Address(
2843 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2844 CGF.EmitRuntimeCall(
2845 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args),
2846 VarLVType->getPointerTo(/*AddrSpace=*/0)),
2847 CGM.getPointerAlign());
2848}
2849
Arpith Chacko Jacobbb36fe82017-01-10 15:42:51 +00002850void CGOpenMPRuntime::emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond,
2851 const RegionCodeGenTy &ThenGen,
2852 const RegionCodeGenTy &ElseGen) {
Alexey Bataev1d677132015-04-22 13:57:31 +00002853 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange());
2854
2855 // If the condition constant folds and can be elided, try to avoid emitting
2856 // the condition and the dead arm of the if/else.
2857 bool CondConstant;
2858 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002859 if (CondConstant)
Alexey Bataev1d677132015-04-22 13:57:31 +00002860 ThenGen(CGF);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002861 else
Alexey Bataev1d677132015-04-22 13:57:31 +00002862 ElseGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00002863 return;
2864 }
2865
2866 // Otherwise, the condition did not fold, or we couldn't elide it. Just
2867 // emit the conditional branch.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002868 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then");
2869 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else");
2870 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end");
Alexey Bataev1d677132015-04-22 13:57:31 +00002871 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0);
2872
2873 // Emit the 'then' code.
2874 CGF.EmitBlock(ThenBlock);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002875 ThenGen(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00002876 CGF.EmitBranch(ContBlock);
2877 // Emit the 'else' code if present.
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002878 // There is no need to emit line number for unconditional branch.
2879 (void)ApplyDebugLocation::CreateEmpty(CGF);
2880 CGF.EmitBlock(ElseBlock);
2881 ElseGen(CGF);
2882 // There is no need to emit line number for unconditional branch.
2883 (void)ApplyDebugLocation::CreateEmpty(CGF);
2884 CGF.EmitBranch(ContBlock);
Alexey Bataev1d677132015-04-22 13:57:31 +00002885 // Emit the continuation block for code after the if.
2886 CGF.EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00002887}
2888
Alexey Bataev1d677132015-04-22 13:57:31 +00002889void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00002890 llvm::Function *OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00002891 ArrayRef<llvm::Value *> CapturedVars,
Alexey Bataev1d677132015-04-22 13:57:31 +00002892 const Expr *IfCond) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00002893 if (!CGF.HaveInsertPoint())
2894 return;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002895 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002896 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF,
2897 PrePostActionTy &) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00002898 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002899 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev2377fe92015-09-10 08:12:02 +00002900 llvm::Value *Args[] = {
2901 RTLoc,
2902 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002903 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())};
Alexey Bataev2377fe92015-09-10 08:12:02 +00002904 llvm::SmallVector<llvm::Value *, 16> RealArgs;
2905 RealArgs.append(std::begin(Args), std::end(Args));
2906 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
2907
James Y Knight9871db02019-02-05 16:42:33 +00002908 llvm::FunctionCallee RTLFn =
2909 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call);
Alexey Bataev2377fe92015-09-10 08:12:02 +00002910 CGF.EmitRuntimeCall(RTLFn, RealArgs);
2911 };
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002912 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF,
2913 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002914 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
2915 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc);
Alexey Bataev1d677132015-04-22 13:57:31 +00002916 // Build calls:
2917 // __kmpc_serialized_parallel(&Loc, GTid);
2918 llvm::Value *Args[] = {RTLoc, ThreadID};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002919 CGF.EmitRuntimeCall(
2920 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args);
Alexey Bataevd74d0602014-10-13 06:02:40 +00002921
Alexey Bataev1d677132015-04-22 13:57:31 +00002922 // OutlinedFn(&GTid, &zero, CapturedStruct);
Alexey Bataev18fa2322018-05-02 14:20:50 +00002923 Address ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty,
2924 /*Name*/ ".zero.addr");
Alexey Bataev1d677132015-04-22 13:57:31 +00002925 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0));
Alexey Bataev2377fe92015-09-10 08:12:02 +00002926 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs;
Alexey Bataev8521ff62018-07-25 20:03:01 +00002927 // ThreadId for serialized parallels is 0.
2928 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
Alexey Bataev2377fe92015-09-10 08:12:02 +00002929 OutlinedFnArgs.push_back(ZeroAddr.getPointer());
2930 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end());
Alexey Bataev3c595a62017-08-14 15:01:03 +00002931 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs);
Alexey Bataevd74d0602014-10-13 06:02:40 +00002932
Alexey Bataev1d677132015-04-22 13:57:31 +00002933 // __kmpc_end_serialized_parallel(&Loc, GTid);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002934 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID};
Alexey Bataev1d677132015-04-22 13:57:31 +00002935 CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002936 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel),
2937 EndArgs);
Alexey Bataev1d677132015-04-22 13:57:31 +00002938 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002939 if (IfCond) {
Alexey Bataev1d677132015-04-22 13:57:31 +00002940 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002941 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002942 RegionCodeGenTy ThenRCG(ThenGen);
2943 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00002944 }
Alexey Bataevd74d0602014-10-13 06:02:40 +00002945}
2946
NAKAMURA Takumi59c74b222014-10-27 08:08:18 +00002947// If we're inside an (outlined) parallel region, use the region info's
Alexey Bataevd74d0602014-10-13 06:02:40 +00002948// thread-ID variable (it is passed in a first argument of the outlined function
2949// as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in
2950// regular serial code region, get thread ID by calling kmp_int32
2951// kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and
2952// return the address of that temp.
John McCall7f416cc2015-09-08 08:05:57 +00002953Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF,
2954 SourceLocation Loc) {
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002955 if (auto *OMPRegionInfo =
Alexey Bataevd74d0602014-10-13 06:02:40 +00002956 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00002957 if (OMPRegionInfo->getThreadIDVariable())
Alexey Bataev62b63b12015-03-10 07:28:44 +00002958 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress();
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00002959
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002960 llvm::Value *ThreadID = getThreadID(CGF, Loc);
2961 QualType Int32Ty =
Alexey Bataevd74d0602014-10-13 06:02:40 +00002962 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002963 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp.");
Alexey Bataevd74d0602014-10-13 06:02:40 +00002964 CGF.EmitStoreOfScalar(ThreadID,
John McCall7f416cc2015-09-08 08:05:57 +00002965 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty));
Alexey Bataevd74d0602014-10-13 06:02:40 +00002966
2967 return ThreadIDTemp;
2968}
2969
Alexey Bataev1af5bd52019-03-05 17:47:18 +00002970llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable(
2971 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) {
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00002972 SmallString<256> Buffer;
2973 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev97720002014-11-11 04:05:39 +00002974 Out << Name;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00002975 StringRef RuntimeName = Out.str();
Alexey Bataev43a919f2018-04-13 17:48:43 +00002976 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first;
David Blaikie13156b62014-11-19 03:06:06 +00002977 if (Elem.second) {
2978 assert(Elem.second->getType()->getPointerElementType() == Ty &&
Alexey Bataev97720002014-11-11 04:05:39 +00002979 "OMP internal variable has different type than requested");
David Blaikie13156b62014-11-19 03:06:06 +00002980 return &*Elem.second;
Alexey Bataev97720002014-11-11 04:05:39 +00002981 }
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00002982
David Blaikie13156b62014-11-19 03:06:06 +00002983 return Elem.second = new llvm::GlobalVariable(
2984 CGM.getModule(), Ty, /*IsConstant*/ false,
2985 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty),
Alexey Bataev1af5bd52019-03-05 17:47:18 +00002986 Elem.first(), /*InsertBefore=*/nullptr,
2987 llvm::GlobalValue::NotThreadLocal, AddressSpace);
Alexey Bataev97720002014-11-11 04:05:39 +00002988}
2989
Alexey Bataev3eff5f42015-02-25 08:32:46 +00002990llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) {
Alexey Bataev18fa2322018-05-02 14:20:50 +00002991 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str();
2992 std::string Name = getName({Prefix, "var"});
2993 return getOrCreateInternalVariable(KmpCriticalNameTy, Name);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00002994}
2995
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002996namespace {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002997/// Common pre(post)-action for different OpenMP constructs.
2998class CommonActionTy final : public PrePostActionTy {
James Y Knight9871db02019-02-05 16:42:33 +00002999 llvm::FunctionCallee EnterCallee;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003000 ArrayRef<llvm::Value *> EnterArgs;
James Y Knight9871db02019-02-05 16:42:33 +00003001 llvm::FunctionCallee ExitCallee;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003002 ArrayRef<llvm::Value *> ExitArgs;
3003 bool Conditional;
3004 llvm::BasicBlock *ContBlock = nullptr;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003005
3006public:
James Y Knight9871db02019-02-05 16:42:33 +00003007 CommonActionTy(llvm::FunctionCallee EnterCallee,
3008 ArrayRef<llvm::Value *> EnterArgs,
3009 llvm::FunctionCallee ExitCallee,
3010 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003011 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee),
3012 ExitArgs(ExitArgs), Conditional(Conditional) {}
3013 void Enter(CodeGenFunction &CGF) override {
3014 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs);
3015 if (Conditional) {
3016 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes);
3017 auto *ThenBlock = CGF.createBasicBlock("omp_if.then");
3018 ContBlock = CGF.createBasicBlock("omp_if.end");
3019 // Generate the branch (If-stmt)
3020 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock);
3021 CGF.EmitBlock(ThenBlock);
3022 }
Alexey Bataeva744ff52015-05-05 09:24:37 +00003023 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003024 void Done(CodeGenFunction &CGF) {
3025 // Emit the rest of blocks/branches
3026 CGF.EmitBranch(ContBlock);
3027 CGF.EmitBlock(ContBlock, true);
3028 }
3029 void Exit(CodeGenFunction &CGF) override {
3030 CGF.EmitRuntimeCall(ExitCallee, ExitArgs);
Alexey Bataev3e6124b2015-04-10 07:48:12 +00003031 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003032};
Hans Wennborg7eb54642015-09-10 17:07:54 +00003033} // anonymous namespace
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003034
3035void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF,
3036 StringRef CriticalName,
3037 const RegionCodeGenTy &CriticalOpGen,
Alexey Bataevfc57d162015-12-15 10:55:09 +00003038 SourceLocation Loc, const Expr *Hint) {
3039 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]);
Alexey Bataev75ddfab2014-12-01 11:32:38 +00003040 // CriticalOpGen();
3041 // __kmpc_end_critical(ident_t *, gtid, Lock);
3042 // Prepare arguments and build a call to __kmpc_critical
Alexey Bataev8ef31412015-12-18 07:58:25 +00003043 if (!CGF.HaveInsertPoint())
3044 return;
Alexey Bataevfc57d162015-12-15 10:55:09 +00003045 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3046 getCriticalRegionLock(CriticalName)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003047 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args),
3048 std::end(Args));
Alexey Bataevfc57d162015-12-15 10:55:09 +00003049 if (Hint) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003050 EnterArgs.push_back(CGF.Builder.CreateIntCast(
3051 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false));
3052 }
3053 CommonActionTy Action(
3054 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint
3055 : OMPRTL__kmpc_critical),
3056 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args);
3057 CriticalOpGen.setAction(Action);
Alexey Bataevfc57d162015-12-15 10:55:09 +00003058 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen);
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003059}
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003060
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003061void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003062 const RegionCodeGenTy &MasterOpGen,
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003063 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003064 if (!CGF.HaveInsertPoint())
3065 return;
Alexey Bataev8d690652014-12-04 07:23:53 +00003066 // if(__kmpc_master(ident_t *, gtid)) {
3067 // MasterOpGen();
3068 // __kmpc_end_master(ident_t *, gtid);
3069 // }
3070 // Prepare arguments and build a call to __kmpc_master
Alexey Bataevd7614fb2015-04-10 06:33:45 +00003071 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003072 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args,
3073 createRuntimeFunction(OMPRTL__kmpc_end_master), Args,
3074 /*Conditional=*/true);
3075 MasterOpGen.setAction(Action);
3076 emitInlinedDirective(CGF, OMPD_master, MasterOpGen);
3077 Action.Done(CGF);
Alexey Bataev8d690652014-12-04 07:23:53 +00003078}
3079
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003080void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
3081 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003082 if (!CGF.HaveInsertPoint())
3083 return;
Alexey Bataev9f797f32015-02-05 05:57:51 +00003084 // Build call __kmpc_omp_taskyield(loc, thread_id, 0);
3085 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003086 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataev9f797f32015-02-05 05:57:51 +00003087 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003088 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00003089 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
3090 Region->emitUntiedSwitch(CGF);
Alexey Bataev9f797f32015-02-05 05:57:51 +00003091}
3092
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003093void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF,
3094 const RegionCodeGenTy &TaskgroupOpGen,
3095 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003096 if (!CGF.HaveInsertPoint())
3097 return;
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003098 // __kmpc_taskgroup(ident_t *, gtid);
3099 // TaskgroupOpGen();
3100 // __kmpc_end_taskgroup(ident_t *, gtid);
3101 // Prepare arguments and build a call to __kmpc_taskgroup
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003102 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
3103 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args,
3104 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup),
3105 Args);
3106 TaskgroupOpGen.setAction(Action);
3107 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen);
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003108}
3109
John McCall7f416cc2015-09-08 08:05:57 +00003110/// Given an array of pointers to variables, project the address of a
3111/// given variable.
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003112static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array,
3113 unsigned Index, const VarDecl *Var) {
John McCall7f416cc2015-09-08 08:05:57 +00003114 // Pull out the pointer to the variable.
James Y Knight751fe282019-02-09 22:22:28 +00003115 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index);
John McCall7f416cc2015-09-08 08:05:57 +00003116 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr);
3117
3118 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00003119 Addr = CGF.Builder.CreateElementBitCast(
3120 Addr, CGF.ConvertTypeForMem(Var->getType()));
John McCall7f416cc2015-09-08 08:05:57 +00003121 return Addr;
3122}
3123
Alexey Bataeva63048e2015-03-23 06:18:07 +00003124static llvm::Value *emitCopyprivateCopyFunction(
Alexey Bataev420d45b2015-04-14 05:11:24 +00003125 CodeGenModule &CGM, llvm::Type *ArgsType,
3126 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003127 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps,
3128 SourceLocation Loc) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003129 ASTContext &C = CGM.getContext();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003130 // void copy_func(void *LHSArg, void *RHSArg);
3131 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003132 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3133 ImplicitParamDecl::Other);
3134 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
3135 ImplicitParamDecl::Other);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003136 Args.push_back(&LHSArg);
3137 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003138 const auto &CGFI =
3139 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00003140 std::string Name =
3141 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"});
3142 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
3143 llvm::GlobalValue::InternalLinkage, Name,
3144 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00003145 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00003146 Fn->setDoesNotRecurse();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003147 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003148 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev420d45b2015-04-14 05:11:24 +00003149 // Dest = (void*[n])(LHSArg);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003150 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00003151 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3152 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
3153 ArgsType), CGF.getPointerAlign());
3154 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
3155 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
3156 ArgsType), CGF.getPointerAlign());
Alexey Bataeva63048e2015-03-23 06:18:07 +00003157 // *(Type0*)Dst[0] = *(Type0*)Src[0];
3158 // *(Type1*)Dst[1] = *(Type1*)Src[1];
3159 // ...
3160 // *(Typen*)Dst[n] = *(Typen*)Src[n];
Alexey Bataeva63048e2015-03-23 06:18:07 +00003161 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003162 const auto *DestVar =
3163 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +00003164 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar);
3165
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003166 const auto *SrcVar =
3167 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +00003168 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar);
3169
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003170 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +00003171 QualType Type = VD->getType();
John McCall7f416cc2015-09-08 08:05:57 +00003172 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003173 }
Alexey Bataeva63048e2015-03-23 06:18:07 +00003174 CGF.FinishFunction();
3175 return Fn;
3176}
3177
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003178void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF,
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003179 const RegionCodeGenTy &SingleOpGen,
Alexey Bataeva63048e2015-03-23 06:18:07 +00003180 SourceLocation Loc,
3181 ArrayRef<const Expr *> CopyprivateVars,
3182 ArrayRef<const Expr *> SrcExprs,
3183 ArrayRef<const Expr *> DstExprs,
3184 ArrayRef<const Expr *> AssignmentOps) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003185 if (!CGF.HaveInsertPoint())
3186 return;
Alexey Bataeva63048e2015-03-23 06:18:07 +00003187 assert(CopyprivateVars.size() == SrcExprs.size() &&
3188 CopyprivateVars.size() == DstExprs.size() &&
3189 CopyprivateVars.size() == AssignmentOps.size());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003190 ASTContext &C = CGM.getContext();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003191 // int32 did_it = 0;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003192 // if(__kmpc_single(ident_t *, gtid)) {
3193 // SingleOpGen();
3194 // __kmpc_end_single(ident_t *, gtid);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003195 // did_it = 1;
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003196 // }
Alexey Bataeva63048e2015-03-23 06:18:07 +00003197 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3198 // <copy_func>, did_it);
3199
John McCall7f416cc2015-09-08 08:05:57 +00003200 Address DidIt = Address::invalid();
Alexey Bataeva63048e2015-03-23 06:18:07 +00003201 if (!CopyprivateVars.empty()) {
3202 // int32 did_it = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003203 QualType KmpInt32Ty =
3204 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003205 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it");
John McCall7f416cc2015-09-08 08:05:57 +00003206 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003207 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003208 // Prepare arguments and build a call to __kmpc_single
Alexey Bataevd7614fb2015-04-10 06:33:45 +00003209 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003210 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args,
3211 createRuntimeFunction(OMPRTL__kmpc_end_single), Args,
3212 /*Conditional=*/true);
3213 SingleOpGen.setAction(Action);
3214 emitInlinedDirective(CGF, OMPD_single, SingleOpGen);
3215 if (DidIt.isValid()) {
3216 // did_it = 1;
3217 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt);
3218 }
3219 Action.Done(CGF);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003220 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>,
3221 // <copy_func>, did_it);
John McCall7f416cc2015-09-08 08:05:57 +00003222 if (DidIt.isValid()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00003223 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003224 QualType CopyprivateArrayTy =
Alexey Bataeva63048e2015-03-23 06:18:07 +00003225 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
3226 /*IndexTypeQuals=*/0);
3227 // Create a list of all private variables for copyprivate.
John McCall7f416cc2015-09-08 08:05:57 +00003228 Address CopyprivateList =
Alexey Bataeva63048e2015-03-23 06:18:07 +00003229 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list");
3230 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +00003231 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I);
John McCall7f416cc2015-09-08 08:05:57 +00003232 CGF.Builder.CreateStore(
Alexey Bataeva63048e2015-03-23 06:18:07 +00003233 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00003234 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy),
3235 Elem);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003236 }
3237 // Build function that copies private values from single region to all other
3238 // threads in the corresponding parallel region.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003239 llvm::Value *CpyFn = emitCopyprivateCopyFunction(
Alexey Bataeva63048e2015-03-23 06:18:07 +00003240 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(),
Alexey Bataev7cae94e2018-01-04 19:45:16 +00003241 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003242 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy);
John McCall7f416cc2015-09-08 08:05:57 +00003243 Address CL =
3244 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList,
3245 CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003246 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt);
Alexey Bataeva63048e2015-03-23 06:18:07 +00003247 llvm::Value *Args[] = {
3248 emitUpdateLocation(CGF, Loc), // ident_t *<loc>
3249 getThreadID(CGF, Loc), // i32 <gtid>
Alexey Bataev66beaa92015-04-30 03:47:32 +00003250 BufSize, // size_t <buf_size>
John McCall7f416cc2015-09-08 08:05:57 +00003251 CL.getPointer(), // void *<copyprivate list>
Alexey Bataeva63048e2015-03-23 06:18:07 +00003252 CpyFn, // void (*) (void *, void *) <copy_func>
3253 DidItVal // i32 did_it
3254 };
3255 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args);
3256 }
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003257}
3258
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003259void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
3260 const RegionCodeGenTy &OrderedOpGen,
Alexey Bataev5f600d62015-09-29 03:48:57 +00003261 SourceLocation Loc, bool IsThreads) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003262 if (!CGF.HaveInsertPoint())
3263 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003264 // __kmpc_ordered(ident_t *, gtid);
3265 // OrderedOpGen();
3266 // __kmpc_end_ordered(ident_t *, gtid);
3267 // Prepare arguments and build a call to __kmpc_ordered
Alexey Bataev5f600d62015-09-29 03:48:57 +00003268 if (IsThreads) {
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003269 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003270 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args,
3271 createRuntimeFunction(OMPRTL__kmpc_end_ordered),
3272 Args);
3273 OrderedOpGen.setAction(Action);
3274 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
3275 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003276 }
Alexey Bataev5f600d62015-09-29 03:48:57 +00003277 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003278}
3279
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003280unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) {
Alexey Bataev50b3c952016-02-19 10:38:26 +00003281 unsigned Flags;
3282 if (Kind == OMPD_for)
3283 Flags = OMP_IDENT_BARRIER_IMPL_FOR;
3284 else if (Kind == OMPD_sections)
3285 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS;
3286 else if (Kind == OMPD_single)
3287 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE;
3288 else if (Kind == OMPD_barrier)
3289 Flags = OMP_IDENT_BARRIER_EXPL;
3290 else
3291 Flags = OMP_IDENT_BARRIER_IMPL;
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003292 return Flags;
3293}
3294
Alexey Bataevf6a53d62019-03-18 18:40:00 +00003295void CGOpenMPRuntime::getDefaultScheduleAndChunk(
3296 CodeGenFunction &CGF, const OMPLoopDirective &S,
3297 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const {
3298 // Check if the loop directive is actually a doacross loop directive. In this
3299 // case choose static, 1 schedule.
3300 if (llvm::any_of(
3301 S.getClausesOfKind<OMPOrderedClause>(),
3302 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) {
3303 ScheduleKind = OMPC_SCHEDULE_static;
3304 // Chunk size is 1 in this case.
3305 llvm::APInt ChunkSize(32, 1);
3306 ChunkExpr = IntegerLiteral::Create(
3307 CGF.getContext(), ChunkSize,
3308 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
3309 SourceLocation());
3310 }
3311}
3312
Alexey Bataevc3028ca2018-12-04 15:03:25 +00003313void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc,
3314 OpenMPDirectiveKind Kind, bool EmitChecks,
3315 bool ForceSimpleCall) {
3316 if (!CGF.HaveInsertPoint())
3317 return;
3318 // Build call __kmpc_cancel_barrier(loc, thread_id);
3319 // Build call __kmpc_barrier(loc, thread_id);
3320 unsigned Flags = getDefaultFlagsForBarriers(Kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003321 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc,
3322 // thread_id);
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003323 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags),
3324 getThreadID(CGF, Loc)};
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003325 if (auto *OMPRegionInfo =
3326 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev25e5b442015-09-15 12:52:43 +00003327 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003328 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003329 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args);
Alexey Bataev25e5b442015-09-15 12:52:43 +00003330 if (EmitChecks) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003331 // if (__kmpc_cancel_barrier()) {
3332 // exit from construct;
3333 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003334 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
3335 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
3336 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003337 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
3338 CGF.EmitBlock(ExitBB);
3339 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003340 CodeGenFunction::JumpDest CancelDestination =
Alexey Bataev25e5b442015-09-15 12:52:43 +00003341 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00003342 CGF.EmitBranchThroughCleanup(CancelDestination);
3343 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
3344 }
3345 return;
3346 }
3347 }
3348 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args);
Alexey Bataev4a5bb772014-10-08 14:01:46 +00003349}
3350
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003351/// Map the OpenMP loop schedule to the runtime enumeration.
Alexander Musmanc6388682014-12-15 07:07:06 +00003352static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind,
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003353 bool Chunked, bool Ordered) {
Alexander Musmanc6388682014-12-15 07:07:06 +00003354 switch (ScheduleKind) {
3355 case OMPC_SCHEDULE_static:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003356 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked)
3357 : (Ordered ? OMP_ord_static : OMP_sch_static);
Alexander Musmanc6388682014-12-15 07:07:06 +00003358 case OMPC_SCHEDULE_dynamic:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003359 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00003360 case OMPC_SCHEDULE_guided:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003361 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked;
Alexander Musmanc6388682014-12-15 07:07:06 +00003362 case OMPC_SCHEDULE_runtime:
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003363 return Ordered ? OMP_ord_runtime : OMP_sch_runtime;
3364 case OMPC_SCHEDULE_auto:
3365 return Ordered ? OMP_ord_auto : OMP_sch_auto;
Alexander Musmanc6388682014-12-15 07:07:06 +00003366 case OMPC_SCHEDULE_unknown:
3367 assert(!Chunked && "chunk was specified but schedule kind not known");
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003368 return Ordered ? OMP_ord_static : OMP_sch_static;
Alexander Musmanc6388682014-12-15 07:07:06 +00003369 }
3370 llvm_unreachable("Unexpected runtime schedule");
3371}
3372
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003373/// Map the OpenMP distribute schedule to the runtime enumeration.
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003374static OpenMPSchedType
3375getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) {
3376 // only static is allowed for dist_schedule
3377 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static;
3378}
3379
Alexander Musmanc6388682014-12-15 07:07:06 +00003380bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind,
3381 bool Chunked) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003382 OpenMPSchedType Schedule =
3383 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
Alexander Musmanc6388682014-12-15 07:07:06 +00003384 return Schedule == OMP_sch_static;
3385}
3386
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003387bool CGOpenMPRuntime::isStaticNonchunked(
3388 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003389 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003390 return Schedule == OMP_dist_sch_static;
3391}
3392
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00003393bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind,
3394 bool Chunked) const {
3395 OpenMPSchedType Schedule =
3396 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false);
3397 return Schedule == OMP_sch_static_chunked;
3398}
3399
3400bool CGOpenMPRuntime::isStaticChunked(
3401 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const {
3402 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked);
3403 return Schedule == OMP_dist_sch_static_chunked;
3404}
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003405
Alexander Musmandf7a8e22015-01-22 08:49:35 +00003406bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003407 OpenMPSchedType Schedule =
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003408 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00003409 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here");
3410 return Schedule != OMP_sch_static;
3411}
3412
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003413static int addMonoNonMonoModifier(OpenMPSchedType Schedule,
3414 OpenMPScheduleClauseModifier M1,
3415 OpenMPScheduleClauseModifier M2) {
Alexey Bataev6cff6242016-05-30 13:05:14 +00003416 int Modifier = 0;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003417 switch (M1) {
3418 case OMPC_SCHEDULE_MODIFIER_monotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003419 Modifier = OMP_sch_modifier_monotonic;
3420 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003421 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003422 Modifier = OMP_sch_modifier_nonmonotonic;
3423 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003424 case OMPC_SCHEDULE_MODIFIER_simd:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003425 if (Schedule == OMP_sch_static_chunked)
3426 Schedule = OMP_sch_static_balanced_chunked;
3427 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003428 case OMPC_SCHEDULE_MODIFIER_last:
3429 case OMPC_SCHEDULE_MODIFIER_unknown:
3430 break;
3431 }
3432 switch (M2) {
3433 case OMPC_SCHEDULE_MODIFIER_monotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003434 Modifier = OMP_sch_modifier_monotonic;
3435 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003436 case OMPC_SCHEDULE_MODIFIER_nonmonotonic:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003437 Modifier = OMP_sch_modifier_nonmonotonic;
3438 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003439 case OMPC_SCHEDULE_MODIFIER_simd:
Alexey Bataev6cff6242016-05-30 13:05:14 +00003440 if (Schedule == OMP_sch_static_chunked)
3441 Schedule = OMP_sch_static_balanced_chunked;
3442 break;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003443 case OMPC_SCHEDULE_MODIFIER_last:
3444 case OMPC_SCHEDULE_MODIFIER_unknown:
3445 break;
3446 }
Alexey Bataev6cff6242016-05-30 13:05:14 +00003447 return Schedule | Modifier;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003448}
3449
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003450void CGOpenMPRuntime::emitForDispatchInit(
3451 CodeGenFunction &CGF, SourceLocation Loc,
3452 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
3453 bool Ordered, const DispatchRTInput &DispatchValues) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003454 if (!CGF.HaveInsertPoint())
3455 return;
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003456 OpenMPSchedType Schedule = getRuntimeSchedule(
3457 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered);
John McCall7f416cc2015-09-08 08:05:57 +00003458 assert(Ordered ||
3459 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked &&
Alexey Bataev6cff6242016-05-30 13:05:14 +00003460 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked &&
3461 Schedule != OMP_sch_static_balanced_chunked));
John McCall7f416cc2015-09-08 08:05:57 +00003462 // Call __kmpc_dispatch_init(
3463 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule,
3464 // kmp_int[32|64] lower, kmp_int[32|64] upper,
3465 // kmp_int[32|64] stride, kmp_int[32|64] chunk);
Alexander Musmanc6388682014-12-15 07:07:06 +00003466
John McCall7f416cc2015-09-08 08:05:57 +00003467 // If the Chunk was not specified in the clause - use default value 1.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003468 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk
3469 : CGF.Builder.getIntN(IVSize, 1);
John McCall7f416cc2015-09-08 08:05:57 +00003470 llvm::Value *Args[] = {
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003471 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3472 CGF.Builder.getInt32(addMonoNonMonoModifier(
3473 Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003474 DispatchValues.LB, // Lower
3475 DispatchValues.UB, // Upper
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003476 CGF.Builder.getIntN(IVSize, 1), // Stride
3477 Chunk // Chunk
John McCall7f416cc2015-09-08 08:05:57 +00003478 };
3479 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args);
3480}
3481
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003482static void emitForStaticInitCall(
3483 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId,
James Y Knight9871db02019-02-05 16:42:33 +00003484 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003485 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003486 const CGOpenMPRuntime::StaticRTInput &Values) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003487 if (!CGF.HaveInsertPoint())
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003488 return;
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003489
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003490 assert(!Values.Ordered);
3491 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked ||
3492 Schedule == OMP_sch_static_balanced_chunked ||
3493 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked ||
3494 Schedule == OMP_dist_sch_static ||
3495 Schedule == OMP_dist_sch_static_chunked);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003496
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003497 // Call __kmpc_for_static_init(
3498 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype,
3499 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower,
3500 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride,
3501 // kmp_int[32|64] incr, kmp_int[32|64] chunk);
3502 llvm::Value *Chunk = Values.Chunk;
3503 if (Chunk == nullptr) {
3504 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static ||
3505 Schedule == OMP_dist_sch_static) &&
3506 "expected static non-chunked schedule");
3507 // If the Chunk was not specified in the clause - use default value 1.
3508 Chunk = CGF.Builder.getIntN(Values.IVSize, 1);
3509 } else {
3510 assert((Schedule == OMP_sch_static_chunked ||
3511 Schedule == OMP_sch_static_balanced_chunked ||
3512 Schedule == OMP_ord_static_chunked ||
3513 Schedule == OMP_dist_sch_static_chunked) &&
3514 "expected static chunked schedule");
3515 }
3516 llvm::Value *Args[] = {
3517 UpdateLocation,
3518 ThreadId,
3519 CGF.Builder.getInt32(addMonoNonMonoModifier(Schedule, M1,
3520 M2)), // Schedule type
3521 Values.IL.getPointer(), // &isLastIter
3522 Values.LB.getPointer(), // &LB
3523 Values.UB.getPointer(), // &UB
3524 Values.ST.getPointer(), // &Stride
3525 CGF.Builder.getIntN(Values.IVSize, 1), // Incr
3526 Chunk // Chunk
3527 };
3528 CGF.EmitRuntimeCall(ForStaticInitFunction, Args);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003529}
3530
John McCall7f416cc2015-09-08 08:05:57 +00003531void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF,
3532 SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003533 OpenMPDirectiveKind DKind,
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003534 const OpenMPScheduleTy &ScheduleKind,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003535 const StaticRTInput &Values) {
3536 OpenMPSchedType ScheduleNum = getRuntimeSchedule(
3537 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered);
3538 assert(isOpenMPWorksharingDirective(DKind) &&
3539 "Expected loop-based or sections-based directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003540 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003541 isOpenMPLoopDirective(DKind)
3542 ? OMP_IDENT_WORK_LOOP
3543 : OMP_IDENT_WORK_SECTIONS);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003544 llvm::Value *ThreadId = getThreadID(CGF, Loc);
James Y Knight9871db02019-02-05 16:42:33 +00003545 llvm::FunctionCallee StaticInitFunction =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003546 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003547 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003548 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003549}
John McCall7f416cc2015-09-08 08:05:57 +00003550
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003551void CGOpenMPRuntime::emitDistributeStaticInit(
3552 CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003553 OpenMPDistScheduleClauseKind SchedKind,
3554 const CGOpenMPRuntime::StaticRTInput &Values) {
3555 OpenMPSchedType ScheduleNum =
3556 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003557 llvm::Value *UpdatedLocation =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003558 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003559 llvm::Value *ThreadId = getThreadID(CGF, Loc);
James Y Knight9871db02019-02-05 16:42:33 +00003560 llvm::FunctionCallee StaticInitFunction =
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003561 createForStaticInitFunction(Values.IVSize, Values.IVSigned);
Alexey Bataev9ebd7422016-05-10 09:57:36 +00003562 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction,
3563 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003564 OMPC_SCHEDULE_MODIFIER_unknown, Values);
Alexander Musmanc6388682014-12-15 07:07:06 +00003565}
3566
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003567void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
Alexey Bataevf43f7142017-09-06 16:17:35 +00003568 SourceLocation Loc,
3569 OpenMPDirectiveKind DKind) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003570 if (!CGF.HaveInsertPoint())
3571 return;
Alexander Musmanc6388682014-12-15 07:07:06 +00003572 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Alexey Bataevf43f7142017-09-06 16:17:35 +00003573 llvm::Value *Args[] = {
3574 emitUpdateLocation(CGF, Loc,
3575 isOpenMPDistributeDirective(DKind)
3576 ? OMP_IDENT_WORK_DISTRIBUTE
3577 : isOpenMPLoopDirective(DKind)
3578 ? OMP_IDENT_WORK_LOOP
3579 : OMP_IDENT_WORK_SECTIONS),
3580 getThreadID(CGF, Loc)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003581 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini),
3582 Args);
Alexander Musmanc6388682014-12-15 07:07:06 +00003583}
3584
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00003585void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
3586 SourceLocation Loc,
3587 unsigned IVSize,
3588 bool IVSigned) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003589 if (!CGF.HaveInsertPoint())
3590 return;
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003591 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid);
Alexey Bataev50b3c952016-02-19 10:38:26 +00003592 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
Alexey Bataev98eb6e32015-04-22 11:15:40 +00003593 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args);
3594}
3595
Alexander Musman92bdaab2015-03-12 13:37:50 +00003596llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF,
3597 SourceLocation Loc, unsigned IVSize,
John McCall7f416cc2015-09-08 08:05:57 +00003598 bool IVSigned, Address IL,
3599 Address LB, Address UB,
3600 Address ST) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00003601 // Call __kmpc_dispatch_next(
3602 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter,
3603 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper,
3604 // kmp_int[32|64] *p_stride);
3605 llvm::Value *Args[] = {
Alexey Bataev50b3c952016-02-19 10:38:26 +00003606 emitUpdateLocation(CGF, Loc),
3607 getThreadID(CGF, Loc),
John McCall7f416cc2015-09-08 08:05:57 +00003608 IL.getPointer(), // &isLastIter
3609 LB.getPointer(), // &Lower
3610 UB.getPointer(), // &Upper
3611 ST.getPointer() // &Stride
Alexander Musman92bdaab2015-03-12 13:37:50 +00003612 };
3613 llvm::Value *Call =
3614 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args);
3615 return CGF.EmitScalarConversion(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003616 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00003617 CGF.getContext().BoolTy, Loc);
Alexander Musman92bdaab2015-03-12 13:37:50 +00003618}
3619
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003620void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
3621 llvm::Value *NumThreads,
3622 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003623 if (!CGF.HaveInsertPoint())
3624 return;
Alexey Bataevb2059782014-10-13 08:23:51 +00003625 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads)
3626 llvm::Value *Args[] = {
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003627 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
Alexey Bataevb2059782014-10-13 08:23:51 +00003628 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)};
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003629 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads),
3630 Args);
Alexey Bataevb2059782014-10-13 08:23:51 +00003631}
3632
Alexey Bataev7f210c62015-06-18 13:40:03 +00003633void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF,
3634 OpenMPProcBindClauseKind ProcBind,
3635 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003636 if (!CGF.HaveInsertPoint())
3637 return;
Alexey Bataev7f210c62015-06-18 13:40:03 +00003638 // Constants for proc bind value accepted by the runtime.
3639 enum ProcBindTy {
3640 ProcBindFalse = 0,
3641 ProcBindTrue,
3642 ProcBindMaster,
3643 ProcBindClose,
3644 ProcBindSpread,
3645 ProcBindIntel,
3646 ProcBindDefault
3647 } RuntimeProcBind;
3648 switch (ProcBind) {
3649 case OMPC_PROC_BIND_master:
3650 RuntimeProcBind = ProcBindMaster;
3651 break;
3652 case OMPC_PROC_BIND_close:
3653 RuntimeProcBind = ProcBindClose;
3654 break;
3655 case OMPC_PROC_BIND_spread:
3656 RuntimeProcBind = ProcBindSpread;
3657 break;
3658 case OMPC_PROC_BIND_unknown:
3659 llvm_unreachable("Unsupported proc_bind value.");
3660 }
3661 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind)
3662 llvm::Value *Args[] = {
3663 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
3664 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)};
3665 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args);
3666}
3667
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003668void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>,
3669 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00003670 if (!CGF.HaveInsertPoint())
3671 return;
Alexey Bataevd76df6d2015-02-24 12:55:09 +00003672 // Build call void __kmpc_flush(ident_t *loc)
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003673 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush),
3674 emitUpdateLocation(CGF, Loc));
Alexey Bataevcc37cc12014-11-20 04:34:54 +00003675}
Alexey Bataev3eff5f42015-02-25 08:32:46 +00003676
Alexey Bataev62b63b12015-03-10 07:28:44 +00003677namespace {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003678/// Indexes of fields for type kmp_task_t.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003679enum KmpTaskTFields {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003680 /// List of shared variables.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003681 KmpTaskTShareds,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003682 /// Task routine.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003683 KmpTaskTRoutine,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003684 /// Partition id for the untied tasks.
Alexey Bataev62b63b12015-03-10 07:28:44 +00003685 KmpTaskTPartId,
Alexey Bataevad537bb2016-05-30 09:06:50 +00003686 /// Function with call of destructors for private variables.
3687 Data1,
3688 /// Task priority.
3689 Data2,
Alexey Bataev7292c292016-04-25 12:22:29 +00003690 /// (Taskloops only) Lower bound.
3691 KmpTaskTLowerBound,
3692 /// (Taskloops only) Upper bound.
3693 KmpTaskTUpperBound,
3694 /// (Taskloops only) Stride.
3695 KmpTaskTStride,
3696 /// (Taskloops only) Is last iteration flag.
3697 KmpTaskTLastIter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003698 /// (Taskloops only) Reduction data.
3699 KmpTaskTReductions,
Alexey Bataev62b63b12015-03-10 07:28:44 +00003700};
Hans Wennborg7eb54642015-09-10 17:07:54 +00003701} // anonymous namespace
Alexey Bataev62b63b12015-03-10 07:28:44 +00003702
Samuel Antaoee8fb302016-01-06 13:42:12 +00003703bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003704 return OffloadEntriesTargetRegion.empty() &&
3705 OffloadEntriesDeviceGlobalVar.empty();
Samuel Antaoee8fb302016-01-06 13:42:12 +00003706}
3707
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003708/// Initialize target region entry.
Samuel Antaoee8fb302016-01-06 13:42:12 +00003709void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3710 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3711 StringRef ParentName, unsigned LineNum,
Samuel Antao2de62b02016-02-13 23:35:10 +00003712 unsigned Order) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003713 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
3714 "only required for the device "
3715 "code generation.");
Samuel Antao2de62b02016-02-13 23:35:10 +00003716 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] =
Samuel Antaof83efdb2017-01-05 16:02:49 +00003717 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003718 OMPTargetRegionEntryTargetRegion);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003719 ++OffloadingEntriesNum;
3720}
3721
3722void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3723 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID,
3724 StringRef ParentName, unsigned LineNum,
Samuel Antaof83efdb2017-01-05 16:02:49 +00003725 llvm::Constant *Addr, llvm::Constant *ID,
Alexey Bataev34f8a702018-03-28 14:28:54 +00003726 OMPTargetRegionEntryKind Flags) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003727 // If we are emitting code for a target, the entry is already initialized,
3728 // only has to be registered.
3729 if (CGM.getLangOpts().OpenMPIsDevice) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00003730 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) {
3731 unsigned DiagID = CGM.getDiags().getCustomDiagID(
3732 DiagnosticsEngine::Error,
3733 "Unable to find target region on line '%0' in the device code.");
3734 CGM.getDiags().Report(DiagID) << LineNum;
3735 return;
3736 }
Samuel Antao2de62b02016-02-13 23:35:10 +00003737 auto &Entry =
3738 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum];
Samuel Antaoee8fb302016-01-06 13:42:12 +00003739 assert(Entry.isValid() && "Entry not initialized!");
3740 Entry.setAddress(Addr);
3741 Entry.setID(ID);
Samuel Antaof83efdb2017-01-05 16:02:49 +00003742 Entry.setFlags(Flags);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003743 } else {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003744 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags);
Samuel Antao2de62b02016-02-13 23:35:10 +00003745 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00003746 ++OffloadingEntriesNum;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003747 }
3748}
3749
3750bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo(
Samuel Antao2de62b02016-02-13 23:35:10 +00003751 unsigned DeviceID, unsigned FileID, StringRef ParentName,
3752 unsigned LineNum) const {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003753 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID);
3754 if (PerDevice == OffloadEntriesTargetRegion.end())
3755 return false;
3756 auto PerFile = PerDevice->second.find(FileID);
3757 if (PerFile == PerDevice->second.end())
3758 return false;
3759 auto PerParentName = PerFile->second.find(ParentName);
3760 if (PerParentName == PerFile->second.end())
3761 return false;
3762 auto PerLine = PerParentName->second.find(LineNum);
3763 if (PerLine == PerParentName->second.end())
3764 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003765 // Fail if this entry is already registered.
Samuel Antao2de62b02016-02-13 23:35:10 +00003766 if (PerLine->second.getAddress() || PerLine->second.getID())
Samuel Antaoee8fb302016-01-06 13:42:12 +00003767 return false;
3768 return true;
3769}
3770
3771void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo(
3772 const OffloadTargetRegionEntryInfoActTy &Action) {
3773 // Scan all target region entries and perform the provided action.
Alexey Bataev03f270c2018-03-30 18:31:07 +00003774 for (const auto &D : OffloadEntriesTargetRegion)
3775 for (const auto &F : D.second)
3776 for (const auto &P : F.second)
3777 for (const auto &L : P.second)
Samuel Antao2de62b02016-02-13 23:35:10 +00003778 Action(D.first, F.first, P.first(), L.first, L.second);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003779}
3780
Alexey Bataev03f270c2018-03-30 18:31:07 +00003781void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3782 initializeDeviceGlobalVarEntryInfo(StringRef Name,
3783 OMPTargetGlobalVarEntryKind Flags,
3784 unsigned Order) {
3785 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is "
3786 "only required for the device "
3787 "code generation.");
3788 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags);
3789 ++OffloadingEntriesNum;
3790}
Samuel Antaoee8fb302016-01-06 13:42:12 +00003791
Alexey Bataev03f270c2018-03-30 18:31:07 +00003792void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3793 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr,
3794 CharUnits VarSize,
3795 OMPTargetGlobalVarEntryKind Flags,
3796 llvm::GlobalValue::LinkageTypes Linkage) {
3797 if (CGM.getLangOpts().OpenMPIsDevice) {
3798 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3799 assert(Entry.isValid() && Entry.getFlags() == Flags &&
3800 "Entry not initialized!");
3801 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
3802 "Resetting with the new address.");
Alexey Bataev8259cc32019-03-12 20:05:17 +00003803 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) {
3804 if (Entry.getVarSize().isZero()) {
3805 Entry.setVarSize(VarSize);
3806 Entry.setLinkage(Linkage);
3807 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003808 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00003809 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003810 Entry.setVarSize(VarSize);
3811 Entry.setLinkage(Linkage);
Alexey Bataev8259cc32019-03-12 20:05:17 +00003812 Entry.setAddress(Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00003813 } else {
Alexey Bataev8259cc32019-03-12 20:05:17 +00003814 if (hasDeviceGlobalVarEntryInfo(VarName)) {
3815 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName];
3816 assert(Entry.isValid() && Entry.getFlags() == Flags &&
3817 "Entry not initialized!");
3818 assert((!Entry.getAddress() || Entry.getAddress() == Addr) &&
3819 "Resetting with the new address.");
3820 if (Entry.getVarSize().isZero()) {
3821 Entry.setVarSize(VarSize);
3822 Entry.setLinkage(Linkage);
3823 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003824 return;
Alexey Bataev8259cc32019-03-12 20:05:17 +00003825 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00003826 OffloadEntriesDeviceGlobalVar.try_emplace(
3827 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage);
3828 ++OffloadingEntriesNum;
3829 }
3830}
3831
3832void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::
3833 actOnDeviceGlobalVarEntriesInfo(
3834 const OffloadDeviceGlobalVarEntryInfoActTy &Action) {
3835 // Scan all target region entries and perform the provided action.
3836 for (const auto &E : OffloadEntriesDeviceGlobalVar)
3837 Action(E.getKey(), E.getValue());
Samuel Antaoee8fb302016-01-06 13:42:12 +00003838}
3839
3840llvm::Function *
3841CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() {
Samuel Antaoee8fb302016-01-06 13:42:12 +00003842 // If we don't have entries or if we are emitting code for the device, we
3843 // don't need to do anything.
3844 if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty())
3845 return nullptr;
3846
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003847 llvm::Module &M = CGM.getModule();
3848 ASTContext &C = CGM.getContext();
Samuel Antaoee8fb302016-01-06 13:42:12 +00003849
3850 // Get list of devices we care about
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003851 const std::vector<llvm::Triple> &Devices = CGM.getLangOpts().OMPTargetTriples;
Samuel Antaoee8fb302016-01-06 13:42:12 +00003852
3853 // We should be creating an offloading descriptor only if there are devices
3854 // specified.
3855 assert(!Devices.empty() && "No OpenMP offloading devices??");
3856
3857 // Create the external variables that will point to the begin and end of the
3858 // host entries section. These will be defined by the linker.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003859 llvm::Type *OffloadEntryTy =
Samuel Antaoee8fb302016-01-06 13:42:12 +00003860 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy());
Alexey Bataev18fa2322018-05-02 14:20:50 +00003861 std::string EntriesBeginName = getName({"omp_offloading", "entries_begin"});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003862 auto *HostEntriesBegin = new llvm::GlobalVariable(
Samuel Antaoee8fb302016-01-06 13:42:12 +00003863 M, OffloadEntryTy, /*isConstant=*/true,
Eugene Zelenko1660a5d2016-01-26 19:01:06 +00003864 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr,
Alexey Bataev18fa2322018-05-02 14:20:50 +00003865 EntriesBeginName);
3866 std::string EntriesEndName = getName({"omp_offloading", "entries_end"});
3867 auto *HostEntriesEnd =
3868 new llvm::GlobalVariable(M, OffloadEntryTy, /*isConstant=*/true,
3869 llvm::GlobalValue::ExternalLinkage,
3870 /*Initializer=*/nullptr, EntriesEndName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003871
3872 // Create all device images
Samuel Antaoee8fb302016-01-06 13:42:12 +00003873 auto *DeviceImageTy = cast<llvm::StructType>(
3874 CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy()));
John McCall23c9dc62016-11-28 22:18:27 +00003875 ConstantInitBuilder DeviceImagesBuilder(CGM);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003876 ConstantArrayBuilder DeviceImagesEntries =
3877 DeviceImagesBuilder.beginArray(DeviceImageTy);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003878
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003879 for (const llvm::Triple &Device : Devices) {
Alexey Bataev03f270c2018-03-30 18:31:07 +00003880 StringRef T = Device.getTriple();
Alexey Bataev18fa2322018-05-02 14:20:50 +00003881 std::string BeginName = getName({"omp_offloading", "img_start", ""});
Samuel Antaoee8fb302016-01-06 13:42:12 +00003882 auto *ImgBegin = new llvm::GlobalVariable(
Alexey Bataev62a4cb02018-07-31 18:27:42 +00003883 M, CGM.Int8Ty, /*isConstant=*/true,
3884 llvm::GlobalValue::ExternalWeakLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00003885 /*Initializer=*/nullptr, Twine(BeginName).concat(T));
3886 std::string EndName = getName({"omp_offloading", "img_end", ""});
Samuel Antaoee8fb302016-01-06 13:42:12 +00003887 auto *ImgEnd = new llvm::GlobalVariable(
Alexey Bataev62a4cb02018-07-31 18:27:42 +00003888 M, CGM.Int8Ty, /*isConstant=*/true,
3889 llvm::GlobalValue::ExternalWeakLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00003890 /*Initializer=*/nullptr, Twine(EndName).concat(T));
Samuel Antaoee8fb302016-01-06 13:42:12 +00003891
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003892 llvm::Constant *Data[] = {ImgBegin, ImgEnd, HostEntriesBegin,
3893 HostEntriesEnd};
3894 createConstantGlobalStructAndAddToParent(CGM, getTgtDeviceImageQTy(), Data,
3895 DeviceImagesEntries);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003896 }
3897
3898 // Create device images global array.
Alexey Bataev18fa2322018-05-02 14:20:50 +00003899 std::string ImagesName = getName({"omp_offloading", "device_images"});
John McCall6c9f1fdb2016-11-19 08:17:24 +00003900 llvm::GlobalVariable *DeviceImages =
Alexey Bataev18fa2322018-05-02 14:20:50 +00003901 DeviceImagesEntries.finishAndCreateGlobal(ImagesName,
3902 CGM.getPointerAlign(),
3903 /*isConstant=*/true);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00003904 DeviceImages->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003905
3906 // This is a Zero array to be used in the creation of the constant expressions
3907 llvm::Constant *Index[] = {llvm::Constant::getNullValue(CGM.Int32Ty),
3908 llvm::Constant::getNullValue(CGM.Int32Ty)};
3909
3910 // Create the target region descriptor.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003911 llvm::Constant *Data[] = {
3912 llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()),
3913 llvm::ConstantExpr::getGetElementPtr(DeviceImages->getValueType(),
3914 DeviceImages, Index),
3915 HostEntriesBegin, HostEntriesEnd};
Alexey Bataev18fa2322018-05-02 14:20:50 +00003916 std::string Descriptor = getName({"omp_offloading", "descriptor"});
Mike Ricee1ca7b62018-08-29 15:45:11 +00003917 llvm::GlobalVariable *Desc = createGlobalStruct(
3918 CGM, getTgtBinaryDescriptorQTy(), /*IsConstant=*/true, Data, Descriptor);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003919
3920 // Emit code to register or unregister the descriptor at execution
3921 // startup or closing, respectively.
3922
Alexey Bataev03f270c2018-03-30 18:31:07 +00003923 llvm::Function *UnRegFn;
3924 {
3925 FunctionArgList Args;
3926 ImplicitParamDecl DummyPtr(C, C.VoidPtrTy, ImplicitParamDecl::Other);
3927 Args.push_back(&DummyPtr);
Samuel Antaoee8fb302016-01-06 13:42:12 +00003928
Alexey Bataev03f270c2018-03-30 18:31:07 +00003929 CodeGenFunction CGF(CGM);
3930 // Disable debug info for global (de-)initializer because they are not part
3931 // of some particular construct.
3932 CGF.disableDebugInfo();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003933 const auto &FI =
3934 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
3935 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Alexey Bataev18fa2322018-05-02 14:20:50 +00003936 std::string UnregName = getName({"omp_offloading", "descriptor_unreg"});
3937 UnRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, UnregName, FI);
Alexey Bataev03f270c2018-03-30 18:31:07 +00003938 CGF.StartFunction(GlobalDecl(), C.VoidTy, UnRegFn, FI, Args);
3939 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_unregister_lib),
3940 Desc);
3941 CGF.FinishFunction();
3942 }
3943 llvm::Function *RegFn;
3944 {
3945 CodeGenFunction CGF(CGM);
3946 // Disable debug info for global (de-)initializer because they are not part
3947 // of some particular construct.
3948 CGF.disableDebugInfo();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003949 const auto &FI = CGM.getTypes().arrangeNullaryFunction();
Alexey Bataev03f270c2018-03-30 18:31:07 +00003950 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI);
Sergey Dmitrievbde9cf92018-08-03 20:19:28 +00003951
3952 // Encode offload target triples into the registration function name. It
3953 // will serve as a comdat key for the registration/unregistration code for
3954 // this particular combination of offloading targets.
3955 SmallVector<StringRef, 4U> RegFnNameParts(Devices.size() + 2U);
3956 RegFnNameParts[0] = "omp_offloading";
3957 RegFnNameParts[1] = "descriptor_reg";
3958 llvm::transform(Devices, std::next(RegFnNameParts.begin(), 2),
3959 [](const llvm::Triple &T) -> const std::string& {
3960 return T.getTriple();
3961 });
3962 llvm::sort(std::next(RegFnNameParts.begin(), 2), RegFnNameParts.end());
3963 std::string Descriptor = getName(RegFnNameParts);
Alexey Bataev18fa2322018-05-02 14:20:50 +00003964 RegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, Descriptor, FI);
Alexey Bataev03f270c2018-03-30 18:31:07 +00003965 CGF.StartFunction(GlobalDecl(), C.VoidTy, RegFn, FI, FunctionArgList());
3966 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_lib), Desc);
3967 // Create a variable to drive the registration and unregistration of the
3968 // descriptor, so we can reuse the logic that emits Ctors and Dtors.
3969 ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(),
3970 SourceLocation(), nullptr, C.CharTy,
3971 ImplicitParamDecl::Other);
3972 CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc);
3973 CGF.FinishFunction();
3974 }
George Rokos29d0f002017-05-27 03:03:13 +00003975 if (CGM.supportsCOMDAT()) {
3976 // It is sufficient to call registration function only once, so create a
3977 // COMDAT group for registration/unregistration functions and associated
3978 // data. That would reduce startup time and code size. Registration
3979 // function serves as a COMDAT group key.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003980 llvm::Comdat *ComdatKey = M.getOrInsertComdat(RegFn->getName());
George Rokos29d0f002017-05-27 03:03:13 +00003981 RegFn->setLinkage(llvm::GlobalValue::LinkOnceAnyLinkage);
3982 RegFn->setVisibility(llvm::GlobalValue::HiddenVisibility);
3983 RegFn->setComdat(ComdatKey);
3984 UnRegFn->setComdat(ComdatKey);
3985 DeviceImages->setComdat(ComdatKey);
3986 Desc->setComdat(ComdatKey);
3987 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00003988 return RegFn;
3989}
3990
Alexey Bataev03f270c2018-03-30 18:31:07 +00003991void CGOpenMPRuntime::createOffloadEntry(
3992 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags,
3993 llvm::GlobalValue::LinkageTypes Linkage) {
Samuel Antao2de62b02016-02-13 23:35:10 +00003994 StringRef Name = Addr->getName();
Samuel Antaoee8fb302016-01-06 13:42:12 +00003995 llvm::Module &M = CGM.getModule();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00003996 llvm::LLVMContext &C = M.getContext();
Samuel Antaoee8fb302016-01-06 13:42:12 +00003997
3998 // Create constant string with the name.
3999 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name);
4000
Alexey Bataev18fa2322018-05-02 14:20:50 +00004001 std::string StringName = getName({"omp_offloading", "entry_name"});
4002 auto *Str = new llvm::GlobalVariable(
4003 M, StrPtrInit->getType(), /*isConstant=*/true,
4004 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00004005 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004006
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004007 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy),
4008 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy),
4009 llvm::ConstantInt::get(CGM.SizeTy, Size),
4010 llvm::ConstantInt::get(CGM.Int32Ty, Flags),
4011 llvm::ConstantInt::get(CGM.Int32Ty, 0)};
Alexey Bataev18fa2322018-05-02 14:20:50 +00004012 std::string EntryName = getName({"omp_offloading", "entry", ""});
Mike Ricee1ca7b62018-08-29 15:45:11 +00004013 llvm::GlobalVariable *Entry = createGlobalStruct(
4014 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data,
4015 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004016
4017 // The entry has to be created in the section the linker expects it to be.
Alexey Bataev18fa2322018-05-02 14:20:50 +00004018 std::string Section = getName({"omp_offloading", "entries"});
4019 Entry->setSection(Section);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004020}
4021
4022void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {
4023 // Emit the offloading entries and metadata so that the device codegen side
Samuel Antao4c8035b2016-12-12 18:00:20 +00004024 // can easily figure out what to emit. The produced metadata looks like
4025 // this:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004026 //
4027 // !omp_offload.info = !{!1, ...}
4028 //
4029 // Right now we only generate metadata for function that contain target
4030 // regions.
4031
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00004032 // If we do not have entries, we don't need to do anything.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004033 if (OffloadEntriesInfoManager.empty())
4034 return;
4035
4036 llvm::Module &M = CGM.getModule();
4037 llvm::LLVMContext &C = M.getContext();
Alexey Bataev03f270c2018-03-30 18:31:07 +00004038 SmallVector<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16>
Samuel Antaoee8fb302016-01-06 13:42:12 +00004039 OrderedEntries(OffloadEntriesInfoManager.size());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004040 llvm::SmallVector<StringRef, 16> ParentFunctions(
4041 OffloadEntriesInfoManager.size());
Samuel Antaoee8fb302016-01-06 13:42:12 +00004042
Simon Pilgrim2c518802017-03-30 14:13:19 +00004043 // Auxiliary methods to create metadata values and strings.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004044 auto &&GetMDInt = [this](unsigned V) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004045 return llvm::ConstantAsMetadata::get(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004046 llvm::ConstantInt::get(CGM.Int32Ty, V));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004047 };
4048
Alexey Bataev03f270c2018-03-30 18:31:07 +00004049 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); };
4050
4051 // Create the offloading info metadata node.
4052 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004053
4054 // Create function that emits metadata for each target region entry;
Alexey Bataev03f270c2018-03-30 18:31:07 +00004055 auto &&TargetRegionMetadataEmitter =
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004056 [&C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, &GetMDString](
Alexey Bataev03f270c2018-03-30 18:31:07 +00004057 unsigned DeviceID, unsigned FileID, StringRef ParentName,
4058 unsigned Line,
4059 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) {
4060 // Generate metadata for target regions. Each entry of this metadata
4061 // contains:
4062 // - Entry 0 -> Kind of this type of metadata (0).
4063 // - Entry 1 -> Device ID of the file where the entry was identified.
4064 // - Entry 2 -> File ID of the file where the entry was identified.
4065 // - Entry 3 -> Mangled name of the function where the entry was
4066 // identified.
4067 // - Entry 4 -> Line in the file where the entry was identified.
4068 // - Entry 5 -> Order the entry was created.
4069 // The first element of the metadata node is the kind.
4070 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID),
4071 GetMDInt(FileID), GetMDString(ParentName),
4072 GetMDInt(Line), GetMDInt(E.getOrder())};
Samuel Antaoee8fb302016-01-06 13:42:12 +00004073
Alexey Bataev03f270c2018-03-30 18:31:07 +00004074 // Save this entry in the right position of the ordered entries array.
4075 OrderedEntries[E.getOrder()] = &E;
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004076 ParentFunctions[E.getOrder()] = ParentName;
Samuel Antaoee8fb302016-01-06 13:42:12 +00004077
Alexey Bataev03f270c2018-03-30 18:31:07 +00004078 // Add metadata to the named metadata node.
4079 MD->addOperand(llvm::MDNode::get(C, Ops));
4080 };
Samuel Antaoee8fb302016-01-06 13:42:12 +00004081
4082 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo(
4083 TargetRegionMetadataEmitter);
4084
Alexey Bataev03f270c2018-03-30 18:31:07 +00004085 // Create function that emits metadata for each device global variable entry;
4086 auto &&DeviceGlobalVarMetadataEmitter =
4087 [&C, &OrderedEntries, &GetMDInt, &GetMDString,
4088 MD](StringRef MangledName,
4089 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar
4090 &E) {
4091 // Generate metadata for global variables. Each entry of this metadata
4092 // contains:
4093 // - Entry 0 -> Kind of this type of metadata (1).
4094 // - Entry 1 -> Mangled name of the variable.
4095 // - Entry 2 -> Declare target kind.
4096 // - Entry 3 -> Order the entry was created.
4097 // The first element of the metadata node is the kind.
4098 llvm::Metadata *Ops[] = {
4099 GetMDInt(E.getKind()), GetMDString(MangledName),
4100 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())};
4101
4102 // Save this entry in the right position of the ordered entries array.
4103 OrderedEntries[E.getOrder()] = &E;
4104
4105 // Add metadata to the named metadata node.
4106 MD->addOperand(llvm::MDNode::get(C, Ops));
4107 };
4108
4109 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo(
4110 DeviceGlobalVarMetadataEmitter);
4111
4112 for (const auto *E : OrderedEntries) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004113 assert(E && "All ordered entries must exist!");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004114 if (const auto *CE =
Samuel Antaoee8fb302016-01-06 13:42:12 +00004115 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>(
4116 E)) {
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004117 if (!CE->getID() || !CE->getAddress()) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00004118 // Do not blame the entry if the parent funtion is not emitted.
4119 StringRef FnName = ParentFunctions[CE->getOrder()];
4120 if (!CGM.GetGlobalValue(FnName))
4121 continue;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004122 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4123 DiagnosticsEngine::Error,
Alexey Bataev7f01d202018-07-16 18:12:18 +00004124 "Offloading entry for target region is incorrect: either the "
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004125 "address or the ID is invalid.");
4126 CGM.getDiags().Report(DiagID);
4127 continue;
4128 }
Alexey Bataev34f8a702018-03-28 14:28:54 +00004129 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004130 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage);
4131 } else if (const auto *CE =
4132 dyn_cast<OffloadEntriesInfoManagerTy::
4133 OffloadEntryInfoDeviceGlobalVar>(E)) {
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004134 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags =
4135 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4136 CE->getFlags());
4137 switch (Flags) {
4138 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: {
4139 if (!CE->getAddress()) {
4140 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4141 DiagnosticsEngine::Error,
4142 "Offloading entry for declare target variable is incorrect: the "
4143 "address is invalid.");
4144 CGM.getDiags().Report(DiagID);
4145 continue;
4146 }
Alexey Bataevb4dd6d22018-08-29 20:41:37 +00004147 // The vaiable has no definition - no need to add the entry.
4148 if (CE->getVarSize().isZero())
4149 continue;
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004150 break;
4151 }
4152 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink:
4153 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) ||
4154 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) &&
4155 "Declaret target link address is set.");
4156 if (CGM.getLangOpts().OpenMPIsDevice)
4157 continue;
4158 if (!CE->getAddress()) {
4159 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4160 DiagnosticsEngine::Error,
4161 "Offloading entry for declare target variable is incorrect: the "
4162 "address is invalid.");
4163 CGM.getDiags().Report(DiagID);
4164 continue;
4165 }
4166 break;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004167 }
Alexey Bataev03f270c2018-03-30 18:31:07 +00004168 createOffloadEntry(CE->getAddress(), CE->getAddress(),
Alexey Bataevc52f01d2018-07-16 20:05:25 +00004169 CE->getVarSize().getQuantity(), Flags,
Alexey Bataev03f270c2018-03-30 18:31:07 +00004170 CE->getLinkage());
4171 } else {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004172 llvm_unreachable("Unsupported entry kind.");
Alexey Bataev03f270c2018-03-30 18:31:07 +00004173 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004174 }
4175}
4176
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004177/// Loads all the offload entries information from the host IR
Samuel Antaoee8fb302016-01-06 13:42:12 +00004178/// metadata.
4179void CGOpenMPRuntime::loadOffloadInfoMetadata() {
4180 // If we are in target mode, load the metadata from the host IR. This code has
4181 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata().
4182
4183 if (!CGM.getLangOpts().OpenMPIsDevice)
4184 return;
4185
4186 if (CGM.getLangOpts().OMPHostIRFile.empty())
4187 return;
4188
4189 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile);
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004190 if (auto EC = Buf.getError()) {
4191 CGM.getDiags().Report(diag::err_cannot_open_file)
4192 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004193 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004194 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004195
4196 llvm::LLVMContext C;
Peter Collingbourned9445c42016-11-13 07:00:17 +00004197 auto ME = expectedToErrorOrAndEmitErrors(
4198 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004199
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004200 if (auto EC = ME.getError()) {
4201 unsigned DiagID = CGM.getDiags().getCustomDiagID(
4202 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'");
4203 CGM.getDiags().Report(DiagID)
4204 << CGM.getLangOpts().OMPHostIRFile << EC.message();
Samuel Antaoee8fb302016-01-06 13:42:12 +00004205 return;
Alexey Bataev64e62dc2018-04-30 16:26:57 +00004206 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00004207
4208 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info");
4209 if (!MD)
4210 return;
4211
George Burgess IV00f70bd2018-03-01 05:43:23 +00004212 for (llvm::MDNode *MN : MD->operands()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004213 auto &&GetMDInt = [MN](unsigned Idx) {
4214 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004215 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue();
4216 };
4217
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004218 auto &&GetMDString = [MN](unsigned Idx) {
4219 auto *V = cast<llvm::MDString>(MN->getOperand(Idx));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004220 return V->getString();
4221 };
4222
Alexey Bataev03f270c2018-03-30 18:31:07 +00004223 switch (GetMDInt(0)) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004224 default:
4225 llvm_unreachable("Unexpected metadata!");
4226 break;
4227 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
Alexey Bataev34f8a702018-03-28 14:28:54 +00004228 OffloadingEntryInfoTargetRegion:
Samuel Antaoee8fb302016-01-06 13:42:12 +00004229 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo(
Alexey Bataev03f270c2018-03-30 18:31:07 +00004230 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2),
4231 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4),
4232 /*Order=*/GetMDInt(5));
4233 break;
4234 case OffloadEntriesInfoManagerTy::OffloadEntryInfo::
4235 OffloadingEntryInfoDeviceGlobalVar:
4236 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo(
4237 /*MangledName=*/GetMDString(1),
4238 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>(
4239 /*Flags=*/GetMDInt(2)),
4240 /*Order=*/GetMDInt(3));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004241 break;
4242 }
4243 }
4244}
4245
Alexey Bataev62b63b12015-03-10 07:28:44 +00004246void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) {
4247 if (!KmpRoutineEntryPtrTy) {
4248 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004249 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004250 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy};
4251 FunctionProtoType::ExtProtoInfo EPI;
4252 KmpRoutineEntryPtrQTy = C.getPointerType(
4253 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI));
4254 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy);
4255 }
4256}
4257
Samuel Antaoee8fb302016-01-06 13:42:12 +00004258QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() {
Samuel Antaoee8fb302016-01-06 13:42:12 +00004259 // Make sure the type of the entry is already created. This is the type we
4260 // have to create:
4261 // struct __tgt_offload_entry{
4262 // void *addr; // Pointer to the offload entry info.
4263 // // (function or global)
4264 // char *name; // Name of the function or global.
4265 // size_t size; // Size of the entry info (0 if it a function).
Samuel Antaof83efdb2017-01-05 16:02:49 +00004266 // int32_t flags; // Flags associated with the entry, e.g. 'link'.
4267 // int32_t reserved; // Reserved, to use by the runtime library.
Samuel Antaoee8fb302016-01-06 13:42:12 +00004268 // };
4269 if (TgtOffloadEntryQTy.isNull()) {
4270 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004271 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004272 RD->startDefinition();
4273 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4274 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy));
4275 addFieldToRecordDecl(C, RD, C.getSizeType());
Samuel Antaof83efdb2017-01-05 16:02:49 +00004276 addFieldToRecordDecl(
4277 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4278 addFieldToRecordDecl(
4279 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004280 RD->completeDefinition();
Jonas Hahnfeld5e4df282018-01-18 15:38:03 +00004281 RD->addAttr(PackedAttr::CreateImplicit(C));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004282 TgtOffloadEntryQTy = C.getRecordType(RD);
4283 }
4284 return TgtOffloadEntryQTy;
4285}
4286
4287QualType CGOpenMPRuntime::getTgtDeviceImageQTy() {
4288 // These are the types we need to build:
4289 // struct __tgt_device_image{
4290 // void *ImageStart; // Pointer to the target code start.
4291 // void *ImageEnd; // Pointer to the target code end.
4292 // // We also add the host entries to the device image, as it may be useful
4293 // // for the target runtime to have access to that information.
4294 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all
4295 // // the entries.
4296 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
4297 // // entries (non inclusive).
4298 // };
4299 if (TgtDeviceImageQTy.isNull()) {
4300 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004301 RecordDecl *RD = C.buildImplicitRecord("__tgt_device_image");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004302 RD->startDefinition();
4303 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4304 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4305 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4306 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4307 RD->completeDefinition();
4308 TgtDeviceImageQTy = C.getRecordType(RD);
4309 }
4310 return TgtDeviceImageQTy;
4311}
4312
4313QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() {
4314 // struct __tgt_bin_desc{
4315 // int32_t NumDevices; // Number of devices supported.
4316 // __tgt_device_image *DeviceImages; // Arrays of device images
4317 // // (one per device).
4318 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the
4319 // // entries.
4320 // __tgt_offload_entry *EntriesEnd; // End of the table with all the
4321 // // entries (non inclusive).
4322 // };
4323 if (TgtBinaryDescriptorQTy.isNull()) {
4324 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004325 RecordDecl *RD = C.buildImplicitRecord("__tgt_bin_desc");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004326 RD->startDefinition();
4327 addFieldToRecordDecl(
4328 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true));
4329 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy()));
4330 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4331 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy()));
4332 RD->completeDefinition();
4333 TgtBinaryDescriptorQTy = C.getRecordType(RD);
4334 }
4335 return TgtBinaryDescriptorQTy;
4336}
4337
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004338namespace {
Alexey Bataev9e034042015-05-05 04:05:12 +00004339struct PrivateHelpersTy {
4340 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy,
4341 const VarDecl *PrivateElemInit)
4342 : Original(Original), PrivateCopy(PrivateCopy),
4343 PrivateElemInit(PrivateElemInit) {}
4344 const VarDecl *Original;
4345 const VarDecl *PrivateCopy;
4346 const VarDecl *PrivateElemInit;
4347};
4348typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy;
Hans Wennborg7eb54642015-09-10 17:07:54 +00004349} // anonymous namespace
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004350
Alexey Bataev9e034042015-05-05 04:05:12 +00004351static RecordDecl *
Craig Topper8674c5c2015-09-29 04:30:07 +00004352createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) {
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004353 if (!Privates.empty()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004354 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004355 // Build struct .kmp_privates_t. {
4356 // /* private vars */
4357 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004358 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t");
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004359 RD->startDefinition();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004360 for (const auto &Pair : Privates) {
4361 const VarDecl *VD = Pair.second.Original;
4362 QualType Type = VD->getType().getNonReferenceType();
4363 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type);
Alexey Bataevc71a4092015-09-11 10:29:41 +00004364 if (VD->hasAttrs()) {
4365 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()),
4366 E(VD->getAttrs().end());
4367 I != E; ++I)
4368 FD->addAttr(*I);
4369 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004370 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004371 RD->completeDefinition();
4372 return RD;
4373 }
4374 return nullptr;
4375}
4376
Alexey Bataev9e034042015-05-05 04:05:12 +00004377static RecordDecl *
Alexey Bataev7292c292016-04-25 12:22:29 +00004378createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind,
4379 QualType KmpInt32Ty,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004380 QualType KmpRoutineEntryPointerQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004381 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004382 // Build struct kmp_task_t {
4383 // void * shareds;
4384 // kmp_routine_entry_t routine;
4385 // kmp_int32 part_id;
Alexey Bataevad537bb2016-05-30 09:06:50 +00004386 // kmp_cmplrdata_t data1;
4387 // kmp_cmplrdata_t data2;
Alexey Bataev7292c292016-04-25 12:22:29 +00004388 // For taskloops additional fields:
4389 // kmp_uint64 lb;
4390 // kmp_uint64 ub;
4391 // kmp_int64 st;
4392 // kmp_int32 liter;
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004393 // void * reductions;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004394 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004395 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004396 UD->startDefinition();
4397 addFieldToRecordDecl(C, UD, KmpInt32Ty);
4398 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy);
4399 UD->completeDefinition();
4400 QualType KmpCmplrdataTy = C.getRecordType(UD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004401 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t");
Alexey Bataev62b63b12015-03-10 07:28:44 +00004402 RD->startDefinition();
4403 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
4404 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy);
4405 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevad537bb2016-05-30 09:06:50 +00004406 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
4407 addFieldToRecordDecl(C, RD, KmpCmplrdataTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004408 if (isOpenMPTaskLoopDirective(Kind)) {
4409 QualType KmpUInt64Ty =
4410 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0);
4411 QualType KmpInt64Ty =
4412 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
4413 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4414 addFieldToRecordDecl(C, RD, KmpUInt64Ty);
4415 addFieldToRecordDecl(C, RD, KmpInt64Ty);
4416 addFieldToRecordDecl(C, RD, KmpInt32Ty);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004417 addFieldToRecordDecl(C, RD, C.VoidPtrTy);
Alexey Bataev7292c292016-04-25 12:22:29 +00004418 }
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004419 RD->completeDefinition();
4420 return RD;
4421}
4422
4423static RecordDecl *
4424createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004425 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004426 ASTContext &C = CGM.getContext();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004427 // Build struct kmp_task_t_with_privates {
4428 // kmp_task_t task_data;
4429 // .kmp_privates_t. privates;
4430 // };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004431 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates");
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004432 RD->startDefinition();
4433 addFieldToRecordDecl(C, RD, KmpTaskTQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004434 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates))
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004435 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004436 RD->completeDefinition();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004437 return RD;
Alexey Bataev62b63b12015-03-10 07:28:44 +00004438}
4439
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004440/// Emit a proxy function which accepts kmp_task_t as the second
Alexey Bataev62b63b12015-03-10 07:28:44 +00004441/// argument.
4442/// \code
4443/// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00004444/// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt,
Alexey Bataev7292c292016-04-25 12:22:29 +00004445/// For taskloops:
4446/// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004447/// tt->reductions, tt->shareds);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004448/// return 0;
4449/// }
4450/// \endcode
James Y Knight9871db02019-02-05 16:42:33 +00004451static llvm::Function *
Alexey Bataev62b63b12015-03-10 07:28:44 +00004452emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc,
Alexey Bataev7292c292016-04-25 12:22:29 +00004453 OpenMPDirectiveKind Kind, QualType KmpInt32Ty,
4454 QualType KmpTaskTWithPrivatesPtrQTy,
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004455 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy,
James Y Knight9871db02019-02-05 16:42:33 +00004456 QualType SharedsPtrTy, llvm::Function *TaskFunction,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004457 llvm::Value *TaskPrivatesMap) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004458 ASTContext &C = CGM.getContext();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004459 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004460 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4461 ImplicitParamDecl::Other);
4462 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4463 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4464 ImplicitParamDecl::Other);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004465 Args.push_back(&GtidArg);
4466 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004467 const auto &TaskEntryFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004468 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004469 llvm::FunctionType *TaskEntryTy =
4470 CGM.getTypes().GetFunctionType(TaskEntryFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004471 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""});
4472 auto *TaskEntry = llvm::Function::Create(
4473 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004474 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004475 TaskEntry->setDoesNotRecurse();
Alexey Bataev62b63b12015-03-10 07:28:44 +00004476 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004477 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args,
4478 Loc, Loc);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004479
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004480 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map,
Alexey Bataev7292c292016-04-25 12:22:29 +00004481 // tt,
4482 // For taskloops:
4483 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter,
4484 // tt->task_data.shareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004485 llvm::Value *GtidParam = CGF.EmitLoadOfScalar(
John McCall7f416cc2015-09-08 08:05:57 +00004486 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc);
Alexey Bataev31300ed2016-02-04 11:27:03 +00004487 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4488 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4489 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004490 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004491 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004492 LValue Base =
4493 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004494 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004495 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004496 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI);
4497 llvm::Value *PartidParam = PartIdLVal.getPointer();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004498
4499 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004500 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI);
4501 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Alexey Bataev1e491372018-01-23 18:44:14 +00004502 CGF.EmitLoadOfScalar(SharedsLVal, Loc),
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004503 CGF.ConvertTypeForMem(SharedsPtrTy));
4504
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004505 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4506 llvm::Value *PrivatesParam;
4507 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004508 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004509 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00004510 PrivatesLVal.getPointer(), CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004511 } else {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004512 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004513 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004514
Alexey Bataev7292c292016-04-25 12:22:29 +00004515 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam,
4516 TaskPrivatesMap,
4517 CGF.Builder
4518 .CreatePointerBitCastOrAddrSpaceCast(
4519 TDBase.getAddress(), CGF.VoidPtrTy)
4520 .getPointer()};
4521 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs),
4522 std::end(CommonArgs));
4523 if (isOpenMPTaskLoopDirective(Kind)) {
4524 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004525 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI);
4526 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004527 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004528 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI);
4529 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004530 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004531 LValue StLVal = CGF.EmitLValueForField(Base, *StFI);
4532 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004533 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004534 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4535 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004536 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004537 LValue RLVal = CGF.EmitLValueForField(Base, *RFI);
4538 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc);
Alexey Bataev7292c292016-04-25 12:22:29 +00004539 CallArgs.push_back(LBParam);
4540 CallArgs.push_back(UBParam);
4541 CallArgs.push_back(StParam);
4542 CallArgs.push_back(LIParam);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00004543 CallArgs.push_back(RParam);
Alexey Bataev7292c292016-04-25 12:22:29 +00004544 }
4545 CallArgs.push_back(SharedsParam);
4546
Alexey Bataev3c595a62017-08-14 15:01:03 +00004547 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction,
4548 CallArgs);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004549 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)),
4550 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty));
Alexey Bataev62b63b12015-03-10 07:28:44 +00004551 CGF.FinishFunction();
4552 return TaskEntry;
4553}
4554
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004555static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM,
4556 SourceLocation Loc,
4557 QualType KmpInt32Ty,
4558 QualType KmpTaskTWithPrivatesPtrQTy,
4559 QualType KmpTaskTWithPrivatesQTy) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004560 ASTContext &C = CGM.getContext();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004561 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004562 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty,
4563 ImplicitParamDecl::Other);
4564 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4565 KmpTaskTWithPrivatesPtrQTy.withRestrict(),
4566 ImplicitParamDecl::Other);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004567 Args.push_back(&GtidArg);
4568 Args.push_back(&TaskTypeArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004569 const auto &DestructorFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004570 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004571 llvm::FunctionType *DestructorFnTy =
4572 CGM.getTypes().GetFunctionType(DestructorFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004573 std::string Name =
4574 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""});
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004575 auto *DestructorFn =
4576 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00004577 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004578 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004579 DestructorFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004580 DestructorFn->setDoesNotRecurse();
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004581 CodeGenFunction CGF(CGM);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004582 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004583 Args, Loc, Loc);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004584
Alexey Bataev31300ed2016-02-04 11:27:03 +00004585 LValue Base = CGF.EmitLoadOfPointerLValue(
4586 CGF.GetAddrOfLocalVar(&TaskTypeArg),
4587 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004588 const auto *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004589 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl());
4590 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004591 Base = CGF.EmitLValueForField(Base, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004592 for (const auto *Field :
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004593 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004594 if (QualType::DestructionKind DtorKind =
4595 Field->getType().isDestructedType()) {
4596 LValue FieldLValue = CGF.EmitLValueForField(Base, Field);
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004597 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType());
4598 }
4599 }
4600 CGF.FinishFunction();
4601 return DestructorFn;
4602}
4603
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004604/// Emit a privates mapping function for correct handling of private and
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004605/// firstprivate variables.
4606/// \code
4607/// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1>
4608/// **noalias priv1,..., <tyn> **noalias privn) {
4609/// *priv1 = &.privates.priv1;
4610/// ...;
4611/// *privn = &.privates.privn;
4612/// }
4613/// \endcode
4614static llvm::Value *
4615emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc,
Craig Topper8674c5c2015-09-29 04:30:07 +00004616 ArrayRef<const Expr *> PrivateVars,
4617 ArrayRef<const Expr *> FirstprivateVars,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004618 ArrayRef<const Expr *> LastprivateVars,
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004619 QualType PrivatesQTy,
Craig Topper8674c5c2015-09-29 04:30:07 +00004620 ArrayRef<PrivateDataTy> Privates) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004621 ASTContext &C = CGM.getContext();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004622 FunctionArgList Args;
4623 ImplicitParamDecl TaskPrivatesArg(
4624 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
Alexey Bataev56223232017-06-09 13:40:18 +00004625 C.getPointerType(PrivatesQTy).withConst().withRestrict(),
4626 ImplicitParamDecl::Other);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004627 Args.push_back(&TaskPrivatesArg);
4628 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos;
4629 unsigned Counter = 1;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004630 for (const Expr *E : PrivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004631 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004632 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4633 C.getPointerType(C.getPointerType(E->getType()))
4634 .withConst()
4635 .withRestrict(),
4636 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004637 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004638 PrivateVarsPos[VD] = Counter;
4639 ++Counter;
4640 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004641 for (const Expr *E : FirstprivateVars) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004642 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004643 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4644 C.getPointerType(C.getPointerType(E->getType()))
4645 .withConst()
4646 .withRestrict(),
4647 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004648 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004649 PrivateVarsPos[VD] = Counter;
4650 ++Counter;
4651 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004652 for (const Expr *E : LastprivateVars) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004653 Args.push_back(ImplicitParamDecl::Create(
Alexey Bataev56223232017-06-09 13:40:18 +00004654 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4655 C.getPointerType(C.getPointerType(E->getType()))
4656 .withConst()
4657 .withRestrict(),
4658 ImplicitParamDecl::Other));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004659 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataevf93095a2016-05-05 08:46:22 +00004660 PrivateVarsPos[VD] = Counter;
4661 ++Counter;
4662 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004663 const auto &TaskPrivatesMapFnInfo =
John McCallc56a8b32016-03-11 04:30:31 +00004664 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004665 llvm::FunctionType *TaskPrivatesMapTy =
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004666 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004667 std::string Name =
4668 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""});
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004669 auto *TaskPrivatesMap = llvm::Function::Create(
Alexey Bataev18fa2322018-05-02 14:20:50 +00004670 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name,
4671 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004672 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap,
Akira Hatanaka44a59f82015-10-28 02:30:47 +00004673 TaskPrivatesMapFnInfo);
Chandler Carruthfcd33142016-12-23 01:24:49 +00004674 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline);
Mehdi Amini6aa9e9b2017-05-29 05:38:20 +00004675 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone);
Evgeniy Stepanov6b2a61d2015-09-14 21:35:16 +00004676 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004677 CodeGenFunction CGF(CGM);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004678 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap,
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004679 TaskPrivatesMapFnInfo, Args, Loc, Loc);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004680
4681 // *privi = &.privates.privi;
Alexey Bataev31300ed2016-02-04 11:27:03 +00004682 LValue Base = CGF.EmitLoadOfPointerLValue(
4683 CGF.GetAddrOfLocalVar(&TaskPrivatesArg),
4684 TaskPrivatesArg.getType()->castAs<PointerType>());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004685 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004686 Counter = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004687 for (const FieldDecl *Field : PrivatesQTyRD->fields()) {
4688 LValue FieldLVal = CGF.EmitLValueForField(Base, Field);
4689 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]];
4690 LValue RefLVal =
4691 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType());
4692 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue(
Alexey Bataev31300ed2016-02-04 11:27:03 +00004693 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>());
Alexey Bataev2377fe92015-09-10 08:12:02 +00004694 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004695 ++Counter;
4696 }
4697 CGF.FinishFunction();
4698 return TaskPrivatesMap;
4699}
4700
Alexey Bataevf93095a2016-05-05 08:46:22 +00004701/// Emit initialization for private variables in task-based directives.
Alexey Bataev8a831592016-05-10 10:36:51 +00004702static void emitPrivatesInit(CodeGenFunction &CGF,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004703 const OMPExecutableDirective &D,
4704 Address KmpTaskSharedsPtr, LValue TDBase,
4705 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4706 QualType SharedsTy, QualType SharedsPtrTy,
4707 const OMPTaskDataTy &Data,
4708 ArrayRef<PrivateDataTy> Privates, bool ForDup) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004709 ASTContext &C = CGF.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004710 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
4711 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004712 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind())
4713 ? OMPD_taskloop
4714 : OMPD_task;
4715 const CapturedStmt &CS = *D.getCapturedStmt(Kind);
4716 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004717 LValue SrcBase;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004718 bool IsTargetTask =
4719 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) ||
4720 isOpenMPTargetExecutionDirective(D.getDirectiveKind());
4721 // For target-based directives skip 3 firstprivate arrays BasePointersArray,
4722 // PointersArray and SizesArray. The original variables for these arrays are
4723 // not captured and we get their addresses explicitly.
4724 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) ||
Alexey Bataev8451efa2018-01-15 19:06:12 +00004725 (IsTargetTask && KmpTaskSharedsPtr.isValid())) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004726 SrcBase = CGF.MakeAddrLValue(
4727 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4728 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
4729 SharedsTy);
4730 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004731 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004732 for (const PrivateDataTy &Pair : Privates) {
4733 const VarDecl *VD = Pair.second.PrivateCopy;
4734 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004735 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) &&
4736 !CGF.isTrivialInitializer(Init)))) {
Alexey Bataev8a831592016-05-10 10:36:51 +00004737 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004738 if (const VarDecl *Elem = Pair.second.PrivateElemInit) {
4739 const VarDecl *OriginalVD = Pair.second.Original;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004740 // Check if the variable is the target-based BasePointersArray,
4741 // PointersArray or SizesArray.
4742 LValue SharedRefLValue;
Alexey Bataevab41ea62019-03-13 20:46:28 +00004743 QualType Type = PrivateLValue.getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004744 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004745 if (IsTargetTask && !SharedField) {
4746 assert(isa<ImplicitParamDecl>(OriginalVD) &&
4747 isa<CapturedDecl>(OriginalVD->getDeclContext()) &&
4748 cast<CapturedDecl>(OriginalVD->getDeclContext())
4749 ->getNumParams() == 0 &&
4750 isa<TranslationUnitDecl>(
4751 cast<CapturedDecl>(OriginalVD->getDeclContext())
4752 ->getDeclContext()) &&
4753 "Expected artificial target data variable.");
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004754 SharedRefLValue =
4755 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type);
4756 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004757 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField);
4758 SharedRefLValue = CGF.MakeAddrLValue(
4759 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
4760 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl),
4761 SharedRefLValue.getTBAAInfo());
4762 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004763 if (Type->isArrayType()) {
4764 // Initialize firstprivate array.
4765 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) {
4766 // Perform simple memcpy.
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00004767 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004768 } else {
4769 // Initialize firstprivate array using element-by-element
Simon Pilgrim2c518802017-03-30 14:13:19 +00004770 // initialization.
Alexey Bataevf93095a2016-05-05 08:46:22 +00004771 CGF.EmitOMPAggregateAssign(
4772 PrivateLValue.getAddress(), SharedRefLValue.getAddress(), Type,
4773 [&CGF, Elem, Init, &CapturesInfo](Address DestElement,
4774 Address SrcElement) {
4775 // Clean up any temporaries needed by the initialization.
4776 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4777 InitScope.addPrivate(
4778 Elem, [SrcElement]() -> Address { return SrcElement; });
4779 (void)InitScope.Privatize();
4780 // Emit initialization for single element.
4781 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
4782 CGF, &CapturesInfo);
4783 CGF.EmitAnyExprToMem(Init, DestElement,
4784 Init->getType().getQualifiers(),
4785 /*IsInitializer=*/false);
4786 });
4787 }
4788 } else {
4789 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4790 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
4791 return SharedRefLValue.getAddress();
4792 });
4793 (void)InitScope.Privatize();
4794 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
4795 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
4796 /*capturedByInit=*/false);
4797 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004798 } else {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004799 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004800 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004801 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004802 ++FI;
4803 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004804}
4805
4806/// Check if duplication function is required for taskloops.
4807static bool checkInitIsRequired(CodeGenFunction &CGF,
4808 ArrayRef<PrivateDataTy> Privates) {
4809 bool InitRequired = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004810 for (const PrivateDataTy &Pair : Privates) {
4811 const VarDecl *VD = Pair.second.PrivateCopy;
4812 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004813 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) &&
4814 !CGF.isTrivialInitializer(Init));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004815 if (InitRequired)
4816 break;
Alexey Bataevf93095a2016-05-05 08:46:22 +00004817 }
4818 return InitRequired;
4819}
4820
4821
4822/// Emit task_dup function (for initialization of
4823/// private/firstprivate/lastprivate vars and last_iter flag)
4824/// \code
4825/// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int
4826/// lastpriv) {
4827/// // setup lastprivate flag
4828/// task_dst->last = lastpriv;
4829/// // could be constructor calls here...
4830/// }
4831/// \endcode
4832static llvm::Value *
4833emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
4834 const OMPExecutableDirective &D,
4835 QualType KmpTaskTWithPrivatesPtrQTy,
4836 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4837 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy,
4838 QualType SharedsPtrTy, const OMPTaskDataTy &Data,
4839 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004840 ASTContext &C = CGM.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004841 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004842 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4843 KmpTaskTWithPrivatesPtrQTy,
4844 ImplicitParamDecl::Other);
4845 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4846 KmpTaskTWithPrivatesPtrQTy,
4847 ImplicitParamDecl::Other);
4848 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy,
4849 ImplicitParamDecl::Other);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004850 Args.push_back(&DstArg);
4851 Args.push_back(&SrcArg);
4852 Args.push_back(&LastprivArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004853 const auto &TaskDupFnInfo =
Alexey Bataevf93095a2016-05-05 08:46:22 +00004854 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004855 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004856 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""});
4857 auto *TaskDup = llvm::Function::Create(
4858 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004859 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004860 TaskDup->setDoesNotRecurse();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004861 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004862 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc,
4863 Loc);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004864
4865 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4866 CGF.GetAddrOfLocalVar(&DstArg),
4867 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4868 // task_dst->liter = lastpriv;
4869 if (WithLastIter) {
4870 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
4871 LValue Base = CGF.EmitLValueForField(
4872 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4873 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4874 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar(
4875 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc);
4876 CGF.EmitStoreOfScalar(Lastpriv, LILVal);
4877 }
4878
4879 // Emit initial values for private copies (if any).
4880 assert(!Privates.empty());
4881 Address KmpTaskSharedsPtr = Address::invalid();
4882 if (!Data.FirstprivateVars.empty()) {
4883 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4884 CGF.GetAddrOfLocalVar(&SrcArg),
4885 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4886 LValue Base = CGF.EmitLValueForField(
4887 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4888 KmpTaskSharedsPtr = Address(
4889 CGF.EmitLoadOfScalar(CGF.EmitLValueForField(
4890 Base, *std::next(KmpTaskTQTyRD->field_begin(),
4891 KmpTaskTShareds)),
4892 Loc),
4893 CGF.getNaturalTypeAlignment(SharedsTy));
4894 }
Alexey Bataev8a831592016-05-10 10:36:51 +00004895 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
4896 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004897 CGF.FinishFunction();
4898 return TaskDup;
4899}
4900
Alexey Bataev8a831592016-05-10 10:36:51 +00004901/// Checks if destructor function is required to be generated.
4902/// \return true if cleanups are required, false otherwise.
4903static bool
4904checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) {
4905 bool NeedsCleanup = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004906 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4907 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl());
4908 for (const FieldDecl *FD : PrivateRD->fields()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00004909 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType();
4910 if (NeedsCleanup)
4911 break;
4912 }
4913 return NeedsCleanup;
4914}
4915
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004916CGOpenMPRuntime::TaskResultTy
4917CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
4918 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00004919 llvm::Function *TaskFunction, QualType SharedsTy,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004920 Address Shareds, const OMPTaskDataTy &Data) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004921 ASTContext &C = CGM.getContext();
Alexey Bataev7292c292016-04-25 12:22:29 +00004922 llvm::SmallVector<PrivateDataTy, 4> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004923 // Aggregate privates and sort them by the alignment.
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004924 auto I = Data.PrivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004925 for (const Expr *E : Data.PrivateVars) {
4926 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00004927 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00004928 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00004929 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00004930 /*PrivateElemInit=*/nullptr));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004931 ++I;
4932 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004933 I = Data.FirstprivateCopies.begin();
4934 auto IElemInitRef = Data.FirstprivateInits.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004935 for (const Expr *E : Data.FirstprivateVars) {
4936 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00004937 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00004938 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00004939 PrivateHelpersTy(
4940 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00004941 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())));
Richard Trieucc3949d2016-02-18 22:34:54 +00004942 ++I;
4943 ++IElemInitRef;
Alexey Bataev9e034042015-05-05 04:05:12 +00004944 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004945 I = Data.LastprivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004946 for (const Expr *E : Data.LastprivateVars) {
4947 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00004948 Privates.emplace_back(
Alexey Bataevf93095a2016-05-05 08:46:22 +00004949 C.getDeclAlign(VD),
4950 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00004951 /*PrivateElemInit=*/nullptr));
Alexey Bataevf93095a2016-05-05 08:46:22 +00004952 ++I;
4953 }
Fangrui Song899d1392019-04-24 14:43:05 +00004954 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) {
4955 return L.first > R.first;
4956 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004957 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004958 // Build type kmp_routine_entry_t (if not built yet).
4959 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004960 // Build type kmp_task_t (if not built yet).
Alexey Bataeve213f3e2017-10-11 15:29:40 +00004961 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) {
4962 if (SavedKmpTaskloopTQTy.isNull()) {
4963 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl(
4964 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
4965 }
4966 KmpTaskTQTy = SavedKmpTaskloopTQTy;
Alexey Bataev3a03a7f2017-10-11 15:56:38 +00004967 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004968 assert((D.getDirectiveKind() == OMPD_task ||
4969 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) ||
4970 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) &&
4971 "Expected taskloop, task or target directive");
Alexey Bataeve213f3e2017-10-11 15:29:40 +00004972 if (SavedKmpTaskTQTy.isNull()) {
4973 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl(
4974 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
4975 }
4976 KmpTaskTQTy = SavedKmpTaskTQTy;
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004977 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004978 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00004979 // Build particular struct kmp_task_t for the given task.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004980 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004981 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004982 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004983 QualType KmpTaskTWithPrivatesPtrQTy =
4984 C.getPointerType(KmpTaskTWithPrivatesQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004985 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
4986 llvm::Type *KmpTaskTWithPrivatesPtrTy =
4987 KmpTaskTWithPrivatesTy->getPointerTo();
4988 llvm::Value *KmpTaskTWithPrivatesTySize =
4989 CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004990 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
4991
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004992 // Emit initial values for private copies (if any).
4993 llvm::Value *TaskPrivatesMap = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004994 llvm::Type *TaskPrivatesMapTy =
James Y Knight9871db02019-02-05 16:42:33 +00004995 std::next(TaskFunction->arg_begin(), 3)->getType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004996 if (!Privates.empty()) {
4997 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataevf93095a2016-05-05 08:46:22 +00004998 TaskPrivatesMap = emitTaskPrivateMappingFunction(
4999 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars,
5000 FI->getType(), Privates);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005001 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5002 TaskPrivatesMap, TaskPrivatesMapTy);
5003 } else {
5004 TaskPrivatesMap = llvm::ConstantPointerNull::get(
5005 cast<llvm::PointerType>(TaskPrivatesMapTy));
5006 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005007 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
5008 // kmp_task_t *tt);
James Y Knight9871db02019-02-05 16:42:33 +00005009 llvm::Function *TaskEntry = emitProxyTaskFunction(
Alexey Bataev7292c292016-04-25 12:22:29 +00005010 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5011 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction,
5012 TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005013
5014 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
5015 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
5016 // kmp_routine_entry_t *task_entry);
5017 // Task flags. Format is taken from
James Y Knight5d71fc52019-01-29 16:37:27 +00005018 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h,
Alexey Bataev62b63b12015-03-10 07:28:44 +00005019 // description of kmp_tasking_flags struct.
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005020 enum {
5021 TiedFlag = 0x1,
5022 FinalFlag = 0x2,
5023 DestructorsFlag = 0x8,
5024 PriorityFlag = 0x20
5025 };
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005026 unsigned Flags = Data.Tied ? TiedFlag : 0;
Alexey Bataev8a831592016-05-10 10:36:51 +00005027 bool NeedsCleanup = false;
5028 if (!Privates.empty()) {
5029 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD);
5030 if (NeedsCleanup)
5031 Flags = Flags | DestructorsFlag;
5032 }
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005033 if (Data.Priority.getInt())
5034 Flags = Flags | PriorityFlag;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005035 llvm::Value *TaskFlags =
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005036 Data.Final.getPointer()
5037 ? CGF.Builder.CreateSelect(Data.Final.getPointer(),
Alexey Bataev62b63b12015-03-10 07:28:44 +00005038 CGF.Builder.getInt32(FinalFlag),
5039 CGF.Builder.getInt32(/*C=*/0))
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005040 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005041 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005042 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005043 llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc),
5044 getThreadID(CGF, Loc), TaskFlags,
5045 KmpTaskTWithPrivatesTySize, SharedsSize,
5046 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5047 TaskEntry, KmpRoutineEntryPtrTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005048 llvm::Value *NewTask = CGF.EmitRuntimeCall(
Alexey Bataev62b63b12015-03-10 07:28:44 +00005049 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005050 llvm::Value *NewTaskNewTaskTTy =
5051 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5052 NewTask, KmpTaskTWithPrivatesPtrTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005053 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
5054 KmpTaskTWithPrivatesQTy);
5055 LValue TDBase =
5056 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005057 // Fill the data in the resulting kmp_task_t record.
5058 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00005059 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005060 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00005061 KmpTaskSharedsPtr =
5062 Address(CGF.EmitLoadOfScalar(
5063 CGF.EmitLValueForField(
5064 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
5065 KmpTaskTShareds)),
5066 Loc),
5067 CGF.getNaturalTypeAlignment(SharedsTy));
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00005068 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy);
5069 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy);
Richard Smithe78fac52018-04-05 20:52:58 +00005070 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005071 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005072 // Emit initial values for private copies (if any).
Alexey Bataevf93095a2016-05-05 08:46:22 +00005073 TaskResultTy Result;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005074 if (!Privates.empty()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00005075 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD,
5076 SharedsTy, SharedsPtrTy, Data, Privates,
5077 /*ForDup=*/false);
Alexey Bataevf93095a2016-05-05 08:46:22 +00005078 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
5079 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) {
5080 Result.TaskDupFn = emitTaskDupFunction(
5081 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
5082 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates,
5083 /*WithLastIter=*/!Data.LastprivateVars.empty());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005084 }
5085 }
Alexey Bataevad537bb2016-05-30 09:06:50 +00005086 // Fields of union "kmp_cmplrdata_t" for destructors and priority.
5087 enum { Priority = 0, Destructors = 1 };
Alexey Bataev62b63b12015-03-10 07:28:44 +00005088 // Provide pointer to function with destructors for privates.
Alexey Bataevad537bb2016-05-30 09:06:50 +00005089 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005090 const RecordDecl *KmpCmplrdataUD =
5091 (*FI)->getType()->getAsUnionType()->getDecl();
Alexey Bataevad537bb2016-05-30 09:06:50 +00005092 if (NeedsCleanup) {
5093 llvm::Value *DestructorFn = emitDestructorsFunction(
5094 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5095 KmpTaskTWithPrivatesQTy);
5096 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI);
5097 LValue DestructorsLV = CGF.EmitLValueForField(
5098 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
5099 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5100 DestructorFn, KmpRoutineEntryPtrTy),
5101 DestructorsLV);
5102 }
5103 // Set priority.
5104 if (Data.Priority.getInt()) {
5105 LValue Data2LV = CGF.EmitLValueForField(
5106 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
5107 LValue PriorityLV = CGF.EmitLValueForField(
5108 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
5109 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV);
5110 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005111 Result.NewTask = NewTask;
5112 Result.TaskEntry = TaskEntry;
5113 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
5114 Result.TDBase = TDBase;
5115 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
5116 return Result;
Alexey Bataev7292c292016-04-25 12:22:29 +00005117}
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005118
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005119void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
5120 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005121 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005122 QualType SharedsTy, Address Shareds,
5123 const Expr *IfCond,
5124 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005125 if (!CGF.HaveInsertPoint())
5126 return;
5127
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005128 TaskResultTy Result =
5129 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
5130 llvm::Value *NewTask = Result.NewTask;
James Y Knight9871db02019-02-05 16:42:33 +00005131 llvm::Function *TaskEntry = Result.TaskEntry;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005132 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy;
5133 LValue TDBase = Result.TDBase;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005134 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD;
5135 ASTContext &C = CGM.getContext();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005136 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00005137 Address DependenciesArray = Address::invalid();
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005138 unsigned NumDependencies = Data.Dependences.size();
John McCall7f416cc2015-09-08 08:05:57 +00005139 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005140 // Dependence kind for RTL.
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005141 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 };
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005142 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
5143 RecordDecl *KmpDependInfoRD;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005144 QualType FlagsTy =
5145 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005146 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
5147 if (KmpDependInfoTy.isNull()) {
5148 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
5149 KmpDependInfoRD->startDefinition();
5150 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
5151 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
5152 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
5153 KmpDependInfoRD->completeDefinition();
5154 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005155 } else {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005156 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005157 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005158 // Define type kmp_depend_info[<Dependences.size()>];
5159 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00005160 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005161 ArrayType::Normal, /*IndexTypeQuals=*/0);
5162 // kmp_depend_info[<Dependences.size()>] deps;
Alexey Bataev48591dd2016-04-20 04:01:36 +00005163 DependenciesArray =
5164 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005165 for (unsigned I = 0; I < NumDependencies; ++I) {
5166 const Expr *E = Data.Dependences[I].second;
5167 LValue Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005168 llvm::Value *Size;
5169 QualType Ty = E->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005170 if (const auto *ASE =
5171 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005172 LValue UpAddrLVal =
5173 CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false);
5174 llvm::Value *UpAddr =
John McCall7f416cc2015-09-08 08:05:57 +00005175 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005176 llvm::Value *LowIntPtr =
John McCall7f416cc2015-09-08 08:05:57 +00005177 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005178 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
5179 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005180 } else {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005181 Size = CGF.getTypeSize(Ty);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005182 }
5183 LValue Base = CGF.MakeAddrLValue(
James Y Knight751fe282019-02-09 22:22:28 +00005184 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005185 KmpDependInfoTy);
5186 // deps[i].base_addr = &<Dependences[i].second>;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005187 LValue BaseAddrLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005188 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00005189 CGF.EmitStoreOfScalar(
5190 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy),
5191 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005192 // deps[i].len = sizeof(<Dependences[i].second>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005193 LValue LenLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005194 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
5195 CGF.EmitStoreOfScalar(Size, LenLVal);
5196 // deps[i].flags = <Dependences[i].first>;
5197 RTLDependenceKindTy DepKind;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005198 switch (Data.Dependences[I].first) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005199 case OMPC_DEPEND_in:
5200 DepKind = DepIn;
5201 break;
Alexey Bataev92e82f92015-11-23 13:33:42 +00005202 // Out and InOut dependencies must use the same code.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005203 case OMPC_DEPEND_out:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005204 case OMPC_DEPEND_inout:
5205 DepKind = DepInOut;
5206 break;
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005207 case OMPC_DEPEND_mutexinoutset:
5208 DepKind = DepMutexInOutSet;
5209 break;
Alexey Bataeveb482352015-12-18 05:05:56 +00005210 case OMPC_DEPEND_source:
Alexey Bataeva636c7f2015-12-23 10:27:45 +00005211 case OMPC_DEPEND_sink:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005212 case OMPC_DEPEND_unknown:
5213 llvm_unreachable("Unknown task dependence type");
5214 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005215 LValue FlagsLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005216 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
5217 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
5218 FlagsLVal);
5219 }
John McCall7f416cc2015-09-08 08:05:57 +00005220 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knightf5f1b0e2019-02-08 15:34:12 +00005221 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005222 }
5223
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005224 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev62b63b12015-03-10 07:28:44 +00005225 // libcall.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005226 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
5227 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
5228 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
5229 // list is not empty
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005230 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5231 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00005232 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
5233 llvm::Value *DepTaskArgs[7];
5234 if (NumDependencies) {
5235 DepTaskArgs[0] = UpLoc;
5236 DepTaskArgs[1] = ThreadID;
5237 DepTaskArgs[2] = NewTask;
5238 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
5239 DepTaskArgs[4] = DependenciesArray.getPointer();
5240 DepTaskArgs[5] = CGF.Builder.getInt32(0);
5241 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5242 }
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005243 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies,
5244 &TaskArgs,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005245 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005246 if (!Data.Tied) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005247 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005248 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
Alexey Bataev48591dd2016-04-20 04:01:36 +00005249 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
5250 }
John McCall7f416cc2015-09-08 08:05:57 +00005251 if (NumDependencies) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005252 CGF.EmitRuntimeCall(
Alexey Bataev48591dd2016-04-20 04:01:36 +00005253 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs);
John McCall7f416cc2015-09-08 08:05:57 +00005254 } else {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005255 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
John McCall7f416cc2015-09-08 08:05:57 +00005256 TaskArgs);
5257 }
Alexey Bataev48591dd2016-04-20 04:01:36 +00005258 // Check if parent region is untied and build return for untied task;
5259 if (auto *Region =
5260 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
5261 Region->emitUntiedSwitch(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00005262 };
John McCall7f416cc2015-09-08 08:05:57 +00005263
5264 llvm::Value *DepWaitTaskArgs[6];
5265 if (NumDependencies) {
5266 DepWaitTaskArgs[0] = UpLoc;
5267 DepWaitTaskArgs[1] = ThreadID;
5268 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
5269 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
5270 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
5271 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5272 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005273 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
Alexey Bataev3c595a62017-08-14 15:01:03 +00005274 NumDependencies, &DepWaitTaskArgs,
5275 Loc](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005276 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005277 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
5278 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
5279 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
5280 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
5281 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00005282 if (NumDependencies)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005283 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005284 DepWaitTaskArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005285 // Call proxy_task_entry(gtid, new_task);
Alexey Bataev3c595a62017-08-14 15:01:03 +00005286 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
5287 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005288 Action.Enter(CGF);
5289 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
Alexey Bataev3c595a62017-08-14 15:01:03 +00005290 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
Alexey Bataev2c7eee52017-08-04 19:10:54 +00005291 OutlinedFnArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005292 };
5293
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005294 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
5295 // kmp_task_t *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005296 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
5297 // kmp_task_t *new_task);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005298 RegionCodeGenTy RCG(CodeGen);
5299 CommonActionTy Action(
5300 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs,
5301 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs);
5302 RCG.setAction(Action);
5303 RCG(CGF);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005304 };
John McCall7f416cc2015-09-08 08:05:57 +00005305
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005306 if (IfCond) {
Alexey Bataev1d677132015-04-22 13:57:31 +00005307 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005308 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005309 RegionCodeGenTy ThenRCG(ThenCodeGen);
5310 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00005311 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005312}
5313
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005314void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
5315 const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005316 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005317 QualType SharedsTy, Address Shareds,
5318 const Expr *IfCond,
5319 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005320 if (!CGF.HaveInsertPoint())
5321 return;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005322 TaskResultTy Result =
5323 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005324 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev7292c292016-04-25 12:22:29 +00005325 // libcall.
5326 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
5327 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
5328 // sched, kmp_uint64 grainsize, void *task_dup);
5329 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5330 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
5331 llvm::Value *IfVal;
5332 if (IfCond) {
5333 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy,
5334 /*isSigned=*/true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005335 } else {
Alexey Bataev7292c292016-04-25 12:22:29 +00005336 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005337 }
Alexey Bataev7292c292016-04-25 12:22:29 +00005338
5339 LValue LBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005340 Result.TDBase,
5341 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005342 const auto *LBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005343 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl());
5344 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(),
5345 /*IsInitializer=*/true);
5346 LValue UBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005347 Result.TDBase,
5348 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005349 const auto *UBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005350 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl());
5351 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(),
5352 /*IsInitializer=*/true);
5353 LValue StLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005354 Result.TDBase,
5355 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005356 const auto *StVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005357 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl());
5358 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(),
5359 /*IsInitializer=*/true);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005360 // Store reductions address.
5361 LValue RedLVal = CGF.EmitLValueForField(
5362 Result.TDBase,
5363 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005364 if (Data.Reductions) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005365 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005366 } else {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005367 CGF.EmitNullInitialization(RedLVal.getAddress(),
5368 CGF.getContext().VoidPtrTy);
5369 }
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005370 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
Alexey Bataev7292c292016-04-25 12:22:29 +00005371 llvm::Value *TaskArgs[] = {
Alexey Bataev33446032017-07-12 18:09:32 +00005372 UpLoc,
5373 ThreadID,
5374 Result.NewTask,
5375 IfVal,
5376 LBLVal.getPointer(),
5377 UBLVal.getPointer(),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00005378 CGF.EmitLoadOfScalar(StLVal, Loc),
Alexey Bataevac6e4de2018-10-24 19:06:37 +00005379 llvm::ConstantInt::getSigned(
5380 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005381 llvm::ConstantInt::getSigned(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005382 CGF.IntTy, Data.Schedule.getPointer()
5383 ? Data.Schedule.getInt() ? NumTasks : Grainsize
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005384 : NoSchedule),
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005385 Data.Schedule.getPointer()
5386 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty,
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005387 /*isSigned=*/false)
5388 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0),
Alexey Bataev33446032017-07-12 18:09:32 +00005389 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5390 Result.TaskDupFn, CGF.VoidPtrTy)
5391 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)};
Alexey Bataev7292c292016-04-25 12:22:29 +00005392 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs);
5393}
5394
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005395/// Emit reduction operation for each element of array (required for
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005396/// array sections) LHS op = RHS.
5397/// \param Type Type of array.
5398/// \param LHSVar Variable on the left side of the reduction operation
5399/// (references element of array in original variable).
5400/// \param RHSVar Variable on the right side of the reduction operation
5401/// (references element of array in original variable).
5402/// \param RedOpGen Generator of reduction operation with use of LHSVar and
5403/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00005404static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005405 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
5406 const VarDecl *RHSVar,
5407 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
5408 const Expr *, const Expr *)> &RedOpGen,
5409 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
5410 const Expr *UpExpr = nullptr) {
5411 // Perform element-by-element initialization.
5412 QualType ElementTy;
5413 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
5414 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
5415
5416 // Drill down to the base element type on both arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005417 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
5418 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005419
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005420 llvm::Value *RHSBegin = RHSAddr.getPointer();
5421 llvm::Value *LHSBegin = LHSAddr.getPointer();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005422 // Cast from pointer to array type to pointer to single element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005423 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005424 // The basic structure here is a while-do loop.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005425 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
5426 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
5427 llvm::Value *IsEmpty =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005428 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
5429 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
5430
5431 // Enter the loop body, making that address the current address.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005432 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005433 CGF.EmitBlock(BodyBB);
5434
5435 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
5436
5437 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
5438 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
5439 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
5440 Address RHSElementCurrent =
5441 Address(RHSElementPHI,
5442 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5443
5444 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
5445 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
5446 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
5447 Address LHSElementCurrent =
5448 Address(LHSElementPHI,
5449 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5450
5451 // Emit copy.
5452 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005453 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; });
5454 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005455 Scope.Privatize();
5456 RedOpGen(CGF, XExpr, EExpr, UpExpr);
5457 Scope.ForceCleanup();
5458
5459 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005460 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005461 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005462 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005463 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
5464 // Check whether we've reached the end.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005465 llvm::Value *Done =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005466 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
5467 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
5468 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
5469 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
5470
5471 // Done.
5472 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
5473}
5474
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005475/// Emit reduction combiner. If the combiner is a simple expression emit it as
5476/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
5477/// UDR combiner function.
5478static void emitReductionCombiner(CodeGenFunction &CGF,
5479 const Expr *ReductionOp) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005480 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
5481 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
5482 if (const auto *DRE =
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005483 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005484 if (const auto *DRD =
5485 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005486 std::pair<llvm::Function *, llvm::Function *> Reduction =
5487 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
5488 RValue Func = RValue::get(Reduction.first);
5489 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
5490 CGF.EmitIgnoredExpr(ReductionOp);
5491 return;
5492 }
5493 CGF.EmitIgnoredExpr(ReductionOp);
5494}
5495
James Y Knight9871db02019-02-05 16:42:33 +00005496llvm::Function *CGOpenMPRuntime::emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005497 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates,
5498 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
5499 ArrayRef<const Expr *> ReductionOps) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005500 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005501
5502 // void reduction_func(void *LHSArg, void *RHSArg);
5503 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005504 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5505 ImplicitParamDecl::Other);
5506 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5507 ImplicitParamDecl::Other);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005508 Args.push_back(&LHSArg);
5509 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005510 const auto &CGFI =
5511 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00005512 std::string Name = getName({"omp", "reduction", "reduction_func"});
5513 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
5514 llvm::GlobalValue::InternalLinkage, Name,
5515 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00005516 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00005517 Fn->setDoesNotRecurse();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005518 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005519 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005520
5521 // Dst = (void*[n])(LHSArg);
5522 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00005523 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5524 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
5525 ArgsType), CGF.getPointerAlign());
5526 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5527 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
5528 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005529
5530 // ...
5531 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
5532 // ...
5533 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005534 auto IPriv = Privates.begin();
5535 unsigned Idx = 0;
5536 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005537 const auto *RHSVar =
5538 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
5539 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005540 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005541 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005542 const auto *LHSVar =
5543 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
5544 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005545 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005546 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005547 QualType PrivTy = (*IPriv)->getType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00005548 if (PrivTy->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005549 // Get array size and emit VLA type.
5550 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005551 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005552 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005553 const VariableArrayType *VLA =
5554 CGF.getContext().getAsVariableArrayType(PrivTy);
5555 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005556 CodeGenFunction::OpaqueValueMapping OpaqueMap(
Alexey Bataev1189bd02016-01-26 12:20:39 +00005557 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005558 CGF.EmitVariablyModifiedType(PrivTy);
5559 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005560 }
5561 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005562 IPriv = Privates.begin();
5563 auto ILHS = LHSExprs.begin();
5564 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005565 for (const Expr *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005566 if ((*IPriv)->getType()->isArrayType()) {
5567 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005568 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5569 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005570 EmitOMPAggregateReduction(
5571 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5572 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5573 emitReductionCombiner(CGF, E);
5574 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005575 } else {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005576 // Emit reduction for array subscript or single variable.
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005577 emitReductionCombiner(CGF, E);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005578 }
Richard Trieucc3949d2016-02-18 22:34:54 +00005579 ++IPriv;
5580 ++ILHS;
5581 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005582 }
5583 Scope.ForceCleanup();
5584 CGF.FinishFunction();
5585 return Fn;
5586}
5587
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005588void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF,
5589 const Expr *ReductionOp,
5590 const Expr *PrivateRef,
5591 const DeclRefExpr *LHS,
5592 const DeclRefExpr *RHS) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005593 if (PrivateRef->getType()->isArrayType()) {
5594 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005595 const auto *LHSVar = cast<VarDecl>(LHS->getDecl());
5596 const auto *RHSVar = cast<VarDecl>(RHS->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005597 EmitOMPAggregateReduction(
5598 CGF, PrivateRef->getType(), LHSVar, RHSVar,
5599 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5600 emitReductionCombiner(CGF, ReductionOp);
5601 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005602 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005603 // Emit reduction for array subscript or single variable.
5604 emitReductionCombiner(CGF, ReductionOp);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005605 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005606}
5607
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005608void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005609 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005610 ArrayRef<const Expr *> LHSExprs,
5611 ArrayRef<const Expr *> RHSExprs,
5612 ArrayRef<const Expr *> ReductionOps,
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005613 ReductionOptionsTy Options) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00005614 if (!CGF.HaveInsertPoint())
5615 return;
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005616
5617 bool WithNowait = Options.WithNowait;
5618 bool SimpleReduction = Options.SimpleReduction;
5619
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005620 // Next code should be emitted for reduction:
5621 //
5622 // static kmp_critical_name lock = { 0 };
5623 //
5624 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
5625 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
5626 // ...
5627 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
5628 // *(Type<n>-1*)rhs[<n>-1]);
5629 // }
5630 //
5631 // ...
5632 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
5633 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5634 // RedList, reduce_func, &<lock>)) {
5635 // case 1:
5636 // ...
5637 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5638 // ...
5639 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5640 // break;
5641 // case 2:
5642 // ...
5643 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5644 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00005645 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005646 // break;
5647 // default:;
5648 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005649 //
5650 // if SimpleReduction is true, only the next code is generated:
5651 // ...
5652 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5653 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005654
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005655 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005656
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005657 if (SimpleReduction) {
5658 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005659 auto IPriv = Privates.begin();
5660 auto ILHS = LHSExprs.begin();
5661 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005662 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005663 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5664 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005665 ++IPriv;
5666 ++ILHS;
5667 ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005668 }
5669 return;
5670 }
5671
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005672 // 1. Build a list of reduction variables.
5673 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005674 auto Size = RHSExprs.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005675 for (const Expr *E : Privates) {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005676 if (E->getType()->isVariablyModifiedType())
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005677 // Reserve place for array size.
5678 ++Size;
5679 }
5680 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005681 QualType ReductionArrayTy =
5682 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
5683 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00005684 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005685 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005686 auto IPriv = Privates.begin();
5687 unsigned Idx = 0;
5688 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
James Y Knight751fe282019-02-09 22:22:28 +00005689 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
John McCall7f416cc2015-09-08 08:05:57 +00005690 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005691 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00005692 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
5693 Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005694 if ((*IPriv)->getType()->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005695 // Store array size.
5696 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005697 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005698 llvm::Value *Size = CGF.Builder.CreateIntCast(
5699 CGF.getVLASize(
5700 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
Sander de Smalen891af03a2018-02-03 13:55:59 +00005701 .NumElts,
Alexey Bataev1189bd02016-01-26 12:20:39 +00005702 CGF.SizeTy, /*isSigned=*/false);
5703 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
5704 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005705 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005706 }
5707
5708 // 2. Emit reduce_func().
James Y Knight9871db02019-02-05 16:42:33 +00005709 llvm::Function *ReductionFn = emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005710 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
5711 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005712
5713 // 3. Create static kmp_critical_name lock = { 0 };
Alexey Bataev18fa2322018-05-02 14:20:50 +00005714 std::string Name = getName({"reduction"});
5715 llvm::Value *Lock = getCriticalRegionLock(Name);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005716
5717 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5718 // RedList, reduce_func, &<lock>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005719 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
5720 llvm::Value *ThreadId = getThreadID(CGF, Loc);
5721 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
5722 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Samuel Antao4c8035b2016-12-12 18:00:20 +00005723 ReductionList.getPointer(), CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005724 llvm::Value *Args[] = {
5725 IdentTLoc, // ident_t *<loc>
5726 ThreadId, // i32 <gtid>
5727 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
5728 ReductionArrayTySize, // size_type sizeof(RedList)
5729 RL, // void *RedList
5730 ReductionFn, // void (*) (void *, void *) <reduce_func>
5731 Lock // kmp_critical_name *&<lock>
5732 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005733 llvm::Value *Res = CGF.EmitRuntimeCall(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005734 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
5735 : OMPRTL__kmpc_reduce),
5736 Args);
5737
5738 // 5. Build switch(res)
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005739 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
5740 llvm::SwitchInst *SwInst =
5741 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005742
5743 // 6. Build case 1:
5744 // ...
5745 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5746 // ...
5747 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5748 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005749 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005750 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
5751 CGF.EmitBlock(Case1BB);
5752
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005753 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5754 llvm::Value *EndArgs[] = {
5755 IdentTLoc, // ident_t *<loc>
5756 ThreadId, // i32 <gtid>
5757 Lock // kmp_critical_name *&<lock>
5758 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005759 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5760 CodeGenFunction &CGF, PrePostActionTy &Action) {
5761 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005762 auto IPriv = Privates.begin();
5763 auto ILHS = LHSExprs.begin();
5764 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005765 for (const Expr *E : ReductionOps) {
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005766 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5767 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005768 ++IPriv;
5769 ++ILHS;
5770 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005771 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005772 };
5773 RegionCodeGenTy RCG(CodeGen);
5774 CommonActionTy Action(
5775 nullptr, llvm::None,
5776 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
5777 : OMPRTL__kmpc_end_reduce),
5778 EndArgs);
5779 RCG.setAction(Action);
5780 RCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005781
5782 CGF.EmitBranch(DefaultBB);
5783
5784 // 7. Build case 2:
5785 // ...
5786 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5787 // ...
5788 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005789 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005790 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
5791 CGF.EmitBlock(Case2BB);
5792
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005793 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
5794 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005795 auto ILHS = LHSExprs.begin();
5796 auto IRHS = RHSExprs.begin();
5797 auto IPriv = Privates.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005798 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005799 const Expr *XExpr = nullptr;
5800 const Expr *EExpr = nullptr;
5801 const Expr *UpExpr = nullptr;
5802 BinaryOperatorKind BO = BO_Comma;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005803 if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005804 if (BO->getOpcode() == BO_Assign) {
5805 XExpr = BO->getLHS();
5806 UpExpr = BO->getRHS();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005807 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005808 }
5809 // Try to emit update expression as a simple atomic.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005810 const Expr *RHSExpr = UpExpr;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005811 if (RHSExpr) {
5812 // Analyze RHS part of the whole expression.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005813 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005814 RHSExpr->IgnoreParenImpCasts())) {
5815 // If this is a conditional operator, analyze its condition for
5816 // min/max reduction operator.
5817 RHSExpr = ACO->getCond();
Alexey Bataev69a47792015-05-07 03:54:03 +00005818 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005819 if (const auto *BORHS =
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005820 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
5821 EExpr = BORHS->getRHS();
5822 BO = BORHS->getOpcode();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005823 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005824 }
5825 if (XExpr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005826 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005827 auto &&AtomicRedGen = [BO, VD,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005828 Loc](CodeGenFunction &CGF, const Expr *XExpr,
5829 const Expr *EExpr, const Expr *UpExpr) {
5830 LValue X = CGF.EmitLValue(XExpr);
5831 RValue E;
5832 if (EExpr)
5833 E = CGF.EmitAnyExpr(EExpr);
5834 CGF.EmitOMPAtomicSimpleUpdateExpr(
JF Bastien92f4ef12016-04-06 17:26:42 +00005835 X, E, BO, /*IsXLHSInRHSPart=*/true,
5836 llvm::AtomicOrdering::Monotonic, Loc,
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005837 [&CGF, UpExpr, VD, Loc](RValue XRValue) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005838 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5839 PrivateScope.addPrivate(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005840 VD, [&CGF, VD, XRValue, Loc]() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005841 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5842 CGF.emitOMPSimpleStore(
5843 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
5844 VD->getType().getNonReferenceType(), Loc);
5845 return LHSTemp;
5846 });
5847 (void)PrivateScope.Privatize();
5848 return CGF.EmitAnyExpr(UpExpr);
5849 });
5850 };
5851 if ((*IPriv)->getType()->isArrayType()) {
5852 // Emit atomic reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005853 const auto *RHSVar =
5854 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005855 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
5856 AtomicRedGen, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005857 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005858 // Emit atomic reduction for array subscript or single variable.
5859 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005860 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005861 } else {
5862 // Emit as a critical region.
5863 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
Alexey Bataev18fa2322018-05-02 14:20:50 +00005864 const Expr *, const Expr *) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005865 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev18fa2322018-05-02 14:20:50 +00005866 std::string Name = RT.getName({"atomic_reduction"});
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005867 RT.emitCriticalRegion(
Alexey Bataev18fa2322018-05-02 14:20:50 +00005868 CGF, Name,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005869 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
5870 Action.Enter(CGF);
5871 emitReductionCombiner(CGF, E);
5872 },
5873 Loc);
5874 };
5875 if ((*IPriv)->getType()->isArrayType()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005876 const auto *LHSVar =
5877 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5878 const auto *RHSVar =
5879 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005880 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5881 CritRedGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005882 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005883 CritRedGen(CGF, nullptr, nullptr, nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005884 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005885 }
Richard Trieucc3949d2016-02-18 22:34:54 +00005886 ++ILHS;
5887 ++IRHS;
5888 ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005889 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005890 };
5891 RegionCodeGenTy AtomicRCG(AtomicCodeGen);
5892 if (!WithNowait) {
5893 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
5894 llvm::Value *EndArgs[] = {
5895 IdentTLoc, // ident_t *<loc>
5896 ThreadId, // i32 <gtid>
5897 Lock // kmp_critical_name *&<lock>
5898 };
5899 CommonActionTy Action(nullptr, llvm::None,
5900 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
5901 EndArgs);
5902 AtomicRCG.setAction(Action);
5903 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005904 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005905 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005906 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005907
5908 CGF.EmitBranch(DefaultBB);
5909 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
5910}
5911
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005912/// Generates unique name for artificial threadprivate variables.
Alexey Bataev1c44e152018-03-06 18:59:43 +00005913/// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>"
5914static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix,
5915 const Expr *Ref) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005916 SmallString<256> Buffer;
5917 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev1c44e152018-03-06 18:59:43 +00005918 const clang::DeclRefExpr *DE;
5919 const VarDecl *D = ::getBaseDecl(Ref, DE);
5920 if (!D)
5921 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl());
5922 D = D->getCanonicalDecl();
Alexey Bataev18fa2322018-05-02 14:20:50 +00005923 std::string Name = CGM.getOpenMPRuntime().getName(
5924 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)});
5925 Out << Prefix << Name << "_"
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005926 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005927 return Out.str();
5928}
5929
5930/// Emits reduction initializer function:
5931/// \code
5932/// void @.red_init(void* %arg) {
5933/// %0 = bitcast void* %arg to <type>*
5934/// store <type> <init>, <type>* %0
5935/// ret void
5936/// }
5937/// \endcode
5938static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM,
5939 SourceLocation Loc,
5940 ReductionCodeGen &RCG, unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005941 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005942 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005943 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5944 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005945 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005946 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005947 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005948 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00005949 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005950 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00005951 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00005952 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00005953 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005954 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005955 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005956 Address PrivateAddr = CGF.EmitLoadOfPointer(
5957 CGF.GetAddrOfLocalVar(&Param),
5958 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
5959 llvm::Value *Size = nullptr;
5960 // If the size of the reduction item is non-constant, load it from global
5961 // threadprivate variable.
5962 if (RCG.getSizes(N).second) {
5963 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
5964 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00005965 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00005966 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
5967 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005968 }
5969 RCG.emitAggregateType(CGF, N, Size);
5970 LValue SharedLVal;
5971 // If initializer uses initializer from declare reduction construct, emit a
5972 // pointer to the address of the original reduction item (reuired by reduction
5973 // initializer)
5974 if (RCG.usesReductionInitializer(N)) {
5975 Address SharedAddr =
5976 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
5977 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00005978 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataev21dab122018-03-09 15:20:30 +00005979 SharedAddr = CGF.EmitLoadOfPointer(
5980 SharedAddr,
5981 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005982 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy);
5983 } else {
5984 SharedLVal = CGF.MakeNaturalAlignAddrLValue(
5985 llvm::ConstantPointerNull::get(CGM.VoidPtrTy),
5986 CGM.getContext().VoidPtrTy);
5987 }
5988 // Emit the initializer:
5989 // %0 = bitcast void* %arg to <type>*
5990 // store <type> <init>, <type>* %0
5991 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal,
5992 [](CodeGenFunction &) { return false; });
5993 CGF.FinishFunction();
5994 return Fn;
5995}
5996
5997/// Emits reduction combiner function:
5998/// \code
5999/// void @.red_comb(void* %arg0, void* %arg1) {
6000/// %lhs = bitcast void* %arg0 to <type>*
6001/// %rhs = bitcast void* %arg1 to <type>*
6002/// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs)
6003/// store <type> %2, <type>* %lhs
6004/// ret void
6005/// }
6006/// \endcode
6007static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM,
6008 SourceLocation Loc,
6009 ReductionCodeGen &RCG, unsigned N,
6010 const Expr *ReductionOp,
6011 const Expr *LHS, const Expr *RHS,
6012 const Expr *PrivateRef) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006013 ASTContext &C = CGM.getContext();
6014 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl());
6015 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006016 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006017 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
6018 C.VoidPtrTy, ImplicitParamDecl::Other);
6019 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6020 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006021 Args.emplace_back(&ParamInOut);
6022 Args.emplace_back(&ParamIn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006023 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006024 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006025 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006026 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006027 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006028 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006029 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006030 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006031 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006032 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006033 llvm::Value *Size = nullptr;
6034 // If the size of the reduction item is non-constant, load it from global
6035 // threadprivate variable.
6036 if (RCG.getSizes(N).second) {
6037 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6038 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006039 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006040 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6041 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006042 }
6043 RCG.emitAggregateType(CGF, N, Size);
6044 // Remap lhs and rhs variables to the addresses of the function arguments.
6045 // %lhs = bitcast void* %arg0 to <type>*
6046 // %rhs = bitcast void* %arg1 to <type>*
6047 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006048 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006049 // Pull out the pointer to the variable.
6050 Address PtrAddr = CGF.EmitLoadOfPointer(
6051 CGF.GetAddrOfLocalVar(&ParamInOut),
6052 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6053 return CGF.Builder.CreateElementBitCast(
6054 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType()));
6055 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006056 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006057 // Pull out the pointer to the variable.
6058 Address PtrAddr = CGF.EmitLoadOfPointer(
6059 CGF.GetAddrOfLocalVar(&ParamIn),
6060 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6061 return CGF.Builder.CreateElementBitCast(
6062 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType()));
6063 });
6064 PrivateScope.Privatize();
6065 // Emit the combiner body:
6066 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs)
6067 // store <type> %2, <type>* %lhs
6068 CGM.getOpenMPRuntime().emitSingleReductionCombiner(
6069 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS),
6070 cast<DeclRefExpr>(RHS));
6071 CGF.FinishFunction();
6072 return Fn;
6073}
6074
6075/// Emits reduction finalizer function:
6076/// \code
6077/// void @.red_fini(void* %arg) {
6078/// %0 = bitcast void* %arg to <type>*
6079/// <destroy>(<type>* %0)
6080/// ret void
6081/// }
6082/// \endcode
6083static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM,
6084 SourceLocation Loc,
6085 ReductionCodeGen &RCG, unsigned N) {
6086 if (!RCG.needCleanups(N))
6087 return nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006088 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006089 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006090 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6091 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006092 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006093 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006094 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006095 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006096 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006097 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006098 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006099 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006100 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006101 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006102 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006103 Address PrivateAddr = CGF.EmitLoadOfPointer(
6104 CGF.GetAddrOfLocalVar(&Param),
6105 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6106 llvm::Value *Size = nullptr;
6107 // If the size of the reduction item is non-constant, load it from global
6108 // threadprivate variable.
6109 if (RCG.getSizes(N).second) {
6110 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6111 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006112 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006113 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6114 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006115 }
6116 RCG.emitAggregateType(CGF, N, Size);
6117 // Emit the finalizer body:
6118 // <destroy>(<type>* %0)
6119 RCG.emitCleanups(CGF, N, PrivateAddr);
6120 CGF.FinishFunction();
6121 return Fn;
6122}
6123
6124llvm::Value *CGOpenMPRuntime::emitTaskReductionInit(
6125 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
6126 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
6127 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty())
6128 return nullptr;
6129
6130 // Build typedef struct:
6131 // kmp_task_red_input {
6132 // void *reduce_shar; // shared reduction item
6133 // size_t reduce_size; // size of data item
6134 // void *reduce_init; // data initialization routine
6135 // void *reduce_fini; // data finalization routine
6136 // void *reduce_comb; // data combiner routine
6137 // kmp_task_red_flags_t flags; // flags for additional info from compiler
6138 // } kmp_task_red_input_t;
6139 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006140 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t");
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006141 RD->startDefinition();
6142 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6143 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType());
6144 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6145 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6146 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6147 const FieldDecl *FlagsFD = addFieldToRecordDecl(
6148 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false));
6149 RD->completeDefinition();
6150 QualType RDType = C.getRecordType(RD);
6151 unsigned Size = Data.ReductionVars.size();
6152 llvm::APInt ArraySize(/*numBits=*/64, Size);
6153 QualType ArrayRDType = C.getConstantArrayType(
6154 RDType, ArraySize, ArrayType::Normal, /*IndexTypeQuals=*/0);
6155 // kmp_task_red_input_t .rd_input.[Size];
6156 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input.");
6157 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies,
6158 Data.ReductionOps);
6159 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) {
6160 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt];
6161 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0),
6162 llvm::ConstantInt::get(CGM.SizeTy, Cnt)};
6163 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP(
6164 TaskRedInput.getPointer(), Idxs,
6165 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc,
6166 ".rd_input.gep.");
6167 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType);
6168 // ElemLVal.reduce_shar = &Shareds[Cnt];
6169 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD);
6170 RCG.emitSharedLValue(CGF, Cnt);
6171 llvm::Value *CastedShared =
6172 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer());
6173 CGF.EmitStoreOfScalar(CastedShared, SharedLVal);
6174 RCG.emitAggregateType(CGF, Cnt);
6175 llvm::Value *SizeValInChars;
6176 llvm::Value *SizeVal;
6177 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt);
6178 // We use delayed creation/initialization for VLAs, array sections and
6179 // custom reduction initializations. It is required because runtime does not
6180 // provide the way to pass the sizes of VLAs/array sections to
6181 // initializer/combiner/finalizer functions and does not pass the pointer to
6182 // original reduction item to the initializer. Instead threadprivate global
6183 // variables are used to store these values and use them in the functions.
6184 bool DelayedCreation = !!SizeVal;
6185 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy,
6186 /*isSigned=*/false);
6187 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD);
6188 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal);
6189 // ElemLVal.reduce_init = init;
6190 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD);
6191 llvm::Value *InitAddr =
6192 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt));
6193 CGF.EmitStoreOfScalar(InitAddr, InitLVal);
6194 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt);
6195 // ElemLVal.reduce_fini = fini;
6196 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD);
6197 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt);
6198 llvm::Value *FiniAddr = Fini
6199 ? CGF.EmitCastToVoidPtr(Fini)
6200 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy);
6201 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal);
6202 // ElemLVal.reduce_comb = comb;
6203 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD);
6204 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction(
6205 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt],
6206 RHSExprs[Cnt], Data.ReductionCopies[Cnt]));
6207 CGF.EmitStoreOfScalar(CombAddr, CombLVal);
6208 // ElemLVal.flags = 0;
6209 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD);
6210 if (DelayedCreation) {
6211 CGF.EmitStoreOfScalar(
6212 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*IsSigned=*/true),
6213 FlagsLVal);
6214 } else
6215 CGF.EmitNullInitialization(FlagsLVal.getAddress(), FlagsLVal.getType());
6216 }
6217 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void
6218 // *data);
6219 llvm::Value *Args[] = {
6220 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6221 /*isSigned=*/true),
6222 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true),
6223 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(),
6224 CGM.VoidPtrTy)};
6225 return CGF.EmitRuntimeCall(
6226 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args);
6227}
6228
6229void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
6230 SourceLocation Loc,
6231 ReductionCodeGen &RCG,
6232 unsigned N) {
6233 auto Sizes = RCG.getSizes(N);
6234 // Emit threadprivate global variable if the type is non-constant
6235 // (Sizes.second = nullptr).
6236 if (Sizes.second) {
6237 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy,
6238 /*isSigned=*/false);
6239 Address SizeAddr = getAddrOfArtificialThreadPrivate(
6240 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006241 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006242 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false);
6243 }
6244 // Store address of the original reduction item if custom initializer is used.
6245 if (RCG.usesReductionInitializer(N)) {
6246 Address SharedAddr = getAddrOfArtificialThreadPrivate(
6247 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006248 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006249 CGF.Builder.CreateStore(
6250 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6251 RCG.getSharedLValue(N).getPointer(), CGM.VoidPtrTy),
6252 SharedAddr, /*IsVolatile=*/false);
6253 }
6254}
6255
6256Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF,
6257 SourceLocation Loc,
6258 llvm::Value *ReductionsPtr,
6259 LValue SharedLVal) {
6260 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
6261 // *d);
6262 llvm::Value *Args[] = {
6263 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6264 /*isSigned=*/true),
6265 ReductionsPtr,
6266 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(SharedLVal.getPointer(),
6267 CGM.VoidPtrTy)};
6268 return Address(
6269 CGF.EmitRuntimeCall(
6270 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args),
6271 SharedLVal.getAlignment());
6272}
6273
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006274void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
6275 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006276 if (!CGF.HaveInsertPoint())
6277 return;
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006278 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
6279 // global_tid);
6280 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
6281 // Ignore return result until untied tasks are supported.
6282 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00006283 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
6284 Region->emitUntiedSwitch(CGF);
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006285}
6286
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006287void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006288 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00006289 const RegionCodeGenTy &CodeGen,
6290 bool HasCancel) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006291 if (!CGF.HaveInsertPoint())
6292 return;
Alexey Bataev25e5b442015-09-15 12:52:43 +00006293 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006294 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00006295}
6296
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006297namespace {
6298enum RTCancelKind {
6299 CancelNoreq = 0,
6300 CancelParallel = 1,
6301 CancelLoop = 2,
6302 CancelSections = 3,
6303 CancelTaskgroup = 4
6304};
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00006305} // anonymous namespace
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006306
6307static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
6308 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00006309 if (CancelRegion == OMPD_parallel)
6310 CancelKind = CancelParallel;
6311 else if (CancelRegion == OMPD_for)
6312 CancelKind = CancelLoop;
6313 else if (CancelRegion == OMPD_sections)
6314 CancelKind = CancelSections;
6315 else {
6316 assert(CancelRegion == OMPD_taskgroup);
6317 CancelKind = CancelTaskgroup;
6318 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006319 return CancelKind;
6320}
6321
6322void CGOpenMPRuntime::emitCancellationPointCall(
6323 CodeGenFunction &CGF, SourceLocation Loc,
6324 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006325 if (!CGF.HaveInsertPoint())
6326 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006327 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
6328 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006329 if (auto *OMPRegionInfo =
6330 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Jonas Hahnfeldb07931f2017-02-17 18:32:58 +00006331 // For 'cancellation point taskgroup', the task region info may not have a
6332 // cancel. This may instead happen in another adjacent task.
6333 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006334 llvm::Value *Args[] = {
6335 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
6336 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006337 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006338 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006339 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
6340 // if (__kmpc_cancellationpoint()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006341 // exit from construct;
6342 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006343 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6344 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6345 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006346 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6347 CGF.EmitBlock(ExitBB);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006348 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006349 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev25e5b442015-09-15 12:52:43 +00006350 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006351 CGF.EmitBranchThroughCleanup(CancelDest);
6352 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6353 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006354 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006355}
6356
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006357void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00006358 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006359 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006360 if (!CGF.HaveInsertPoint())
6361 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006362 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
6363 // kmp_int32 cncl_kind);
6364 if (auto *OMPRegionInfo =
6365 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006366 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF,
6367 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006368 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev87933c72015-09-18 08:07:34 +00006369 llvm::Value *Args[] = {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006370 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
Alexey Bataev87933c72015-09-18 08:07:34 +00006371 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
6372 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006373 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006374 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
Alexey Bataev87933c72015-09-18 08:07:34 +00006375 // if (__kmpc_cancel()) {
Alexey Bataev87933c72015-09-18 08:07:34 +00006376 // exit from construct;
6377 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006378 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6379 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6380 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev87933c72015-09-18 08:07:34 +00006381 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6382 CGF.EmitBlock(ExitBB);
Alexey Bataev87933c72015-09-18 08:07:34 +00006383 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006384 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev87933c72015-09-18 08:07:34 +00006385 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6386 CGF.EmitBranchThroughCleanup(CancelDest);
6387 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6388 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006389 if (IfCond) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006390 emitOMPIfClause(CGF, IfCond, ThenGen,
6391 [](CodeGenFunction &, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006392 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006393 RegionCodeGenTy ThenRCG(ThenGen);
6394 ThenRCG(CGF);
6395 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006396 }
6397}
Samuel Antaobed3c462015-10-02 16:14:20 +00006398
Samuel Antaoee8fb302016-01-06 13:42:12 +00006399void CGOpenMPRuntime::emitTargetOutlinedFunction(
6400 const OMPExecutableDirective &D, StringRef ParentName,
6401 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006402 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00006403 assert(!ParentName.empty() && "Invalid target region parent name!");
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006404 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
6405 IsOffloadEntry, CodeGen);
6406}
6407
6408void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
6409 const OMPExecutableDirective &D, StringRef ParentName,
6410 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6411 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antao2de62b02016-02-13 23:35:10 +00006412 // Create a unique name for the entry function using the source location
6413 // information of the current target region. The name will be something like:
Samuel Antaoee8fb302016-01-06 13:42:12 +00006414 //
Samuel Antao2de62b02016-02-13 23:35:10 +00006415 // __omp_offloading_DD_FFFF_PP_lBB
Samuel Antaoee8fb302016-01-06 13:42:12 +00006416 //
6417 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
Samuel Antao2de62b02016-02-13 23:35:10 +00006418 // mangled name of the function that encloses the target region and BB is the
6419 // line number of the target region.
Samuel Antaoee8fb302016-01-06 13:42:12 +00006420
6421 unsigned DeviceID;
6422 unsigned FileID;
6423 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00006424 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00006425 Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006426 SmallString<64> EntryFnName;
6427 {
6428 llvm::raw_svector_ostream OS(EntryFnName);
Samuel Antao2de62b02016-02-13 23:35:10 +00006429 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
6430 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00006431 }
6432
Alexey Bataev475a7442018-01-12 19:39:11 +00006433 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006434
Samuel Antaobed3c462015-10-02 16:14:20 +00006435 CodeGenFunction CGF(CGM, true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006436 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
Samuel Antaobed3c462015-10-02 16:14:20 +00006437 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006438
Samuel Antao6d004262016-06-16 18:39:34 +00006439 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006440
6441 // If this target outline function is not an offload entry, we don't need to
6442 // register it.
6443 if (!IsOffloadEntry)
6444 return;
6445
6446 // The target region ID is used by the runtime library to identify the current
6447 // target region, so it only has to be unique and not necessarily point to
6448 // anything. It could be the pointer to the outlined function that implements
6449 // the target region, but we aren't using that so that the compiler doesn't
6450 // need to keep that, and could therefore inline the host function if proven
6451 // worthwhile during optimization. In the other hand, if emitting code for the
6452 // device, the ID has to be the function address so that it can retrieved from
6453 // the offloading entry and launched by the runtime library. We also mark the
6454 // outlined function to have external linkage in case we are emitting code for
6455 // the device, because these functions will be entry points to the device.
6456
6457 if (CGM.getLangOpts().OpenMPIsDevice) {
6458 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
Alexey Bataev9a700172018-05-08 14:16:57 +00006459 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Rafael Espindolacbca4872018-01-11 22:15:12 +00006460 OutlinedFn->setDSOLocal(false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006461 } else {
Alexey Bataevc15ea702018-05-09 18:02:37 +00006462 std::string Name = getName({EntryFnName, "region_id"});
Samuel Antaoee8fb302016-01-06 13:42:12 +00006463 OutlinedFnID = new llvm::GlobalVariable(
6464 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
Alexey Bataev9a700172018-05-08 14:16:57 +00006465 llvm::GlobalValue::WeakAnyLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006466 llvm::Constant::getNullValue(CGM.Int8Ty), Name);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006467 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00006468
6469 // Register the information for the entry associated with this target region.
6470 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
Samuel Antaof83efdb2017-01-05 16:02:49 +00006471 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID,
Alexey Bataev03f270c2018-03-30 18:31:07 +00006472 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion);
Samuel Antaobed3c462015-10-02 16:14:20 +00006473}
6474
Alexey Bataev5c427362019-04-10 19:11:33 +00006475/// Checks if the expression is constant or does not have non-trivial function
6476/// calls.
6477static bool isTrivial(ASTContext &Ctx, const Expr * E) {
6478 // We can skip constant expressions.
6479 // We can skip expressions with trivial calls or simple expressions.
6480 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) ||
6481 !E->hasNonTrivialCall(Ctx)) &&
6482 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true);
6483}
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006484
Alexey Bataev5c427362019-04-10 19:11:33 +00006485const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx,
6486 const Stmt *Body) {
6487 const Stmt *Child = Body->IgnoreContainers();
6488 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) {
6489 Child = nullptr;
6490 for (const Stmt *S : C->body()) {
6491 if (const auto *E = dyn_cast<Expr>(S)) {
6492 if (isTrivial(Ctx, E))
6493 continue;
6494 }
6495 // Some of the statements can be ignored.
6496 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) ||
6497 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S))
6498 continue;
6499 // Analyze declarations.
6500 if (const auto *DS = dyn_cast<DeclStmt>(S)) {
6501 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) {
6502 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6503 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6504 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6505 isa<UsingDirectiveDecl>(D) ||
6506 isa<OMPDeclareReductionDecl>(D) ||
6507 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6508 return true;
6509 const auto *VD = dyn_cast<VarDecl>(D);
6510 if (!VD)
6511 return false;
6512 return VD->isConstexpr() ||
6513 ((VD->getType().isTrivialType(Ctx) ||
6514 VD->getType()->isReferenceType()) &&
6515 (!VD->hasInit() || isTrivial(Ctx, VD->getInit())));
6516 }))
6517 continue;
6518 }
6519 // Found multiple children - cannot get the one child only.
6520 if (Child)
6521 return nullptr;
6522 Child = S;
6523 }
6524 if (Child)
6525 Child = Child->IgnoreContainers();
6526 }
6527 return Child;
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006528}
6529
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006530/// Emit the number of teams for a target directive. Inspect the num_teams
6531/// clause associated with a teams construct combined or closely nested
6532/// with the target directive.
6533///
6534/// Emit a team of size one for directives such as 'target parallel' that
6535/// have no associated teams construct.
6536///
6537/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006538static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006539emitNumTeamsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006540 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006541 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6542 "Clauses associated with the teams directive expected to be emitted "
6543 "only for the host!");
6544 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6545 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6546 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006547 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006548 switch (DirectiveKind) {
6549 case OMPD_target: {
6550 const auto *CS = D.getInnermostCapturedStmt();
6551 const auto *Body =
6552 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
6553 const Stmt *ChildStmt =
6554 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body);
6555 if (const auto *NestedDir =
6556 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6557 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) {
6558 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) {
6559 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6560 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6561 const Expr *NumTeams =
6562 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6563 llvm::Value *NumTeamsVal =
6564 CGF.EmitScalarExpr(NumTeams,
6565 /*IgnoreResultAssign*/ true);
6566 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
6567 /*IsSigned=*/true);
6568 }
6569 return Bld.getInt32(0);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006570 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006571 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) ||
6572 isOpenMPSimdDirective(NestedDir->getDirectiveKind()))
6573 return Bld.getInt32(1);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006574 return Bld.getInt32(0);
6575 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006576 return nullptr;
Samuel Antaob68e2db2016-03-03 16:20:23 +00006577 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006578 case OMPD_target_teams:
6579 case OMPD_target_teams_distribute:
6580 case OMPD_target_teams_distribute_simd:
6581 case OMPD_target_teams_distribute_parallel_for:
6582 case OMPD_target_teams_distribute_parallel_for_simd: {
6583 if (D.hasClausesOfKind<OMPNumTeamsClause>()) {
6584 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF);
6585 const Expr *NumTeams =
6586 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6587 llvm::Value *NumTeamsVal =
6588 CGF.EmitScalarExpr(NumTeams,
6589 /*IgnoreResultAssign*/ true);
6590 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
6591 /*IsSigned=*/true);
6592 }
6593 return Bld.getInt32(0);
6594 }
6595 case OMPD_target_parallel:
6596 case OMPD_target_parallel_for:
6597 case OMPD_target_parallel_for_simd:
6598 case OMPD_target_simd:
6599 return Bld.getInt32(1);
6600 case OMPD_parallel:
6601 case OMPD_for:
6602 case OMPD_parallel_for:
6603 case OMPD_parallel_sections:
6604 case OMPD_for_simd:
6605 case OMPD_parallel_for_simd:
6606 case OMPD_cancel:
6607 case OMPD_cancellation_point:
6608 case OMPD_ordered:
6609 case OMPD_threadprivate:
6610 case OMPD_allocate:
6611 case OMPD_task:
6612 case OMPD_simd:
6613 case OMPD_sections:
6614 case OMPD_section:
6615 case OMPD_single:
6616 case OMPD_master:
6617 case OMPD_critical:
6618 case OMPD_taskyield:
6619 case OMPD_barrier:
6620 case OMPD_taskwait:
6621 case OMPD_taskgroup:
6622 case OMPD_atomic:
6623 case OMPD_flush:
6624 case OMPD_teams:
6625 case OMPD_target_data:
6626 case OMPD_target_exit_data:
6627 case OMPD_target_enter_data:
6628 case OMPD_distribute:
6629 case OMPD_distribute_simd:
6630 case OMPD_distribute_parallel_for:
6631 case OMPD_distribute_parallel_for_simd:
6632 case OMPD_teams_distribute:
6633 case OMPD_teams_distribute_simd:
6634 case OMPD_teams_distribute_parallel_for:
6635 case OMPD_teams_distribute_parallel_for_simd:
6636 case OMPD_target_update:
6637 case OMPD_declare_simd:
6638 case OMPD_declare_target:
6639 case OMPD_end_declare_target:
6640 case OMPD_declare_reduction:
6641 case OMPD_declare_mapper:
6642 case OMPD_taskloop:
6643 case OMPD_taskloop_simd:
6644 case OMPD_requires:
6645 case OMPD_unknown:
6646 break;
6647 }
6648 llvm_unreachable("Unexpected directive kind.");
6649}
Samuel Antaob68e2db2016-03-03 16:20:23 +00006650
Alexey Bataev5c427362019-04-10 19:11:33 +00006651static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS,
6652 llvm::Value *DefaultThreadLimitVal) {
6653 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6654 CGF.getContext(), CS->getCapturedStmt());
6655 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6656 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) {
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006657 llvm::Value *NumThreads = nullptr;
6658 llvm::Value *CondVal = nullptr;
6659 // Handle if clause. If if clause present, the number of threads is
6660 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6661 if (Dir->hasClausesOfKind<OMPIfClause>()) {
6662 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6663 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6664 const OMPIfClause *IfClause = nullptr;
6665 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) {
6666 if (C->getNameModifier() == OMPD_unknown ||
6667 C->getNameModifier() == OMPD_parallel) {
6668 IfClause = C;
6669 break;
6670 }
6671 }
6672 if (IfClause) {
6673 const Expr *Cond = IfClause->getCondition();
6674 bool Result;
6675 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6676 if (!Result)
6677 return CGF.Builder.getInt32(1);
6678 } else {
6679 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange());
6680 if (const auto *PreInit =
6681 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) {
6682 for (const auto *I : PreInit->decls()) {
6683 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6684 CGF.EmitVarDecl(cast<VarDecl>(*I));
6685 } else {
6686 CodeGenFunction::AutoVarEmission Emission =
6687 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6688 CGF.EmitAutoVarCleanups(Emission);
6689 }
6690 }
6691 }
6692 CondVal = CGF.EvaluateExprAsBool(Cond);
6693 }
6694 }
6695 }
6696 // Check the value of num_threads clause iff if clause was not specified
6697 // or is not evaluated to false.
Alexey Bataev5c427362019-04-10 19:11:33 +00006698 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) {
6699 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6700 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6701 const auto *NumThreadsClause =
6702 Dir->getSingleClause<OMPNumThreadsClause>();
6703 CodeGenFunction::LexicalScope Scope(
6704 CGF, NumThreadsClause->getNumThreads()->getSourceRange());
6705 if (const auto *PreInit =
6706 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6707 for (const auto *I : PreInit->decls()) {
6708 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6709 CGF.EmitVarDecl(cast<VarDecl>(*I));
6710 } else {
6711 CodeGenFunction::AutoVarEmission Emission =
6712 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6713 CGF.EmitAutoVarCleanups(Emission);
6714 }
6715 }
6716 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006717 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads());
Alexey Bataev5c427362019-04-10 19:11:33 +00006718 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty,
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006719 /*IsSigned=*/false);
6720 if (DefaultThreadLimitVal)
6721 NumThreads = CGF.Builder.CreateSelect(
6722 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads),
6723 DefaultThreadLimitVal, NumThreads);
6724 } else {
6725 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal
6726 : CGF.Builder.getInt32(0);
Alexey Bataev5c427362019-04-10 19:11:33 +00006727 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006728 // Process condition of the if clause.
6729 if (CondVal) {
6730 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads,
6731 CGF.Builder.getInt32(1));
6732 }
6733 return NumThreads;
Alexey Bataev5c427362019-04-10 19:11:33 +00006734 }
6735 if (isOpenMPSimdDirective(Dir->getDirectiveKind()))
6736 return CGF.Builder.getInt32(1);
6737 return DefaultThreadLimitVal;
6738 }
6739 return DefaultThreadLimitVal ? DefaultThreadLimitVal
6740 : CGF.Builder.getInt32(0);
Samuel Antaob68e2db2016-03-03 16:20:23 +00006741}
6742
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006743/// Emit the number of threads for a target directive. Inspect the
6744/// thread_limit clause associated with a teams construct combined or closely
6745/// nested with the target directive.
6746///
6747/// Emit the num_threads clause for directives such as 'target parallel' that
6748/// have no associated teams construct.
6749///
6750/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006751static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006752emitNumThreadsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006753 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006754 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6755 "Clauses associated with the teams directive expected to be emitted "
6756 "only for the host!");
6757 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6758 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6759 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006760 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006761 llvm::Value *ThreadLimitVal = nullptr;
6762 llvm::Value *NumThreadsVal = nullptr;
6763 switch (DirectiveKind) {
6764 case OMPD_target: {
6765 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6766 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6767 return NumThreads;
6768 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6769 CGF.getContext(), CS->getCapturedStmt());
6770 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6771 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) {
6772 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6773 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6774 const auto *ThreadLimitClause =
6775 Dir->getSingleClause<OMPThreadLimitClause>();
6776 CodeGenFunction::LexicalScope Scope(
6777 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange());
6778 if (const auto *PreInit =
6779 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6780 for (const auto *I : PreInit->decls()) {
6781 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6782 CGF.EmitVarDecl(cast<VarDecl>(*I));
6783 } else {
6784 CodeGenFunction::AutoVarEmission Emission =
6785 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6786 CGF.EmitAutoVarCleanups(Emission);
6787 }
6788 }
6789 }
6790 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6791 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6792 ThreadLimitVal =
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006793 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*IsSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006794 }
6795 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) &&
6796 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) {
6797 CS = Dir->getInnermostCapturedStmt();
6798 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6799 CGF.getContext(), CS->getCapturedStmt());
6800 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6801 }
6802 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) &&
6803 !isOpenMPSimdDirective(Dir->getDirectiveKind())) {
6804 CS = Dir->getInnermostCapturedStmt();
6805 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6806 return NumThreads;
6807 }
6808 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind()))
6809 return Bld.getInt32(1);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006810 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006811 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6812 }
6813 case OMPD_target_teams: {
6814 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6815 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6816 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6817 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6818 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6819 ThreadLimitVal =
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006820 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*IsSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006821 }
6822 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6823 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6824 return NumThreads;
6825 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6826 CGF.getContext(), CS->getCapturedStmt());
6827 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6828 if (Dir->getDirectiveKind() == OMPD_distribute) {
6829 CS = Dir->getInnermostCapturedStmt();
6830 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6831 return NumThreads;
6832 }
6833 }
6834 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6835 }
6836 case OMPD_target_teams_distribute:
6837 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6838 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6839 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6840 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6841 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6842 ThreadLimitVal =
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006843 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*IsSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006844 }
6845 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal);
6846 case OMPD_target_parallel:
6847 case OMPD_target_parallel_for:
6848 case OMPD_target_parallel_for_simd:
6849 case OMPD_target_teams_distribute_parallel_for:
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006850 case OMPD_target_teams_distribute_parallel_for_simd: {
6851 llvm::Value *CondVal = nullptr;
6852 // Handle if clause. If if clause present, the number of threads is
6853 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6854 if (D.hasClausesOfKind<OMPIfClause>()) {
6855 const OMPIfClause *IfClause = nullptr;
6856 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) {
6857 if (C->getNameModifier() == OMPD_unknown ||
6858 C->getNameModifier() == OMPD_parallel) {
6859 IfClause = C;
6860 break;
6861 }
6862 }
6863 if (IfClause) {
6864 const Expr *Cond = IfClause->getCondition();
6865 bool Result;
6866 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6867 if (!Result)
6868 return Bld.getInt32(1);
6869 } else {
6870 CodeGenFunction::RunCleanupsScope Scope(CGF);
6871 CondVal = CGF.EvaluateExprAsBool(Cond);
6872 }
6873 }
6874 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006875 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6876 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6877 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6878 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6879 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6880 ThreadLimitVal =
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006881 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*IsSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006882 }
6883 if (D.hasClausesOfKind<OMPNumThreadsClause>()) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006884 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
Alexey Bataev5c427362019-04-10 19:11:33 +00006885 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>();
6886 llvm::Value *NumThreads = CGF.EmitScalarExpr(
6887 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true);
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006888 NumThreadsVal =
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006889 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*IsSigned=*/false);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006890 ThreadLimitVal = ThreadLimitVal
Alexey Bataev5c427362019-04-10 19:11:33 +00006891 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal,
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006892 ThreadLimitVal),
6893 NumThreadsVal, ThreadLimitVal)
6894 : NumThreadsVal;
Alexey Bataev50a1c782017-12-01 21:31:08 +00006895 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006896 if (!ThreadLimitVal)
6897 ThreadLimitVal = Bld.getInt32(0);
6898 if (CondVal)
6899 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1));
6900 return ThreadLimitVal;
6901 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006902 case OMPD_target_teams_distribute_simd:
6903 case OMPD_target_simd:
6904 return Bld.getInt32(1);
6905 case OMPD_parallel:
6906 case OMPD_for:
6907 case OMPD_parallel_for:
6908 case OMPD_parallel_sections:
6909 case OMPD_for_simd:
6910 case OMPD_parallel_for_simd:
6911 case OMPD_cancel:
6912 case OMPD_cancellation_point:
6913 case OMPD_ordered:
6914 case OMPD_threadprivate:
6915 case OMPD_allocate:
6916 case OMPD_task:
6917 case OMPD_simd:
6918 case OMPD_sections:
6919 case OMPD_section:
6920 case OMPD_single:
6921 case OMPD_master:
6922 case OMPD_critical:
6923 case OMPD_taskyield:
6924 case OMPD_barrier:
6925 case OMPD_taskwait:
6926 case OMPD_taskgroup:
6927 case OMPD_atomic:
6928 case OMPD_flush:
6929 case OMPD_teams:
6930 case OMPD_target_data:
6931 case OMPD_target_exit_data:
6932 case OMPD_target_enter_data:
6933 case OMPD_distribute:
6934 case OMPD_distribute_simd:
6935 case OMPD_distribute_parallel_for:
6936 case OMPD_distribute_parallel_for_simd:
6937 case OMPD_teams_distribute:
6938 case OMPD_teams_distribute_simd:
6939 case OMPD_teams_distribute_parallel_for:
6940 case OMPD_teams_distribute_parallel_for_simd:
6941 case OMPD_target_update:
6942 case OMPD_declare_simd:
6943 case OMPD_declare_target:
6944 case OMPD_end_declare_target:
6945 case OMPD_declare_reduction:
6946 case OMPD_declare_mapper:
6947 case OMPD_taskloop:
6948 case OMPD_taskloop_simd:
6949 case OMPD_requires:
6950 case OMPD_unknown:
6951 break;
Samuel Antaob68e2db2016-03-03 16:20:23 +00006952 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006953 llvm_unreachable("Unsupported directive kind.");
Samuel Antaob68e2db2016-03-03 16:20:23 +00006954}
6955
Samuel Antao86ace552016-04-27 22:40:57 +00006956namespace {
Alexey Bataevb3638132018-07-19 16:34:13 +00006957LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
6958
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006959// Utility to handle information from clauses associated with a given
Samuel Antao86ace552016-04-27 22:40:57 +00006960// construct that use mappable expressions (e.g. 'map' clause, 'to' clause).
6961// It provides a convenient interface to obtain the information and generate
6962// code for that information.
6963class MappableExprsHandler {
6964public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006965 /// Values for bit flags used to specify the mapping type for
Samuel Antao86ace552016-04-27 22:40:57 +00006966 /// offloading.
Alexey Bataevb3638132018-07-19 16:34:13 +00006967 enum OpenMPOffloadMappingFlags : uint64_t {
6968 /// No flags
6969 OMP_MAP_NONE = 0x0,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006970 /// Allocate memory on the device and move data from host to device.
Samuel Antao86ace552016-04-27 22:40:57 +00006971 OMP_MAP_TO = 0x01,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006972 /// Allocate memory on the device and move data from device to host.
Samuel Antao86ace552016-04-27 22:40:57 +00006973 OMP_MAP_FROM = 0x02,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006974 /// Always perform the requested mapping action on the element, even
Samuel Antao86ace552016-04-27 22:40:57 +00006975 /// if it was already mapped before.
6976 OMP_MAP_ALWAYS = 0x04,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006977 /// Delete the element from the device environment, ignoring the
Samuel Antao86ace552016-04-27 22:40:57 +00006978 /// current reference count associated with the element.
Samuel Antao6782e942016-05-26 16:48:10 +00006979 OMP_MAP_DELETE = 0x08,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006980 /// The element being mapped is a pointer-pointee pair; both the
George Rokos065755d2017-11-07 18:27:04 +00006981 /// pointer and the pointee should be mapped.
6982 OMP_MAP_PTR_AND_OBJ = 0x10,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006983 /// This flags signals that the base address of an entry should be
George Rokos065755d2017-11-07 18:27:04 +00006984 /// passed to the target kernel as an argument.
6985 OMP_MAP_TARGET_PARAM = 0x20,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006986 /// Signal that the runtime library has to return the device pointer
George Rokos065755d2017-11-07 18:27:04 +00006987 /// in the current position for the data being mapped. Used when we have the
6988 /// use_device_ptr clause.
6989 OMP_MAP_RETURN_PARAM = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006990 /// This flag signals that the reference being passed is a pointer to
Samuel Antaod486f842016-05-26 16:53:38 +00006991 /// private data.
George Rokos065755d2017-11-07 18:27:04 +00006992 OMP_MAP_PRIVATE = 0x80,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006993 /// Pass the element to the device by value.
George Rokos065755d2017-11-07 18:27:04 +00006994 OMP_MAP_LITERAL = 0x100,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00006995 /// Implicit map
6996 OMP_MAP_IMPLICIT = 0x200,
Alexey Bataevb3638132018-07-19 16:34:13 +00006997 /// The 16 MSBs of the flags indicate whether the entry is member of some
6998 /// struct/class.
6999 OMP_MAP_MEMBER_OF = 0xffff000000000000,
7000 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF),
Samuel Antao86ace552016-04-27 22:40:57 +00007001 };
7002
Samuel Antaocc10b852016-07-28 14:23:26 +00007003 /// Class that associates information with a base pointer to be passed to the
7004 /// runtime library.
7005 class BasePointerInfo {
7006 /// The base pointer.
7007 llvm::Value *Ptr = nullptr;
7008 /// The base declaration that refers to this device pointer, or null if
7009 /// there is none.
7010 const ValueDecl *DevPtrDecl = nullptr;
7011
7012 public:
7013 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr)
7014 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {}
7015 llvm::Value *operator*() const { return Ptr; }
7016 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; }
7017 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; }
7018 };
7019
Alexey Bataevb3638132018-07-19 16:34:13 +00007020 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>;
7021 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>;
7022 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>;
7023
7024 /// Map between a struct and the its lowest & highest elements which have been
7025 /// mapped.
7026 /// [ValueDecl *] --> {LE(FieldIndex, Pointer),
7027 /// HE(FieldIndex, Pointer)}
7028 struct StructRangeInfoTy {
7029 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = {
7030 0, Address::invalid()};
7031 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = {
7032 0, Address::invalid()};
7033 Address Base = Address::invalid();
7034 };
Samuel Antao86ace552016-04-27 22:40:57 +00007035
7036private:
Alexey Bataevb3638132018-07-19 16:34:13 +00007037 /// Kind that defines how a device pointer has to be returned.
7038 struct MapInfo {
7039 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
7040 OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
Kelvin Lief579432018-12-18 22:18:41 +00007041 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataevb3638132018-07-19 16:34:13 +00007042 bool ReturnDevicePointer = false;
7043 bool IsImplicit = false;
7044
7045 MapInfo() = default;
7046 MapInfo(
7047 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Kelvin Lief579432018-12-18 22:18:41 +00007048 OpenMPMapClauseKind MapType,
7049 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007050 bool ReturnDevicePointer, bool IsImplicit)
Kelvin Lief579432018-12-18 22:18:41 +00007051 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
Alexey Bataevb3638132018-07-19 16:34:13 +00007052 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {}
7053 };
7054
7055 /// If use_device_ptr is used on a pointer which is a struct member and there
7056 /// is no map information about it, then emission of that entry is deferred
7057 /// until the whole struct has been processed.
7058 struct DeferredDevicePtrEntryTy {
7059 const Expr *IE = nullptr;
7060 const ValueDecl *VD = nullptr;
7061
7062 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD)
7063 : IE(IE), VD(VD) {}
7064 };
7065
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007066 /// Directive from where the map clauses were extracted.
Samuel Antao44bcdb32016-07-28 15:31:29 +00007067 const OMPExecutableDirective &CurDir;
Samuel Antao86ace552016-04-27 22:40:57 +00007068
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007069 /// Function the directive is being generated for.
Samuel Antao86ace552016-04-27 22:40:57 +00007070 CodeGenFunction &CGF;
7071
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007072 /// Set of all first private variables in the current directive.
Samuel Antaod486f842016-05-26 16:53:38 +00007073 llvm::SmallPtrSet<const VarDecl *, 8> FirstPrivateDecls;
7074
Samuel Antao6890b092016-07-28 14:25:09 +00007075 /// Map between device pointer declarations and their expression components.
7076 /// The key value for declarations in 'this' is null.
7077 llvm::DenseMap<
7078 const ValueDecl *,
7079 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7080 DevPointersMap;
7081
Samuel Antao86ace552016-04-27 22:40:57 +00007082 llvm::Value *getExprTypeSize(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007083 QualType ExprTy = E->getType().getCanonicalType();
Samuel Antao86ace552016-04-27 22:40:57 +00007084
7085 // Reference types are ignored for mapping purposes.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007086 if (const auto *RefTy = ExprTy->getAs<ReferenceType>())
Samuel Antao86ace552016-04-27 22:40:57 +00007087 ExprTy = RefTy->getPointeeType().getCanonicalType();
7088
7089 // Given that an array section is considered a built-in type, we need to
7090 // do the calculation based on the length of the section instead of relying
7091 // on CGF.getTypeSize(E->getType()).
7092 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) {
7093 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType(
7094 OAE->getBase()->IgnoreParenImpCasts())
7095 .getCanonicalType();
7096
7097 // If there is no length associated with the expression, that means we
7098 // are using the whole length of the base.
7099 if (!OAE->getLength() && OAE->getColonLoc().isValid())
7100 return CGF.getTypeSize(BaseTy);
7101
7102 llvm::Value *ElemSize;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007103 if (const auto *PTy = BaseTy->getAs<PointerType>()) {
Samuel Antao86ace552016-04-27 22:40:57 +00007104 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007105 } else {
7106 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr());
Samuel Antao86ace552016-04-27 22:40:57 +00007107 assert(ATy && "Expecting array type if not a pointer type.");
7108 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType());
7109 }
7110
7111 // If we don't have a length at this point, that is because we have an
7112 // array section with a single element.
7113 if (!OAE->getLength())
7114 return ElemSize;
7115
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007116 llvm::Value *LengthVal = CGF.EmitScalarExpr(OAE->getLength());
Samuel Antao86ace552016-04-27 22:40:57 +00007117 LengthVal =
7118 CGF.Builder.CreateIntCast(LengthVal, CGF.SizeTy, /*isSigned=*/false);
7119 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize);
7120 }
7121 return CGF.getTypeSize(ExprTy);
7122 }
7123
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007124 /// Return the corresponding bits for a given map clause modifier. Add
Samuel Antao86ace552016-04-27 22:40:57 +00007125 /// a flag marking the map as a pointer if requested. Add a flag marking the
Samuel Antao6782e942016-05-26 16:48:10 +00007126 /// map as the first one of a series of maps that relate to the same map
7127 /// expression.
Kelvin Lief579432018-12-18 22:18:41 +00007128 OpenMPOffloadMappingFlags getMapTypeBits(
7129 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
7130 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const {
Alexey Bataevb3638132018-07-19 16:34:13 +00007131 OpenMPOffloadMappingFlags Bits =
7132 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE;
Samuel Antao86ace552016-04-27 22:40:57 +00007133 switch (MapType) {
7134 case OMPC_MAP_alloc:
Samuel Antao6782e942016-05-26 16:48:10 +00007135 case OMPC_MAP_release:
7136 // alloc and release is the default behavior in the runtime library, i.e.
7137 // if we don't pass any bits alloc/release that is what the runtime is
7138 // going to do. Therefore, we don't need to signal anything for these two
7139 // type modifiers.
Samuel Antao86ace552016-04-27 22:40:57 +00007140 break;
7141 case OMPC_MAP_to:
Alexey Bataevb3638132018-07-19 16:34:13 +00007142 Bits |= OMP_MAP_TO;
Samuel Antao86ace552016-04-27 22:40:57 +00007143 break;
7144 case OMPC_MAP_from:
Alexey Bataevb3638132018-07-19 16:34:13 +00007145 Bits |= OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007146 break;
7147 case OMPC_MAP_tofrom:
Alexey Bataevb3638132018-07-19 16:34:13 +00007148 Bits |= OMP_MAP_TO | OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007149 break;
7150 case OMPC_MAP_delete:
Alexey Bataevb3638132018-07-19 16:34:13 +00007151 Bits |= OMP_MAP_DELETE;
Samuel Antao86ace552016-04-27 22:40:57 +00007152 break;
Alexey Bataevb3638132018-07-19 16:34:13 +00007153 case OMPC_MAP_unknown:
Samuel Antao86ace552016-04-27 22:40:57 +00007154 llvm_unreachable("Unexpected map type!");
Samuel Antao86ace552016-04-27 22:40:57 +00007155 }
7156 if (AddPtrFlag)
George Rokos065755d2017-11-07 18:27:04 +00007157 Bits |= OMP_MAP_PTR_AND_OBJ;
7158 if (AddIsTargetParamFlag)
7159 Bits |= OMP_MAP_TARGET_PARAM;
Kelvin Lief579432018-12-18 22:18:41 +00007160 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always)
7161 != MapModifiers.end())
Samuel Antao86ace552016-04-27 22:40:57 +00007162 Bits |= OMP_MAP_ALWAYS;
7163 return Bits;
7164 }
7165
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007166 /// Return true if the provided expression is a final array section. A
Samuel Antao86ace552016-04-27 22:40:57 +00007167 /// final array section, is one whose length can't be proved to be one.
7168 bool isFinalArraySectionExpression(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007169 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
Samuel Antao86ace552016-04-27 22:40:57 +00007170
7171 // It is not an array section and therefore not a unity-size one.
7172 if (!OASE)
7173 return false;
7174
7175 // An array section with no colon always refer to a single element.
7176 if (OASE->getColonLoc().isInvalid())
7177 return false;
7178
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007179 const Expr *Length = OASE->getLength();
Samuel Antao86ace552016-04-27 22:40:57 +00007180
7181 // If we don't have a length we have to check if the array has size 1
7182 // for this dimension. Also, we should always expect a length if the
7183 // base type is pointer.
7184 if (!Length) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007185 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType(
7186 OASE->getBase()->IgnoreParenImpCasts())
7187 .getCanonicalType();
7188 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
Samuel Antao86ace552016-04-27 22:40:57 +00007189 return ATy->getSize().getSExtValue() != 1;
7190 // If we don't have a constant dimension length, we have to consider
7191 // the current section as having any size, so it is not necessarily
7192 // unitary. If it happen to be unity size, that's user fault.
7193 return true;
7194 }
7195
7196 // Check if the length evaluates to 1.
Fangrui Song407659a2018-11-30 23:41:18 +00007197 Expr::EvalResult Result;
7198 if (!Length->EvaluateAsInt(Result, CGF.getContext()))
Samuel Antao86ace552016-04-27 22:40:57 +00007199 return true; // Can have more that size 1.
7200
Fangrui Song407659a2018-11-30 23:41:18 +00007201 llvm::APSInt ConstLength = Result.Val.getInt();
Samuel Antao86ace552016-04-27 22:40:57 +00007202 return ConstLength.getSExtValue() != 1;
7203 }
7204
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007205 /// Generate the base pointers, section pointers, sizes and map type
Samuel Antao86ace552016-04-27 22:40:57 +00007206 /// bits for the provided map type, map modifier, and expression components.
7207 /// \a IsFirstComponent should be set to true if the provided set of
7208 /// components is the first associated with a capture.
7209 void generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00007210 OpenMPMapClauseKind MapType,
7211 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Samuel Antao86ace552016-04-27 22:40:57 +00007212 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Samuel Antaocc10b852016-07-28 14:23:26 +00007213 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007214 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
Alexey Bataevb3638132018-07-19 16:34:13 +00007215 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007216 bool IsImplicit,
7217 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7218 OverlappedElements = llvm::None) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007219 // The following summarizes what has to be generated for each map and the
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00007220 // types below. The generated information is expressed in this order:
Samuel Antao86ace552016-04-27 22:40:57 +00007221 // base pointer, section pointer, size, flags
7222 // (to add to the ones that come from the map type and modifier).
7223 //
7224 // double d;
7225 // int i[100];
7226 // float *p;
7227 //
7228 // struct S1 {
7229 // int i;
7230 // float f[50];
7231 // }
7232 // struct S2 {
7233 // int i;
7234 // float f[50];
7235 // S1 s;
7236 // double *p;
7237 // struct S2 *ps;
7238 // }
7239 // S2 s;
7240 // S2 *ps;
7241 //
7242 // map(d)
Alexey Bataevb3638132018-07-19 16:34:13 +00007243 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007244 //
7245 // map(i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007246 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007247 //
7248 // map(i[1:23])
Alexey Bataevb3638132018-07-19 16:34:13 +00007249 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007250 //
7251 // map(p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007252 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007253 //
7254 // map(p[1:24])
Alexey Bataevb3638132018-07-19 16:34:13 +00007255 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007256 //
7257 // map(s)
Alexey Bataevb3638132018-07-19 16:34:13 +00007258 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007259 //
7260 // map(s.i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007261 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007262 //
7263 // map(s.s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007264 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007265 //
7266 // map(s.p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007267 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007268 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007269 // map(to: s.p[:22])
7270 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*)
7271 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**)
7272 // &(s.p), &(s.p[0]), 22*sizeof(double),
7273 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***)
7274 // (*) alloc space for struct members, only this is a target parameter
7275 // (**) map the pointer (nothing to be mapped in this example) (the compiler
7276 // optimizes this entry out, same in the examples below)
7277 // (***) map the pointee (map: to)
Samuel Antao86ace552016-04-27 22:40:57 +00007278 //
7279 // map(s.ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007280 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007281 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007282 // map(from: s.ps->s.i)
7283 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7284 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7285 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007286 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007287 // map(to: s.ps->ps)
7288 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7289 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7290 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007291 //
7292 // map(s.ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007293 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7294 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7295 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7296 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007297 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007298 // map(to: s.ps->ps->s.f[:22])
7299 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7300 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7301 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7302 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007303 //
7304 // map(ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007305 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007306 //
7307 // map(ps->i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007308 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007309 //
7310 // map(ps->s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007311 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007312 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007313 // map(from: ps->p)
7314 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007315 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007316 // map(to: ps->p[:22])
7317 // ps, &(ps->p), sizeof(double*), TARGET_PARAM
7318 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1)
7319 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007320 //
7321 // map(ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007322 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007323 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007324 // map(from: ps->ps->s.i)
7325 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7326 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7327 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007328 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007329 // map(from: ps->ps->ps)
7330 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7331 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7332 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007333 //
7334 // map(ps->ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007335 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7336 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7337 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7338 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007339 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007340 // map(to: ps->ps->ps->s.f[:22])
7341 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7342 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7343 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7344 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
7345 //
7346 // map(to: s.f[:22]) map(from: s.p[:33])
7347 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) +
7348 // sizeof(double*) (**), TARGET_PARAM
7349 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO
7350 // &s, &(s.p), sizeof(double*), MEMBER_OF(1)
7351 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7352 // (*) allocate contiguous space needed to fit all mapped members even if
7353 // we allocate space for members not mapped (in this example,
7354 // s.f[22..49] and s.s are not mapped, yet we must allocate space for
7355 // them as well because they fall between &s.f[0] and &s.p)
7356 //
7357 // map(from: s.f[:22]) map(to: ps->p[:33])
7358 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM
7359 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7360 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*)
7361 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO
7362 // (*) the struct this entry pertains to is the 2nd element in the list of
7363 // arguments, hence MEMBER_OF(2)
7364 //
7365 // map(from: s.f[:22], s.s) map(to: ps->p[:33])
7366 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM
7367 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM
7368 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM
7369 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7370 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*)
7371 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO
7372 // (*) the struct this entry pertains to is the 4th element in the list
7373 // of arguments, hence MEMBER_OF(4)
Samuel Antao86ace552016-04-27 22:40:57 +00007374
7375 // Track if the map information being generated is the first for a capture.
7376 bool IsCaptureFirstInfo = IsFirstComponentList;
Alexey Bataev92327c52018-03-26 16:40:55 +00007377 bool IsLink = false; // Is this variable a "declare target link"?
Samuel Antao86ace552016-04-27 22:40:57 +00007378
7379 // Scan the components from the base to the complete expression.
7380 auto CI = Components.rbegin();
7381 auto CE = Components.rend();
7382 auto I = CI;
7383
7384 // Track if the map information being generated is the first for a list of
7385 // components.
7386 bool IsExpressionFirstInfo = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00007387 Address BP = Address::invalid();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007388 const Expr *AssocExpr = I->getAssociatedExpression();
7389 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7390 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
Samuel Antao86ace552016-04-27 22:40:57 +00007391
Patrick Lystere13b1e32019-01-02 19:28:48 +00007392 if (isa<MemberExpr>(AssocExpr)) {
Samuel Antao86ace552016-04-27 22:40:57 +00007393 // The base is the 'this' pointer. The content of the pointer is going
7394 // to be the base of the field being mapped.
Alexey Bataevb3638132018-07-19 16:34:13 +00007395 BP = CGF.LoadCXXThisAddress();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007396 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7397 (OASE &&
7398 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
7399 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
Samuel Antao86ace552016-04-27 22:40:57 +00007400 } else {
7401 // The base is the reference to the variable.
7402 // BP = &Var.
Patrick Lystere13b1e32019-01-02 19:28:48 +00007403 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
Alexey Bataev92327c52018-03-26 16:40:55 +00007404 if (const auto *VD =
7405 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7406 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00007407 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
Alexey Bataev2c1dffe2018-04-16 20:34:41 +00007408 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) {
7409 IsLink = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00007410 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetLink(VD);
Alexey Bataev2c1dffe2018-04-16 20:34:41 +00007411 }
Alexey Bataev92327c52018-03-26 16:40:55 +00007412 }
Samuel Antao86ace552016-04-27 22:40:57 +00007413
7414 // If the variable is a pointer and is being dereferenced (i.e. is not
Nico Webera6916892016-06-10 18:53:04 +00007415 // the last component), the base has to be the pointer itself, not its
Samuel Antao403ffd42016-07-27 22:49:49 +00007416 // reference. References are ignored for mapping purposes.
7417 QualType Ty =
7418 I->getAssociatedDeclaration()->getType().getNonReferenceType();
7419 if (Ty->isAnyPointerType() && std::next(I) != CE) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007420 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
Samuel Antao86ace552016-04-27 22:40:57 +00007421
7422 // We do not need to generate individual map information for the
7423 // pointer, it can be associated with the combined storage.
7424 ++I;
7425 }
7426 }
7427
Alexey Bataevb3638132018-07-19 16:34:13 +00007428 // Track whether a component of the list should be marked as MEMBER_OF some
7429 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry
7430 // in a component list should be marked as MEMBER_OF, all subsequent entries
7431 // do not belong to the base struct. E.g.
7432 // struct S2 s;
7433 // s.ps->ps->ps->f[:]
7434 // (1) (2) (3) (4)
7435 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a
7436 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3)
7437 // is the pointee of ps(2) which is not member of struct s, so it should not
7438 // be marked as such (it is still PTR_AND_OBJ).
7439 // The variable is initialized to false so that PTR_AND_OBJ entries which
7440 // are not struct members are not considered (e.g. array of pointers to
7441 // data).
7442 bool ShouldBeMemberOf = false;
7443
7444 // Variable keeping track of whether or not we have encountered a component
7445 // in the component list which is a member expression. Useful when we have a
7446 // pointer or a final array section, in which case it is the previous
7447 // component in the list which tells us whether we have a member expression.
7448 // E.g. X.f[:]
7449 // While processing the final array section "[:]" it is "f" which tells us
7450 // whether we are dealing with a member of a declared struct.
7451 const MemberExpr *EncounteredME = nullptr;
7452
Samuel Antao86ace552016-04-27 22:40:57 +00007453 for (; I != CE; ++I) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007454 // If the current component is member of a struct (parent struct) mark it.
7455 if (!EncounteredME) {
7456 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7457 // If we encounter a PTR_AND_OBJ entry from now on it should be marked
7458 // as MEMBER_OF the parent struct.
7459 if (EncounteredME)
7460 ShouldBeMemberOf = true;
7461 }
7462
Samuel Antao86ace552016-04-27 22:40:57 +00007463 auto Next = std::next(I);
7464
7465 // We need to generate the addresses and sizes if this is the last
7466 // component, if the component is a pointer or if it is an array section
7467 // whose length can't be proved to be one. If this is a pointer, it
7468 // becomes the base address for the following components.
7469
7470 // A final array section, is one whose length can't be proved to be one.
7471 bool IsFinalArraySection =
7472 isFinalArraySectionExpression(I->getAssociatedExpression());
7473
7474 // Get information on whether the element is a pointer. Have to do a
7475 // special treatment for array sections given that they are built-in
7476 // types.
7477 const auto *OASE =
7478 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression());
7479 bool IsPointer =
Alexey Bataevb3638132018-07-19 16:34:13 +00007480 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE)
7481 .getCanonicalType()
7482 ->isAnyPointerType()) ||
Samuel Antao86ace552016-04-27 22:40:57 +00007483 I->getAssociatedExpression()->getType()->isAnyPointerType();
7484
7485 if (Next == CE || IsPointer || IsFinalArraySection) {
Samuel Antao86ace552016-04-27 22:40:57 +00007486 // If this is not the last component, we expect the pointer to be
7487 // associated with an array expression or member expression.
7488 assert((Next == CE ||
7489 isa<MemberExpr>(Next->getAssociatedExpression()) ||
7490 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||
7491 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) &&
7492 "Unexpected expression");
7493
Alexey Bataevb3638132018-07-19 16:34:13 +00007494 Address LB =
7495 CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getAddress();
Samuel Antao86ace552016-04-27 22:40:57 +00007496
Alexey Bataevb3638132018-07-19 16:34:13 +00007497 // If this component is a pointer inside the base struct then we don't
7498 // need to create any entry for it - it will be combined with the object
7499 // it is pointing to into a single PTR_AND_OBJ entry.
7500 bool IsMemberPointer =
7501 IsPointer && EncounteredME &&
7502 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) ==
7503 EncounteredME);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007504 if (!OverlappedElements.empty()) {
7505 // Handle base element with the info for overlapped elements.
7506 assert(!PartialStruct.Base.isValid() && "The base element is set.");
7507 assert(Next == CE &&
7508 "Expected last element for the overlapped elements.");
7509 assert(!IsPointer &&
7510 "Unexpected base element with the pointer type.");
7511 // Mark the whole struct as the struct that requires allocation on the
7512 // device.
7513 PartialStruct.LowestElem = {0, LB};
7514 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(
7515 I->getAssociatedExpression()->getType());
7516 Address HB = CGF.Builder.CreateConstGEP(
7517 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB,
7518 CGF.VoidPtrTy),
James Y Knight751fe282019-02-09 22:22:28 +00007519 TypeSize.getQuantity() - 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007520 PartialStruct.HighestElem = {
7521 std::numeric_limits<decltype(
7522 PartialStruct.HighestElem.first)>::max(),
7523 HB};
7524 PartialStruct.Base = BP;
7525 // Emit data for non-overlapped data.
7526 OpenMPOffloadMappingFlags Flags =
7527 OMP_MAP_MEMBER_OF |
Kelvin Lief579432018-12-18 22:18:41 +00007528 getMapTypeBits(MapType, MapModifiers, IsImplicit,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007529 /*AddPtrFlag=*/false,
7530 /*AddIsTargetParamFlag=*/false);
7531 LB = BP;
7532 llvm::Value *Size = nullptr;
7533 // Do bitcopy of all non-overlapped structure elements.
7534 for (OMPClauseMappableExprCommon::MappableExprComponentListRef
7535 Component : OverlappedElements) {
7536 Address ComponentLB = Address::invalid();
7537 for (const OMPClauseMappableExprCommon::MappableComponent &MC :
7538 Component) {
7539 if (MC.getAssociatedDeclaration()) {
7540 ComponentLB =
7541 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
7542 .getAddress();
7543 Size = CGF.Builder.CreatePtrDiff(
7544 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()),
7545 CGF.EmitCastToVoidPtr(LB.getPointer()));
7546 break;
7547 }
7548 }
7549 BasePointers.push_back(BP.getPointer());
7550 Pointers.push_back(LB.getPointer());
7551 Sizes.push_back(Size);
7552 Types.push_back(Flags);
James Y Knight751fe282019-02-09 22:22:28 +00007553 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007554 }
7555 BasePointers.push_back(BP.getPointer());
7556 Pointers.push_back(LB.getPointer());
7557 Size = CGF.Builder.CreatePtrDiff(
7558 CGF.EmitCastToVoidPtr(
James Y Knight751fe282019-02-09 22:22:28 +00007559 CGF.Builder.CreateConstGEP(HB, 1).getPointer()),
Alexey Bataeve82445f2018-09-20 13:54:02 +00007560 CGF.EmitCastToVoidPtr(LB.getPointer()));
7561 Sizes.push_back(Size);
7562 Types.push_back(Flags);
7563 break;
7564 }
7565 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
Alexey Bataevb3638132018-07-19 16:34:13 +00007566 if (!IsMemberPointer) {
7567 BasePointers.push_back(BP.getPointer());
7568 Pointers.push_back(LB.getPointer());
7569 Sizes.push_back(Size);
Samuel Antao03a3cec2016-07-27 22:52:16 +00007570
Alexey Bataevb3638132018-07-19 16:34:13 +00007571 // We need to add a pointer flag for each map that comes from the
7572 // same expression except for the first one. We also need to signal
7573 // this map is the first one that relates with the current capture
7574 // (there is a set of entries for each capture).
7575 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
Kelvin Lief579432018-12-18 22:18:41 +00007576 MapType, MapModifiers, IsImplicit,
Alexey Bataevb3638132018-07-19 16:34:13 +00007577 !IsExpressionFirstInfo || IsLink, IsCaptureFirstInfo && !IsLink);
7578
7579 if (!IsExpressionFirstInfo) {
7580 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
7581 // then we reset the TO/FROM/ALWAYS/DELETE flags.
7582 if (IsPointer)
7583 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS |
7584 OMP_MAP_DELETE);
7585
7586 if (ShouldBeMemberOf) {
7587 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag
7588 // should be later updated with the correct value of MEMBER_OF.
7589 Flags |= OMP_MAP_MEMBER_OF;
7590 // From now on, all subsequent PTR_AND_OBJ entries should not be
7591 // marked as MEMBER_OF.
7592 ShouldBeMemberOf = false;
7593 }
7594 }
7595
7596 Types.push_back(Flags);
Samuel Antao03a3cec2016-07-27 22:52:16 +00007597 }
7598
Alexey Bataevb3638132018-07-19 16:34:13 +00007599 // If we have encountered a member expression so far, keep track of the
7600 // mapped member. If the parent is "*this", then the value declaration
7601 // is nullptr.
7602 if (EncounteredME) {
7603 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl());
7604 unsigned FieldIndex = FD->getFieldIndex();
Samuel Antao03a3cec2016-07-27 22:52:16 +00007605
Alexey Bataevb3638132018-07-19 16:34:13 +00007606 // Update info about the lowest and highest elements for this struct
7607 if (!PartialStruct.Base.isValid()) {
7608 PartialStruct.LowestElem = {FieldIndex, LB};
7609 PartialStruct.HighestElem = {FieldIndex, LB};
7610 PartialStruct.Base = BP;
7611 } else if (FieldIndex < PartialStruct.LowestElem.first) {
7612 PartialStruct.LowestElem = {FieldIndex, LB};
7613 } else if (FieldIndex > PartialStruct.HighestElem.first) {
7614 PartialStruct.HighestElem = {FieldIndex, LB};
7615 }
7616 }
Samuel Antao86ace552016-04-27 22:40:57 +00007617
7618 // If we have a final array section, we are done with this expression.
7619 if (IsFinalArraySection)
7620 break;
7621
7622 // The pointer becomes the base for the next element.
7623 if (Next != CE)
7624 BP = LB;
7625
7626 IsExpressionFirstInfo = false;
7627 IsCaptureFirstInfo = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007628 }
7629 }
7630 }
7631
Alexey Bataevb3638132018-07-19 16:34:13 +00007632 /// Return the adjusted map modifiers if the declaration a capture refers to
7633 /// appears in a first-private clause. This is expected to be used only with
7634 /// directives that start with 'target'.
7635 MappableExprsHandler::OpenMPOffloadMappingFlags
7636 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const {
7637 assert(Cap.capturesVariable() && "Expected capture by reference only!");
7638
7639 // A first private variable captured by reference will use only the
7640 // 'private ptr' and 'map to' flag. Return the right flags if the captured
7641 // declaration is known as first-private in this handler.
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007642 if (FirstPrivateDecls.count(Cap.getCapturedVar())) {
7643 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) &&
7644 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef)
7645 return MappableExprsHandler::OMP_MAP_ALWAYS |
7646 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataevc2b831f2019-04-02 16:03:40 +00007647 if (Cap.getCapturedVar()->getType()->isAnyPointerType())
7648 return MappableExprsHandler::OMP_MAP_TO |
7649 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ;
Alexey Bataevb3638132018-07-19 16:34:13 +00007650 return MappableExprsHandler::OMP_MAP_PRIVATE |
7651 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007652 }
Alexey Bataevb3638132018-07-19 16:34:13 +00007653 return MappableExprsHandler::OMP_MAP_TO |
7654 MappableExprsHandler::OMP_MAP_FROM;
7655 }
7656
7657 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) {
7658 // Member of is given by the 16 MSB of the flag, so rotate by 48 bits.
7659 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1)
7660 << 48);
7661 }
7662
7663 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags,
7664 OpenMPOffloadMappingFlags MemberOfFlag) {
7665 // If the entry is PTR_AND_OBJ but has not been marked with the special
7666 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be
7667 // marked as MEMBER_OF.
7668 if ((Flags & OMP_MAP_PTR_AND_OBJ) &&
7669 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF))
7670 return;
7671
7672 // Reset the placeholder value to prepare the flag for the assignment of the
7673 // proper MEMBER_OF value.
7674 Flags &= ~OMP_MAP_MEMBER_OF;
7675 Flags |= MemberOfFlag;
7676 }
7677
Alexey Bataeve82445f2018-09-20 13:54:02 +00007678 void getPlainLayout(const CXXRecordDecl *RD,
7679 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
7680 bool AsBase) const {
7681 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD);
7682
7683 llvm::StructType *St =
7684 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType();
7685
7686 unsigned NumElements = St->getNumElements();
7687 llvm::SmallVector<
7688 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
7689 RecordLayout(NumElements);
7690
7691 // Fill bases.
7692 for (const auto &I : RD->bases()) {
7693 if (I.isVirtual())
7694 continue;
7695 const auto *Base = I.getType()->getAsCXXRecordDecl();
7696 // Ignore empty bases.
7697 if (Base->isEmpty() || CGF.getContext()
7698 .getASTRecordLayout(Base)
7699 .getNonVirtualSize()
7700 .isZero())
7701 continue;
7702
7703 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
7704 RecordLayout[FieldIndex] = Base;
7705 }
7706 // Fill in virtual bases.
7707 for (const auto &I : RD->vbases()) {
7708 const auto *Base = I.getType()->getAsCXXRecordDecl();
7709 // Ignore empty bases.
7710 if (Base->isEmpty())
7711 continue;
7712 unsigned FieldIndex = RL.getVirtualBaseIndex(Base);
7713 if (RecordLayout[FieldIndex])
7714 continue;
7715 RecordLayout[FieldIndex] = Base;
7716 }
7717 // Fill in all the fields.
7718 assert(!RD->isUnion() && "Unexpected union.");
7719 for (const auto *Field : RD->fields()) {
7720 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
7721 // will fill in later.)
7722 if (!Field->isBitField()) {
7723 unsigned FieldIndex = RL.getLLVMFieldNo(Field);
7724 RecordLayout[FieldIndex] = Field;
7725 }
7726 }
7727 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
7728 &Data : RecordLayout) {
7729 if (Data.isNull())
7730 continue;
7731 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>())
7732 getPlainLayout(Base, Layout, /*AsBase=*/true);
7733 else
7734 Layout.push_back(Data.get<const FieldDecl *>());
7735 }
7736 }
7737
Alexey Bataevb3638132018-07-19 16:34:13 +00007738public:
7739 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
7740 : CurDir(Dir), CGF(CGF) {
7741 // Extract firstprivate clause information.
7742 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>())
7743 for (const auto *D : C->varlists())
7744 FirstPrivateDecls.insert(
7745 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl());
7746 // Extract device pointer clause information.
7747 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
7748 for (auto L : C->component_lists())
7749 DevPointersMap[L.first].push_back(L.second);
7750 }
7751
7752 /// Generate code for the combined entry if we have a partially mapped struct
7753 /// and take care of the mapping flags of the arguments corresponding to
7754 /// individual struct members.
7755 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers,
7756 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7757 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes,
7758 const StructRangeInfoTy &PartialStruct) const {
7759 // Base is the base of the struct
7760 BasePointers.push_back(PartialStruct.Base.getPointer());
7761 // Pointer is the address of the lowest element
7762 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer();
7763 Pointers.push_back(LB);
7764 // Size is (addr of {highest+1} element) - (addr of lowest element)
7765 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer();
7766 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1);
7767 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy);
7768 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy);
7769 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr);
7770 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.SizeTy,
7771 /*isSinged=*/false);
7772 Sizes.push_back(Size);
7773 // Map type is always TARGET_PARAM
7774 Types.push_back(OMP_MAP_TARGET_PARAM);
7775 // Remove TARGET_PARAM flag from the first element
7776 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM;
7777
7778 // All other current entries will be MEMBER_OF the combined entry
7779 // (except for PTR_AND_OBJ entries which do not have a placeholder value
7780 // 0xFFFF in the MEMBER_OF field).
7781 OpenMPOffloadMappingFlags MemberOfFlag =
7782 getMemberOfFlag(BasePointers.size() - 1);
7783 for (auto &M : CurTypes)
7784 setCorrectMemberOfFlag(M, MemberOfFlag);
7785 }
7786
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007787 /// Generate all the base pointers, section pointers, sizes and map
Samuel Antaocc10b852016-07-28 14:23:26 +00007788 /// types for the extracted mappable expressions. Also, for each item that
7789 /// relates with a device pointer, a pair of the relevant declaration and
7790 /// index where it occurs is appended to the device pointers info array.
7791 void generateAllInfo(MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007792 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7793 MapFlagsArrayTy &Types) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007794 // We have to process the component lists that relate with the same
7795 // declaration in a single chunk so that we can generate the map flags
7796 // correctly. Therefore, we organize all lists in a map.
Alexey Bataev5d1c3f62017-06-27 15:46:42 +00007797 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
Samuel Antao8d2d7302016-05-26 18:30:22 +00007798
7799 // Helper function to fill the information map for the different supported
7800 // clauses.
Samuel Antaocc10b852016-07-28 14:23:26 +00007801 auto &&InfoGen = [&Info](
7802 const ValueDecl *D,
7803 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
Kelvin Lief579432018-12-18 22:18:41 +00007804 OpenMPMapClauseKind MapType,
7805 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007806 bool ReturnDevicePointer, bool IsImplicit) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007807 const ValueDecl *VD =
7808 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
Kelvin Lief579432018-12-18 22:18:41 +00007809 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007810 IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00007811 };
Samuel Antao8d2d7302016-05-26 18:30:22 +00007812
Paul Robinson78fb1322016-08-01 22:12:46 +00007813 // FIXME: MSVC 2013 seems to require this-> to find member CurDir.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007814 for (const auto *C : this->CurDir.getClausesOfKind<OMPMapClause>())
7815 for (const auto &L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007816 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(),
Alexey Bataevb3638132018-07-19 16:34:13 +00007817 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007818 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007819 for (const auto *C : this->CurDir.getClausesOfKind<OMPToClause>())
7820 for (const auto &L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007821 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007822 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007823 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007824 for (const auto *C : this->CurDir.getClausesOfKind<OMPFromClause>())
7825 for (const auto &L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007826 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007827 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007828 }
Samuel Antao86ace552016-04-27 22:40:57 +00007829
Samuel Antaocc10b852016-07-28 14:23:26 +00007830 // Look at the use_device_ptr clause information and mark the existing map
7831 // entries as such. If there is no map information for an entry in the
7832 // use_device_ptr list, we create one with map type 'alloc' and zero size
Alexey Bataevb3638132018-07-19 16:34:13 +00007833 // section. It is the user fault if that was not mapped before. If there is
7834 // no map information and the pointer is a struct member, then we defer the
7835 // emission of that entry until the whole struct has been processed.
7836 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>>
7837 DeferredInfo;
7838
Paul Robinson78fb1322016-08-01 22:12:46 +00007839 // FIXME: MSVC 2013 seems to require this-> to find member CurDir.
Alexey Bataevb3638132018-07-19 16:34:13 +00007840 for (const auto *C :
7841 this->CurDir.getClausesOfKind<OMPUseDevicePtrClause>()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007842 for (const auto &L : C->component_lists()) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007843 assert(!L.second.empty() && "Not expecting empty list of components!");
7844 const ValueDecl *VD = L.second.back().getAssociatedDeclaration();
7845 VD = cast<ValueDecl>(VD->getCanonicalDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007846 const Expr *IE = L.second.back().getAssociatedExpression();
Samuel Antaocc10b852016-07-28 14:23:26 +00007847 // If the first component is a member expression, we have to look into
7848 // 'this', which maps to null in the map of map information. Otherwise
7849 // look directly for the information.
7850 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
7851
7852 // We potentially have map information for this declaration already.
7853 // Look for the first set of components that refer to it.
7854 if (It != Info.end()) {
7855 auto CI = std::find_if(
7856 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) {
7857 return MI.Components.back().getAssociatedDeclaration() == VD;
7858 });
7859 // If we found a map entry, signal that the pointer has to be returned
7860 // and move on to the next declaration.
7861 if (CI != It->second.end()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007862 CI->ReturnDevicePointer = true;
Samuel Antaocc10b852016-07-28 14:23:26 +00007863 continue;
7864 }
7865 }
7866
7867 // We didn't find any match in our map information - generate a zero
Alexey Bataevb3638132018-07-19 16:34:13 +00007868 // size array section - if the pointer is a struct member we defer this
7869 // action until the whole struct has been processed.
Paul Robinson78fb1322016-08-01 22:12:46 +00007870 // FIXME: MSVC 2013 seems to require this-> to find member CGF.
Alexey Bataevb3638132018-07-19 16:34:13 +00007871 if (isa<MemberExpr>(IE)) {
7872 // Insert the pointer into Info to be processed by
7873 // generateInfoForComponentList. Because it is a member pointer
7874 // without a pointee, no entry will be generated for it, therefore
7875 // we need to generate one after the whole struct has been processed.
7876 // Nonetheless, generateInfoForComponentList must be called to take
7877 // the pointer into account for the calculation of the range of the
7878 // partial struct.
Kelvin Lief579432018-12-18 22:18:41 +00007879 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007880 /*ReturnDevicePointer=*/false, C->isImplicit());
7881 DeferredInfo[nullptr].emplace_back(IE, VD);
7882 } else {
7883 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar(
7884 this->CGF.EmitLValue(IE), IE->getExprLoc());
7885 BasePointers.emplace_back(Ptr, VD);
7886 Pointers.push_back(Ptr);
7887 Sizes.push_back(llvm::Constant::getNullValue(this->CGF.SizeTy));
7888 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM);
7889 }
Samuel Antaocc10b852016-07-28 14:23:26 +00007890 }
Alexey Bataevb3638132018-07-19 16:34:13 +00007891 }
Samuel Antaocc10b852016-07-28 14:23:26 +00007892
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007893 for (const auto &M : Info) {
Samuel Antao86ace552016-04-27 22:40:57 +00007894 // We need to know when we generate information for the first component
7895 // associated with a capture, because the mapping flags depend on it.
7896 bool IsFirstComponentList = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00007897
7898 // Temporary versions of arrays
7899 MapBaseValuesArrayTy CurBasePointers;
7900 MapValuesArrayTy CurPointers;
7901 MapValuesArrayTy CurSizes;
7902 MapFlagsArrayTy CurTypes;
7903 StructRangeInfoTy PartialStruct;
7904
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007905 for (const MapInfo &L : M.second) {
Samuel Antao86ace552016-04-27 22:40:57 +00007906 assert(!L.Components.empty() &&
7907 "Not expecting declaration with no component lists.");
Samuel Antaocc10b852016-07-28 14:23:26 +00007908
7909 // Remember the current base pointer index.
Alexey Bataevb3638132018-07-19 16:34:13 +00007910 unsigned CurrentBasePointersIdx = CurBasePointers.size();
Paul Robinson78fb1322016-08-01 22:12:46 +00007911 // FIXME: MSVC 2013 seems to require this-> to find the member method.
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007912 this->generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00007913 L.MapType, L.MapModifiers, L.Components, CurBasePointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007914 CurPointers, CurSizes, CurTypes, PartialStruct,
7915 IsFirstComponentList, L.IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00007916
7917 // If this entry relates with a device pointer, set the relevant
7918 // declaration and add the 'return pointer' flag.
Alexey Bataevb3638132018-07-19 16:34:13 +00007919 if (L.ReturnDevicePointer) {
7920 assert(CurBasePointers.size() > CurrentBasePointersIdx &&
Samuel Antaocc10b852016-07-28 14:23:26 +00007921 "Unexpected number of mapped base pointers.");
7922
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007923 const ValueDecl *RelevantVD =
7924 L.Components.back().getAssociatedDeclaration();
Samuel Antaocc10b852016-07-28 14:23:26 +00007925 assert(RelevantVD &&
7926 "No relevant declaration related with device pointer??");
7927
Alexey Bataevb3638132018-07-19 16:34:13 +00007928 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD);
7929 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM;
Samuel Antaocc10b852016-07-28 14:23:26 +00007930 }
Samuel Antao86ace552016-04-27 22:40:57 +00007931 IsFirstComponentList = false;
7932 }
Alexey Bataevb3638132018-07-19 16:34:13 +00007933
7934 // Append any pending zero-length pointers which are struct members and
7935 // used with use_device_ptr.
7936 auto CI = DeferredInfo.find(M.first);
7937 if (CI != DeferredInfo.end()) {
7938 for (const DeferredDevicePtrEntryTy &L : CI->second) {
7939 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer();
7940 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar(
7941 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc());
7942 CurBasePointers.emplace_back(BasePtr, L.VD);
7943 CurPointers.push_back(Ptr);
7944 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.SizeTy));
7945 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder
7946 // value MEMBER_OF=FFFF so that the entry is later updated with the
7947 // correct value of MEMBER_OF.
7948 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM |
7949 OMP_MAP_MEMBER_OF);
7950 }
7951 }
7952
7953 // If there is an entry in PartialStruct it means we have a struct with
7954 // individual members mapped. Emit an extra combined entry.
7955 if (PartialStruct.Base.isValid())
7956 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
7957 PartialStruct);
7958
7959 // We need to append the results of this capture to what we already have.
7960 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
7961 Pointers.append(CurPointers.begin(), CurPointers.end());
7962 Sizes.append(CurSizes.begin(), CurSizes.end());
7963 Types.append(CurTypes.begin(), CurTypes.end());
Samuel Antao86ace552016-04-27 22:40:57 +00007964 }
7965 }
7966
Alexey Bataev60705422018-10-30 15:50:12 +00007967 /// Emit capture info for lambdas for variables captured by reference.
Alexey Bataev969dbc02018-11-08 15:47:39 +00007968 void generateInfoForLambdaCaptures(
7969 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers,
7970 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7971 MapFlagsArrayTy &Types,
7972 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const {
Alexey Bataev60705422018-10-30 15:50:12 +00007973 const auto *RD = VD->getType()
7974 .getCanonicalType()
7975 .getNonReferenceType()
7976 ->getAsCXXRecordDecl();
7977 if (!RD || !RD->isLambda())
7978 return;
7979 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD));
7980 LValue VDLVal = CGF.MakeAddrLValue(
7981 VDAddr, VD->getType().getCanonicalType().getNonReferenceType());
7982 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
7983 FieldDecl *ThisCapture = nullptr;
7984 RD->getCaptureFields(Captures, ThisCapture);
7985 if (ThisCapture) {
7986 LValue ThisLVal =
7987 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture);
Alexey Bataev969dbc02018-11-08 15:47:39 +00007988 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture);
7989 LambdaPointers.try_emplace(ThisLVal.getPointer(), VDLVal.getPointer());
7990 BasePointers.push_back(ThisLVal.getPointer());
7991 Pointers.push_back(ThisLValVal.getPointer());
Alexey Bataev60705422018-10-30 15:50:12 +00007992 Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy));
Alexey Bataev2dc07d02018-11-02 15:25:06 +00007993 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00007994 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
7995 }
7996 for (const LambdaCapture &LC : RD->captures()) {
7997 if (LC.getCaptureKind() != LCK_ByRef)
7998 continue;
7999 const VarDecl *VD = LC.getCapturedVar();
8000 auto It = Captures.find(VD);
8001 assert(It != Captures.end() && "Found lambda capture without field.");
8002 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second);
Alexey Bataev969dbc02018-11-08 15:47:39 +00008003 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second);
8004 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer());
8005 BasePointers.push_back(VarLVal.getPointer());
8006 Pointers.push_back(VarLValVal.getPointer());
Alexey Bataev60705422018-10-30 15:50:12 +00008007 Sizes.push_back(CGF.getTypeSize(
8008 VD->getType().getCanonicalType().getNonReferenceType()));
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008009 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008010 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8011 }
8012 }
8013
8014 /// Set correct indices for lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008015 void adjustMemberOfForLambdaCaptures(
8016 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
8017 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
8018 MapFlagsArrayTy &Types) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008019 for (unsigned I = 0, E = Types.size(); I < E; ++I) {
8020 // Set correct member_of idx for all implicit lambda captures.
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008021 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008022 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT))
8023 continue;
Alexey Bataev969dbc02018-11-08 15:47:39 +00008024 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]);
8025 assert(BasePtr && "Unable to find base lambda address.");
Alexey Bataev60705422018-10-30 15:50:12 +00008026 int TgtIdx = -1;
8027 for (unsigned J = I; J > 0; --J) {
8028 unsigned Idx = J - 1;
8029 if (Pointers[Idx] != BasePtr)
8030 continue;
8031 TgtIdx = Idx;
8032 break;
8033 }
8034 assert(TgtIdx != -1 && "Unable to find parent lambda.");
8035 // All other current entries will be MEMBER_OF the combined entry
8036 // (except for PTR_AND_OBJ entries which do not have a placeholder value
8037 // 0xFFFF in the MEMBER_OF field).
8038 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx);
8039 setCorrectMemberOfFlag(Types[I], MemberOfFlag);
8040 }
8041 }
8042
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008043 /// Generate the base pointers, section pointers, sizes and map types
Samuel Antao86ace552016-04-27 22:40:57 +00008044 /// associated to a given capture.
8045 void generateInfoForCapture(const CapturedStmt::Capture *Cap,
Samuel Antao6890b092016-07-28 14:25:09 +00008046 llvm::Value *Arg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008047 MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00008048 MapValuesArrayTy &Pointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008049 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
8050 StructRangeInfoTy &PartialStruct) const {
Samuel Antao86ace552016-04-27 22:40:57 +00008051 assert(!Cap->capturesVariableArrayType() &&
8052 "Not expecting to generate map info for a variable array type!");
8053
Samuel Antao6890b092016-07-28 14:25:09 +00008054 // We need to know when we generating information for the first component
Alexey Bataevb3638132018-07-19 16:34:13 +00008055 const ValueDecl *VD = Cap->capturesThis()
8056 ? nullptr
8057 : Cap->getCapturedVar()->getCanonicalDecl();
Samuel Antao86ace552016-04-27 22:40:57 +00008058
Samuel Antao6890b092016-07-28 14:25:09 +00008059 // If this declaration appears in a is_device_ptr clause we just have to
8060 // pass the pointer by value. If it is a reference to a declaration, we just
Alexey Bataevb3638132018-07-19 16:34:13 +00008061 // pass its value.
8062 if (DevPointersMap.count(VD)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008063 BasePointers.emplace_back(Arg, VD);
Samuel Antao6890b092016-07-28 14:25:09 +00008064 Pointers.push_back(Arg);
8065 Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy));
George Rokos065755d2017-11-07 18:27:04 +00008066 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM);
Samuel Antao6890b092016-07-28 14:25:09 +00008067 return;
8068 }
8069
Alexey Bataeve82445f2018-09-20 13:54:02 +00008070 using MapData =
8071 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
Kelvin Lief579432018-12-18 22:18:41 +00008072 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008073 SmallVector<MapData, 4> DeclComponentLists;
Paul Robinson78fb1322016-08-01 22:12:46 +00008074 // FIXME: MSVC 2013 seems to require this-> to find member CurDir.
Alexey Bataeve82445f2018-09-20 13:54:02 +00008075 for (const auto *C : this->CurDir.getClausesOfKind<OMPMapClause>()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008076 for (const auto &L : C->decl_component_lists(VD)) {
Samuel Antao86ace552016-04-27 22:40:57 +00008077 assert(L.first == VD &&
8078 "We got information for the wrong declaration??");
8079 assert(!L.second.empty() &&
8080 "Not expecting declaration with no component lists.");
Alexey Bataeve82445f2018-09-20 13:54:02 +00008081 DeclComponentLists.emplace_back(L.second, C->getMapType(),
Kelvin Lief579432018-12-18 22:18:41 +00008082 C->getMapTypeModifiers(),
Alexey Bataeve82445f2018-09-20 13:54:02 +00008083 C->isImplicit());
Samuel Antao86ace552016-04-27 22:40:57 +00008084 }
Alexey Bataeve82445f2018-09-20 13:54:02 +00008085 }
8086
8087 // Find overlapping elements (including the offset from the base element).
8088 llvm::SmallDenseMap<
8089 const MapData *,
8090 llvm::SmallVector<
8091 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>,
8092 4>
8093 OverlappedData;
8094 size_t Count = 0;
8095 for (const MapData &L : DeclComponentLists) {
8096 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8097 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008098 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008099 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008100 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008101 ++Count;
8102 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) {
8103 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1;
Kelvin Lief579432018-12-18 22:18:41 +00008104 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008105 auto CI = Components.rbegin();
8106 auto CE = Components.rend();
8107 auto SI = Components1.rbegin();
8108 auto SE = Components1.rend();
8109 for (; CI != CE && SI != SE; ++CI, ++SI) {
8110 if (CI->getAssociatedExpression()->getStmtClass() !=
8111 SI->getAssociatedExpression()->getStmtClass())
8112 break;
8113 // Are we dealing with different variables/fields?
8114 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
8115 break;
8116 }
8117 // Found overlapping if, at least for one component, reached the head of
8118 // the components list.
8119 if (CI == CE || SI == SE) {
8120 assert((CI != CE || SI != SE) &&
8121 "Unexpected full match of the mapping components.");
8122 const MapData &BaseData = CI == CE ? L : L1;
8123 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData =
8124 SI == SE ? Components : Components1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008125 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData);
8126 OverlappedElements.getSecond().push_back(SubData);
8127 }
8128 }
8129 }
8130 // Sort the overlapped elements for each item.
8131 llvm::SmallVector<const FieldDecl *, 4> Layout;
8132 if (!OverlappedData.empty()) {
8133 if (const auto *CRD =
8134 VD->getType().getCanonicalType()->getAsCXXRecordDecl())
8135 getPlainLayout(CRD, Layout, /*AsBase=*/false);
8136 else {
8137 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl();
8138 Layout.append(RD->field_begin(), RD->field_end());
8139 }
8140 }
8141 for (auto &Pair : OverlappedData) {
8142 llvm::sort(
8143 Pair.getSecond(),
8144 [&Layout](
8145 OMPClauseMappableExprCommon::MappableExprComponentListRef First,
8146 OMPClauseMappableExprCommon::MappableExprComponentListRef
8147 Second) {
8148 auto CI = First.rbegin();
8149 auto CE = First.rend();
8150 auto SI = Second.rbegin();
8151 auto SE = Second.rend();
8152 for (; CI != CE && SI != SE; ++CI, ++SI) {
8153 if (CI->getAssociatedExpression()->getStmtClass() !=
8154 SI->getAssociatedExpression()->getStmtClass())
8155 break;
8156 // Are we dealing with different variables/fields?
8157 if (CI->getAssociatedDeclaration() !=
8158 SI->getAssociatedDeclaration())
8159 break;
8160 }
Richard Trieu5061e832018-09-21 21:20:33 +00008161
8162 // Lists contain the same elements.
8163 if (CI == CE && SI == SE)
8164 return false;
8165
8166 // List with less elements is less than list with more elements.
8167 if (CI == CE || SI == SE)
8168 return CI == CE;
8169
Alexey Bataeve82445f2018-09-20 13:54:02 +00008170 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
8171 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
8172 if (FD1->getParent() == FD2->getParent())
8173 return FD1->getFieldIndex() < FD2->getFieldIndex();
8174 const auto It =
8175 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) {
8176 return FD == FD1 || FD == FD2;
8177 });
8178 return *It == FD1;
8179 });
8180 }
8181
8182 // Associated with a capture, because the mapping flags depend on it.
8183 // Go through all of the elements with the overlapped elements.
8184 for (const auto &Pair : OverlappedData) {
8185 const MapData &L = *Pair.getFirst();
8186 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8187 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008188 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008189 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008190 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008191 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
8192 OverlappedComponents = Pair.getSecond();
8193 bool IsFirstComponentList = true;
Kelvin Lief579432018-12-18 22:18:41 +00008194 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008195 BasePointers, Pointers, Sizes, Types,
8196 PartialStruct, IsFirstComponentList,
8197 IsImplicit, OverlappedComponents);
8198 }
8199 // Go through other elements without overlapped elements.
8200 bool IsFirstComponentList = OverlappedData.empty();
8201 for (const MapData &L : DeclComponentLists) {
8202 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8203 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008204 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008205 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008206 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008207 auto It = OverlappedData.find(&L);
8208 if (It == OverlappedData.end())
Kelvin Lief579432018-12-18 22:18:41 +00008209 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008210 BasePointers, Pointers, Sizes, Types,
8211 PartialStruct, IsFirstComponentList,
8212 IsImplicit);
8213 IsFirstComponentList = false;
8214 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008215 }
Samuel Antao86ace552016-04-27 22:40:57 +00008216
Alexey Bataevb3638132018-07-19 16:34:13 +00008217 /// Generate the base pointers, section pointers, sizes and map types
8218 /// associated with the declare target link variables.
8219 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers,
8220 MapValuesArrayTy &Pointers,
8221 MapValuesArrayTy &Sizes,
8222 MapFlagsArrayTy &Types) const {
8223 // Map other list items in the map clause which are not captured variables
8224 // but "declare target link" global variables.,
8225 for (const auto *C : this->CurDir.getClausesOfKind<OMPMapClause>()) {
8226 for (const auto &L : C->component_lists()) {
8227 if (!L.first)
8228 continue;
8229 const auto *VD = dyn_cast<VarDecl>(L.first);
8230 if (!VD)
8231 continue;
8232 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00008233 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Alexey Bataevb3638132018-07-19 16:34:13 +00008234 if (!Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)
8235 continue;
8236 StructRangeInfoTy PartialStruct;
8237 generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00008238 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008239 Pointers, Sizes, Types, PartialStruct,
8240 /*IsFirstComponentList=*/true, C->isImplicit());
8241 assert(!PartialStruct.Base.isValid() &&
8242 "No partial structs for declare target link expected.");
8243 }
8244 }
Samuel Antao86ace552016-04-27 22:40:57 +00008245 }
Samuel Antaod486f842016-05-26 16:53:38 +00008246
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008247 /// Generate the default map information for a given capture \a CI,
Samuel Antaod486f842016-05-26 16:53:38 +00008248 /// record field declaration \a RI and captured value \a CV.
Samuel Antaocc10b852016-07-28 14:23:26 +00008249 void generateDefaultMapInfo(const CapturedStmt::Capture &CI,
8250 const FieldDecl &RI, llvm::Value *CV,
8251 MapBaseValuesArrayTy &CurBasePointers,
8252 MapValuesArrayTy &CurPointers,
8253 MapValuesArrayTy &CurSizes,
Alexey Bataevb3638132018-07-19 16:34:13 +00008254 MapFlagsArrayTy &CurMapTypes) const {
Samuel Antaod486f842016-05-26 16:53:38 +00008255 // Do the default mapping.
8256 if (CI.capturesThis()) {
8257 CurBasePointers.push_back(CV);
8258 CurPointers.push_back(CV);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008259 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr());
Samuel Antaod486f842016-05-26 16:53:38 +00008260 CurSizes.push_back(CGF.getTypeSize(PtrTy->getPointeeType()));
8261 // Default map type.
Samuel Antaocc10b852016-07-28 14:23:26 +00008262 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM);
Samuel Antaod486f842016-05-26 16:53:38 +00008263 } else if (CI.capturesVariableByCopy()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008264 CurBasePointers.push_back(CV);
8265 CurPointers.push_back(CV);
Samuel Antaod486f842016-05-26 16:53:38 +00008266 if (!RI.getType()->isAnyPointerType()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008267 // We have to signal to the runtime captures passed by value that are
8268 // not pointers.
George Rokos065755d2017-11-07 18:27:04 +00008269 CurMapTypes.push_back(OMP_MAP_LITERAL);
Samuel Antaod486f842016-05-26 16:53:38 +00008270 CurSizes.push_back(CGF.getTypeSize(RI.getType()));
8271 } else {
8272 // Pointers are implicitly mapped with a zero size and no flags
8273 // (other than first map that is added for all implicit maps).
Alexey Bataevb3638132018-07-19 16:34:13 +00008274 CurMapTypes.push_back(OMP_MAP_NONE);
Samuel Antaod486f842016-05-26 16:53:38 +00008275 CurSizes.push_back(llvm::Constant::getNullValue(CGF.SizeTy));
8276 }
8277 } else {
8278 assert(CI.capturesVariable() && "Expected captured reference.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008279 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr());
Samuel Antaod486f842016-05-26 16:53:38 +00008280 QualType ElementType = PtrTy->getPointeeType();
8281 CurSizes.push_back(CGF.getTypeSize(ElementType));
8282 // The default map type for a scalar/complex type is 'to' because by
8283 // default the value doesn't have to be retrieved. For an aggregate
8284 // type, the default is 'tofrom'.
Alexey Bataevb3638132018-07-19 16:34:13 +00008285 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI));
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008286 const VarDecl *VD = CI.getCapturedVar();
8287 if (FirstPrivateDecls.count(VD) &&
8288 VD->getType().isConstant(CGF.getContext())) {
8289 llvm::Constant *Addr =
8290 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD);
8291 // Copy the value of the original variable to the new global copy.
8292 CGF.Builder.CreateMemCpy(
8293 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(),
8294 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)),
Alexey Bataevc2b831f2019-04-02 16:03:40 +00008295 CurSizes.back(), /*isVolatile=*/false);
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008296 // Use new global variable as the base pointers.
8297 CurBasePointers.push_back(Addr);
8298 CurPointers.push_back(Addr);
8299 } else {
8300 CurBasePointers.push_back(CV);
Alexey Bataevc2b831f2019-04-02 16:03:40 +00008301 if (FirstPrivateDecls.count(VD) && ElementType->isAnyPointerType()) {
8302 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue(
8303 CV, ElementType, CGF.getContext().getDeclAlign(VD),
8304 AlignmentSource::Decl));
8305 CurPointers.push_back(PtrAddr.getPointer());
8306 } else {
8307 CurPointers.push_back(CV);
8308 }
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008309 }
Samuel Antaod486f842016-05-26 16:53:38 +00008310 }
George Rokos065755d2017-11-07 18:27:04 +00008311 // Every default map produces a single argument which is a target parameter.
8312 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM;
Alexey Bataevb3638132018-07-19 16:34:13 +00008313
8314 // Add flag stating this is an implicit map.
8315 CurMapTypes.back() |= OMP_MAP_IMPLICIT;
Samuel Antaod486f842016-05-26 16:53:38 +00008316 }
Samuel Antao86ace552016-04-27 22:40:57 +00008317};
Samuel Antaodf158d52016-04-27 22:58:19 +00008318
8319enum OpenMPOffloadingReservedDeviceIDs {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008320 /// Device ID if the device was not defined, runtime should get it
Samuel Antaodf158d52016-04-27 22:58:19 +00008321 /// from environment variables in the spec.
8322 OMP_DEVICEID_UNDEF = -1,
8323};
8324} // anonymous namespace
8325
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008326/// Emit the arrays used to pass the captures and map information to the
Samuel Antaodf158d52016-04-27 22:58:19 +00008327/// offloading runtime library. If there is no map or capture information,
8328/// return nullptr by reference.
8329static void
Samuel Antaocc10b852016-07-28 14:23:26 +00008330emitOffloadingArrays(CodeGenFunction &CGF,
8331 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers,
Samuel Antaodf158d52016-04-27 22:58:19 +00008332 MappableExprsHandler::MapValuesArrayTy &Pointers,
8333 MappableExprsHandler::MapValuesArrayTy &Sizes,
Samuel Antaocc10b852016-07-28 14:23:26 +00008334 MappableExprsHandler::MapFlagsArrayTy &MapTypes,
8335 CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008336 CodeGenModule &CGM = CGF.CGM;
8337 ASTContext &Ctx = CGF.getContext();
Samuel Antaodf158d52016-04-27 22:58:19 +00008338
Samuel Antaocc10b852016-07-28 14:23:26 +00008339 // Reset the array information.
8340 Info.clearArrayInfo();
8341 Info.NumberOfPtrs = BasePointers.size();
Samuel Antaodf158d52016-04-27 22:58:19 +00008342
Samuel Antaocc10b852016-07-28 14:23:26 +00008343 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008344 // Detect if we have any capture size requiring runtime evaluation of the
8345 // size so that a constant array could be eventually used.
8346 bool hasRuntimeEvaluationCaptureSize = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008347 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008348 if (!isa<llvm::Constant>(S)) {
8349 hasRuntimeEvaluationCaptureSize = true;
8350 break;
8351 }
8352
Samuel Antaocc10b852016-07-28 14:23:26 +00008353 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true);
Samuel Antaodf158d52016-04-27 22:58:19 +00008354 QualType PointerArrayType =
8355 Ctx.getConstantArrayType(Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal,
8356 /*IndexTypeQuals=*/0);
8357
Samuel Antaocc10b852016-07-28 14:23:26 +00008358 Info.BasePointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008359 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
Samuel Antaocc10b852016-07-28 14:23:26 +00008360 Info.PointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008361 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
8362
8363 // If we don't have any VLA types or other types that require runtime
8364 // evaluation, we can use a constant array for the map sizes, otherwise we
8365 // need to fill up the arrays as we do for the pointers.
8366 if (hasRuntimeEvaluationCaptureSize) {
8367 QualType SizeArrayType = Ctx.getConstantArrayType(
8368 Ctx.getSizeType(), PointerNumAP, ArrayType::Normal,
8369 /*IndexTypeQuals=*/0);
Samuel Antaocc10b852016-07-28 14:23:26 +00008370 Info.SizesArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008371 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
8372 } else {
8373 // We expect all the sizes to be constant, so we collect them to create
8374 // a constant array.
8375 SmallVector<llvm::Constant *, 16> ConstSizes;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008376 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008377 ConstSizes.push_back(cast<llvm::Constant>(S));
8378
8379 auto *SizesArrayInit = llvm::ConstantArray::get(
8380 llvm::ArrayType::get(CGM.SizeTy, ConstSizes.size()), ConstSizes);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008381 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008382 auto *SizesArrayGbl = new llvm::GlobalVariable(
8383 CGM.getModule(), SizesArrayInit->getType(),
8384 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008385 SizesArrayInit, Name);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008386 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008387 Info.SizesArray = SizesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008388 }
8389
8390 // The map types are always constant so we don't need to generate code to
8391 // fill arrays. Instead, we create an array constant.
Alexey Bataevb3638132018-07-19 16:34:13 +00008392 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0);
8393 llvm::copy(MapTypes, Mapping.begin());
Samuel Antaodf158d52016-04-27 22:58:19 +00008394 llvm::Constant *MapTypesArrayInit =
Alexey Bataevb3638132018-07-19 16:34:13 +00008395 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008396 std::string MaptypesName =
8397 CGM.getOpenMPRuntime().getName({"offload_maptypes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008398 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
8399 CGM.getModule(), MapTypesArrayInit->getType(),
8400 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008401 MapTypesArrayInit, MaptypesName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008402 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008403 Info.MapTypesArray = MapTypesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008404
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008405 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) {
8406 llvm::Value *BPVal = *BasePointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008407 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008408 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008409 Info.BasePointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008410 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8411 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008412 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8413 CGF.Builder.CreateStore(BPVal, BPAddr);
8414
Samuel Antaocc10b852016-07-28 14:23:26 +00008415 if (Info.requiresDevicePointerInfo())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008416 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl())
Alexey Bataev43a919f2018-04-13 17:48:43 +00008417 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr);
Samuel Antaocc10b852016-07-28 14:23:26 +00008418
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008419 llvm::Value *PVal = Pointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008420 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008421 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008422 Info.PointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008423 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8424 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008425 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8426 CGF.Builder.CreateStore(PVal, PAddr);
8427
8428 if (hasRuntimeEvaluationCaptureSize) {
8429 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008430 llvm::ArrayType::get(CGM.SizeTy, Info.NumberOfPtrs),
8431 Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008432 /*Idx0=*/0,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008433 /*Idx1=*/I);
Samuel Antaodf158d52016-04-27 22:58:19 +00008434 Address SAddr(S, Ctx.getTypeAlignInChars(Ctx.getSizeType()));
8435 CGF.Builder.CreateStore(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008436 CGF.Builder.CreateIntCast(Sizes[I], CGM.SizeTy, /*isSigned=*/true),
Samuel Antaodf158d52016-04-27 22:58:19 +00008437 SAddr);
8438 }
8439 }
8440 }
8441}
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008442/// Emit the arguments to be passed to the runtime library based on the
Samuel Antaodf158d52016-04-27 22:58:19 +00008443/// arrays of pointers, sizes and map types.
8444static void emitOffloadingArraysArgument(
8445 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg,
8446 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008447 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008448 CodeGenModule &CGM = CGF.CGM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008449 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008450 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008451 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8452 Info.BasePointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008453 /*Idx0=*/0, /*Idx1=*/0);
8454 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008455 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8456 Info.PointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008457 /*Idx0=*/0,
8458 /*Idx1=*/0);
8459 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008460 llvm::ArrayType::get(CGM.SizeTy, Info.NumberOfPtrs), Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008461 /*Idx0=*/0, /*Idx1=*/0);
8462 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
George Rokos63bc9d62017-11-21 18:25:12 +00008463 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008464 Info.MapTypesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008465 /*Idx0=*/0,
8466 /*Idx1=*/0);
8467 } else {
8468 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
8469 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
8470 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.SizeTy->getPointerTo());
8471 MapTypesArrayArg =
George Rokos63bc9d62017-11-21 18:25:12 +00008472 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008473 }
Samuel Antao86ace552016-04-27 22:40:57 +00008474}
8475
Alexey Bataev7bb33532019-01-07 21:30:43 +00008476/// Check for inner distribute directive.
8477static const OMPExecutableDirective *
8478getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
8479 const auto *CS = D.getInnermostCapturedStmt();
8480 const auto *Body =
8481 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00008482 const Stmt *ChildStmt =
8483 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
Alexey Bataev7bb33532019-01-07 21:30:43 +00008484
Alexey Bataev5c427362019-04-10 19:11:33 +00008485 if (const auto *NestedDir =
8486 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008487 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind();
8488 switch (D.getDirectiveKind()) {
8489 case OMPD_target:
8490 if (isOpenMPDistributeDirective(DKind))
8491 return NestedDir;
8492 if (DKind == OMPD_teams) {
8493 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
8494 /*IgnoreCaptured=*/true);
8495 if (!Body)
8496 return nullptr;
Alexey Bataev5c427362019-04-10 19:11:33 +00008497 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
8498 if (const auto *NND =
8499 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008500 DKind = NND->getDirectiveKind();
8501 if (isOpenMPDistributeDirective(DKind))
8502 return NND;
8503 }
8504 }
8505 return nullptr;
8506 case OMPD_target_teams:
8507 if (isOpenMPDistributeDirective(DKind))
8508 return NestedDir;
8509 return nullptr;
8510 case OMPD_target_parallel:
8511 case OMPD_target_simd:
8512 case OMPD_target_parallel_for:
8513 case OMPD_target_parallel_for_simd:
8514 return nullptr;
8515 case OMPD_target_teams_distribute:
8516 case OMPD_target_teams_distribute_simd:
8517 case OMPD_target_teams_distribute_parallel_for:
8518 case OMPD_target_teams_distribute_parallel_for_simd:
8519 case OMPD_parallel:
8520 case OMPD_for:
8521 case OMPD_parallel_for:
8522 case OMPD_parallel_sections:
8523 case OMPD_for_simd:
8524 case OMPD_parallel_for_simd:
8525 case OMPD_cancel:
8526 case OMPD_cancellation_point:
8527 case OMPD_ordered:
8528 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00008529 case OMPD_allocate:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008530 case OMPD_task:
8531 case OMPD_simd:
8532 case OMPD_sections:
8533 case OMPD_section:
8534 case OMPD_single:
8535 case OMPD_master:
8536 case OMPD_critical:
8537 case OMPD_taskyield:
8538 case OMPD_barrier:
8539 case OMPD_taskwait:
8540 case OMPD_taskgroup:
8541 case OMPD_atomic:
8542 case OMPD_flush:
8543 case OMPD_teams:
8544 case OMPD_target_data:
8545 case OMPD_target_exit_data:
8546 case OMPD_target_enter_data:
8547 case OMPD_distribute:
8548 case OMPD_distribute_simd:
8549 case OMPD_distribute_parallel_for:
8550 case OMPD_distribute_parallel_for_simd:
8551 case OMPD_teams_distribute:
8552 case OMPD_teams_distribute_simd:
8553 case OMPD_teams_distribute_parallel_for:
8554 case OMPD_teams_distribute_parallel_for_simd:
8555 case OMPD_target_update:
8556 case OMPD_declare_simd:
8557 case OMPD_declare_target:
8558 case OMPD_end_declare_target:
8559 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00008560 case OMPD_declare_mapper:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008561 case OMPD_taskloop:
8562 case OMPD_taskloop_simd:
8563 case OMPD_requires:
8564 case OMPD_unknown:
8565 llvm_unreachable("Unexpected directive.");
8566 }
8567 }
8568
8569 return nullptr;
8570}
8571
8572void CGOpenMPRuntime::emitTargetNumIterationsCall(
8573 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *Device,
8574 const llvm::function_ref<llvm::Value *(
8575 CodeGenFunction &CGF, const OMPLoopDirective &D)> &SizeEmitter) {
8576 OpenMPDirectiveKind Kind = D.getDirectiveKind();
8577 const OMPExecutableDirective *TD = &D;
8578 // Get nested teams distribute kind directive, if any.
8579 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind))
8580 TD = getNestedDistributeDirective(CGM.getContext(), D);
8581 if (!TD)
8582 return;
8583 const auto *LD = cast<OMPLoopDirective>(TD);
8584 auto &&CodeGen = [LD, &Device, &SizeEmitter, this](CodeGenFunction &CGF,
8585 PrePostActionTy &) {
8586 llvm::Value *NumIterations = SizeEmitter(CGF, *LD);
8587
8588 // Emit device ID if any.
8589 llvm::Value *DeviceID;
8590 if (Device)
8591 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
8592 CGF.Int64Ty, /*isSigned=*/true);
8593 else
8594 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
8595
8596 llvm::Value *Args[] = {DeviceID, NumIterations};
8597 CGF.EmitRuntimeCall(
8598 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args);
8599 };
8600 emitInlinedDirective(CGF, OMPD_unknown, CodeGen);
8601}
8602
Samuel Antaobed3c462015-10-02 16:14:20 +00008603void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
8604 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00008605 llvm::Function *OutlinedFn,
Samuel Antaoee8fb302016-01-06 13:42:12 +00008606 llvm::Value *OutlinedFnID,
Alexey Bataev8451efa2018-01-15 19:06:12 +00008607 const Expr *IfCond, const Expr *Device) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00008608 if (!CGF.HaveInsertPoint())
8609 return;
Samuel Antaobed3c462015-10-02 16:14:20 +00008610
Samuel Antaoee8fb302016-01-06 13:42:12 +00008611 assert(OutlinedFn && "Invalid outlined function!");
8612
Alexey Bataev8451efa2018-01-15 19:06:12 +00008613 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>();
8614 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
Alexey Bataev475a7442018-01-12 19:39:11 +00008615 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Alexey Bataev8451efa2018-01-15 19:06:12 +00008616 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF,
8617 PrePostActionTy &) {
8618 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
8619 };
8620 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen);
Samuel Antao86ace552016-04-27 22:40:57 +00008621
Alexey Bataev8451efa2018-01-15 19:06:12 +00008622 CodeGenFunction::OMPTargetDataInfo InputInfo;
8623 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobed3c462015-10-02 16:14:20 +00008624 // Fill up the pointer arrays and transfer execution to the device.
Alexey Bataev8451efa2018-01-15 19:06:12 +00008625 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo,
8626 &MapTypesArray, &CS, RequiresOuterTask,
8627 &CapturedVars](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobed3c462015-10-02 16:14:20 +00008628 // On top of the arrays that were filled up, the target offloading call
8629 // takes as arguments the device id as well as the host pointer. The host
8630 // pointer is used by the runtime library to identify the current target
8631 // region, so it only has to be unique and not necessarily point to
8632 // anything. It could be the pointer to the outlined function that
8633 // implements the target region, but we aren't using that so that the
8634 // compiler doesn't need to keep that, and could therefore inline the host
8635 // function if proven worthwhile during optimization.
8636
Samuel Antaoee8fb302016-01-06 13:42:12 +00008637 // From this point on, we need to have an ID of the target region defined.
8638 assert(OutlinedFnID && "Invalid outlined function ID!");
Samuel Antaobed3c462015-10-02 16:14:20 +00008639
8640 // Emit device ID if any.
8641 llvm::Value *DeviceID;
George Rokos63bc9d62017-11-21 18:25:12 +00008642 if (Device) {
Samuel Antaobed3c462015-10-02 16:14:20 +00008643 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00008644 CGF.Int64Ty, /*isSigned=*/true);
8645 } else {
8646 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
8647 }
Samuel Antaobed3c462015-10-02 16:14:20 +00008648
Samuel Antaodf158d52016-04-27 22:58:19 +00008649 // Emit the number of elements in the offloading arrays.
Alexey Bataev8451efa2018-01-15 19:06:12 +00008650 llvm::Value *PointerNum =
8651 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaodf158d52016-04-27 22:58:19 +00008652
Samuel Antaob68e2db2016-03-03 16:20:23 +00008653 // Return value of the runtime offloading call.
8654 llvm::Value *Return;
8655
Alexey Bataev5c427362019-04-10 19:11:33 +00008656 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D);
8657 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D);
Samuel Antaob68e2db2016-03-03 16:20:23 +00008658
Alexey Bataeva9f77c62017-12-13 21:04:20 +00008659 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00008660 // The target region is an outlined function launched by the runtime
8661 // via calls __tgt_target() or __tgt_target_teams().
8662 //
8663 // __tgt_target() launches a target region with one team and one thread,
8664 // executing a serial region. This master thread may in turn launch
8665 // more threads within its team upon encountering a parallel region,
8666 // however, no additional teams can be launched on the device.
8667 //
8668 // __tgt_target_teams() launches a target region with one or more teams,
8669 // each with one or more threads. This call is required for target
8670 // constructs such as:
8671 // 'target teams'
8672 // 'target' / 'teams'
8673 // 'target teams distribute parallel for'
8674 // 'target parallel'
8675 // and so on.
8676 //
8677 // Note that on the host and CPU targets, the runtime implementation of
8678 // these calls simply call the outlined function without forking threads.
8679 // The outlined functions themselves have runtime calls to
8680 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by
8681 // the compiler in emitTeamsCall() and emitParallelCall().
8682 //
8683 // In contrast, on the NVPTX target, the implementation of
8684 // __tgt_target_teams() launches a GPU kernel with the requested number
8685 // of teams and threads so no additional calls to the runtime are required.
Samuel Antaob68e2db2016-03-03 16:20:23 +00008686 if (NumTeams) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00008687 // If we have NumTeams defined this means that we have an enclosed teams
8688 // region. Therefore we also expect to have NumThreads defined. These two
8689 // values should be defined in the presence of a teams directive,
8690 // regardless of having any clauses associated. If the user is using teams
8691 // but no clauses, these two values will be the default that should be
8692 // passed to the runtime library - a 32-bit integer with the value zero.
8693 assert(NumThreads && "Thread limit expression should be available along "
8694 "with number of teams.");
Alexey Bataev8451efa2018-01-15 19:06:12 +00008695 llvm::Value *OffloadingArgs[] = {DeviceID,
8696 OutlinedFnID,
8697 PointerNum,
8698 InputInfo.BasePointersArray.getPointer(),
8699 InputInfo.PointersArray.getPointer(),
8700 InputInfo.SizesArray.getPointer(),
8701 MapTypesArray,
8702 NumTeams,
8703 NumThreads};
Samuel Antaob68e2db2016-03-03 16:20:23 +00008704 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00008705 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait
8706 : OMPRTL__tgt_target_teams),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00008707 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00008708 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00008709 llvm::Value *OffloadingArgs[] = {DeviceID,
8710 OutlinedFnID,
8711 PointerNum,
8712 InputInfo.BasePointersArray.getPointer(),
8713 InputInfo.PointersArray.getPointer(),
8714 InputInfo.SizesArray.getPointer(),
8715 MapTypesArray};
Alexey Bataeva9f77c62017-12-13 21:04:20 +00008716 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00008717 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait
8718 : OMPRTL__tgt_target),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00008719 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00008720 }
Samuel Antaobed3c462015-10-02 16:14:20 +00008721
Alexey Bataev2a007e02017-10-02 14:20:58 +00008722 // Check the error code and execute the host version if required.
8723 llvm::BasicBlock *OffloadFailedBlock =
8724 CGF.createBasicBlock("omp_offload.failed");
8725 llvm::BasicBlock *OffloadContBlock =
8726 CGF.createBasicBlock("omp_offload.cont");
8727 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return);
8728 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
8729
8730 CGF.EmitBlock(OffloadFailedBlock);
Alexey Bataev8451efa2018-01-15 19:06:12 +00008731 if (RequiresOuterTask) {
8732 CapturedVars.clear();
8733 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
8734 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00008735 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev2a007e02017-10-02 14:20:58 +00008736 CGF.EmitBranch(OffloadContBlock);
8737
8738 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00008739 };
8740
Samuel Antaoee8fb302016-01-06 13:42:12 +00008741 // Notify that the host version must be executed.
Alexey Bataev8451efa2018-01-15 19:06:12 +00008742 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars,
8743 RequiresOuterTask](CodeGenFunction &CGF,
8744 PrePostActionTy &) {
8745 if (RequiresOuterTask) {
8746 CapturedVars.clear();
8747 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
8748 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00008749 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev8451efa2018-01-15 19:06:12 +00008750 };
8751
8752 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray,
8753 &CapturedVars, RequiresOuterTask,
8754 &CS](CodeGenFunction &CGF, PrePostActionTy &) {
8755 // Fill up the arrays with all the captured variables.
8756 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
8757 MappableExprsHandler::MapValuesArrayTy Pointers;
8758 MappableExprsHandler::MapValuesArrayTy Sizes;
8759 MappableExprsHandler::MapFlagsArrayTy MapTypes;
8760
Alexey Bataev8451efa2018-01-15 19:06:12 +00008761 // Get mappable expression information.
8762 MappableExprsHandler MEHandler(D, CGF);
Alexey Bataev969dbc02018-11-08 15:47:39 +00008763 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
Alexey Bataev8451efa2018-01-15 19:06:12 +00008764
8765 auto RI = CS.getCapturedRecordDecl()->field_begin();
8766 auto CV = CapturedVars.begin();
8767 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
8768 CE = CS.capture_end();
8769 CI != CE; ++CI, ++RI, ++CV) {
Alexey Bataevb3638132018-07-19 16:34:13 +00008770 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers;
8771 MappableExprsHandler::MapValuesArrayTy CurPointers;
8772 MappableExprsHandler::MapValuesArrayTy CurSizes;
8773 MappableExprsHandler::MapFlagsArrayTy CurMapTypes;
8774 MappableExprsHandler::StructRangeInfoTy PartialStruct;
Alexey Bataev8451efa2018-01-15 19:06:12 +00008775
8776 // VLA sizes are passed to the outlined region by copy and do not have map
8777 // information associated.
8778 if (CI->capturesVariableArrayType()) {
8779 CurBasePointers.push_back(*CV);
8780 CurPointers.push_back(*CV);
8781 CurSizes.push_back(CGF.getTypeSize(RI->getType()));
8782 // Copy to the device as an argument. No need to retrieve it.
8783 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL |
8784 MappableExprsHandler::OMP_MAP_TARGET_PARAM);
8785 } else {
8786 // If we have any information in the map clause, we use it, otherwise we
8787 // just do a default mapping.
8788 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008789 CurSizes, CurMapTypes, PartialStruct);
Alexey Bataev8451efa2018-01-15 19:06:12 +00008790 if (CurBasePointers.empty())
8791 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers,
8792 CurPointers, CurSizes, CurMapTypes);
Alexey Bataev60705422018-10-30 15:50:12 +00008793 // Generate correct mapping for variables captured by reference in
8794 // lambdas.
8795 if (CI->capturesVariable())
Alexey Bataev969dbc02018-11-08 15:47:39 +00008796 MEHandler.generateInfoForLambdaCaptures(
8797 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes,
8798 CurMapTypes, LambdaPointers);
Alexey Bataev8451efa2018-01-15 19:06:12 +00008799 }
8800 // We expect to have at least an element of information for this capture.
8801 assert(!CurBasePointers.empty() &&
8802 "Non-existing map pointer for capture!");
8803 assert(CurBasePointers.size() == CurPointers.size() &&
8804 CurBasePointers.size() == CurSizes.size() &&
8805 CurBasePointers.size() == CurMapTypes.size() &&
8806 "Inconsistent map information sizes!");
8807
Alexey Bataevb3638132018-07-19 16:34:13 +00008808 // If there is an entry in PartialStruct it means we have a struct with
8809 // individual members mapped. Emit an extra combined entry.
8810 if (PartialStruct.Base.isValid())
8811 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes,
8812 CurMapTypes, PartialStruct);
8813
Alexey Bataev8451efa2018-01-15 19:06:12 +00008814 // We need to append the results of this capture to what we already have.
8815 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8816 Pointers.append(CurPointers.begin(), CurPointers.end());
8817 Sizes.append(CurSizes.begin(), CurSizes.end());
8818 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end());
8819 }
Alexey Bataev60705422018-10-30 15:50:12 +00008820 // Adjust MEMBER_OF flags for the lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008821 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers,
8822 Pointers, MapTypes);
Alexey Bataev92327c52018-03-26 16:40:55 +00008823 // Map other list items in the map clause which are not captured variables
8824 // but "declare target link" global variables.
Alexey Bataevb3638132018-07-19 16:34:13 +00008825 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes,
8826 MapTypes);
Alexey Bataev8451efa2018-01-15 19:06:12 +00008827
8828 TargetDataInfo Info;
8829 // Fill up the arrays and create the arguments.
8830 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
8831 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
8832 Info.PointersArray, Info.SizesArray,
8833 Info.MapTypesArray, Info);
8834 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
8835 InputInfo.BasePointersArray =
8836 Address(Info.BasePointersArray, CGM.getPointerAlign());
8837 InputInfo.PointersArray =
8838 Address(Info.PointersArray, CGM.getPointerAlign());
8839 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign());
8840 MapTypesArray = Info.MapTypesArray;
8841 if (RequiresOuterTask)
8842 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
8843 else
8844 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
8845 };
8846
8847 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask](
8848 CodeGenFunction &CGF, PrePostActionTy &) {
8849 if (RequiresOuterTask) {
8850 CodeGenFunction::OMPTargetDataInfo InputInfo;
8851 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo);
8852 } else {
8853 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen);
8854 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00008855 };
8856
8857 // If we have a target function ID it means that we need to support
8858 // offloading, otherwise, just execute on the host. We need to execute on host
8859 // regardless of the conditional in the if clause if, e.g., the user do not
8860 // specify target triples.
8861 if (OutlinedFnID) {
Alexey Bataev8451efa2018-01-15 19:06:12 +00008862 if (IfCond) {
8863 emitOMPIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
8864 } else {
8865 RegionCodeGenTy ThenRCG(TargetThenGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00008866 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00008867 }
8868 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00008869 RegionCodeGenTy ElseRCG(TargetElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00008870 ElseRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00008871 }
Samuel Antaobed3c462015-10-02 16:14:20 +00008872}
Samuel Antaoee8fb302016-01-06 13:42:12 +00008873
8874void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
8875 StringRef ParentName) {
8876 if (!S)
8877 return;
8878
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00008879 // Codegen OMP target directives that offload compute to the device.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008880 bool RequiresDeviceCodegen =
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00008881 isa<OMPExecutableDirective>(S) &&
8882 isOpenMPTargetExecutionDirective(
8883 cast<OMPExecutableDirective>(S)->getDirectiveKind());
Samuel Antaoee8fb302016-01-06 13:42:12 +00008884
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008885 if (RequiresDeviceCodegen) {
8886 const auto &E = *cast<OMPExecutableDirective>(S);
Samuel Antaoee8fb302016-01-06 13:42:12 +00008887 unsigned DeviceID;
8888 unsigned FileID;
8889 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00008890 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID,
Samuel Antao2de62b02016-02-13 23:35:10 +00008891 FileID, Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00008892
8893 // Is this a target region that should not be emitted as an entry point? If
8894 // so just signal we are done with this target region.
Samuel Antao2de62b02016-02-13 23:35:10 +00008895 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
8896 ParentName, Line))
Samuel Antaoee8fb302016-01-06 13:42:12 +00008897 return;
8898
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008899 switch (E.getDirectiveKind()) {
8900 case OMPD_target:
8901 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName,
8902 cast<OMPTargetDirective>(E));
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00008903 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008904 case OMPD_target_parallel:
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00008905 CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008906 CGM, ParentName, cast<OMPTargetParallelDirective>(E));
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00008907 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008908 case OMPD_target_teams:
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00008909 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008910 CGM, ParentName, cast<OMPTargetTeamsDirective>(E));
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00008911 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008912 case OMPD_target_teams_distribute:
Alexey Bataevdfa430f2017-12-08 15:03:50 +00008913 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008914 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E));
Alexey Bataevdfa430f2017-12-08 15:03:50 +00008915 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008916 case OMPD_target_teams_distribute_simd:
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00008917 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008918 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E));
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00008919 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008920 case OMPD_target_parallel_for:
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00008921 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008922 CGM, ParentName, cast<OMPTargetParallelForDirective>(E));
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00008923 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008924 case OMPD_target_parallel_for_simd:
Alexey Bataev5d7edca2017-11-09 17:32:15 +00008925 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008926 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E));
Alexey Bataev5d7edca2017-11-09 17:32:15 +00008927 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008928 case OMPD_target_simd:
Alexey Bataevf8365372017-11-17 17:57:25 +00008929 CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008930 CGM, ParentName, cast<OMPTargetSimdDirective>(E));
Alexey Bataevf8365372017-11-17 17:57:25 +00008931 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008932 case OMPD_target_teams_distribute_parallel_for:
Carlo Bertolli52978c32018-01-03 21:12:44 +00008933 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
8934 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008935 cast<OMPTargetTeamsDistributeParallelForDirective>(E));
Carlo Bertolli52978c32018-01-03 21:12:44 +00008936 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008937 case OMPD_target_teams_distribute_parallel_for_simd:
Alexey Bataev647dd842018-01-15 20:59:40 +00008938 CodeGenFunction::
8939 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
8940 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008941 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E));
Alexey Bataev647dd842018-01-15 20:59:40 +00008942 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008943 case OMPD_parallel:
8944 case OMPD_for:
8945 case OMPD_parallel_for:
8946 case OMPD_parallel_sections:
8947 case OMPD_for_simd:
8948 case OMPD_parallel_for_simd:
8949 case OMPD_cancel:
8950 case OMPD_cancellation_point:
8951 case OMPD_ordered:
8952 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00008953 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008954 case OMPD_task:
8955 case OMPD_simd:
8956 case OMPD_sections:
8957 case OMPD_section:
8958 case OMPD_single:
8959 case OMPD_master:
8960 case OMPD_critical:
8961 case OMPD_taskyield:
8962 case OMPD_barrier:
8963 case OMPD_taskwait:
8964 case OMPD_taskgroup:
8965 case OMPD_atomic:
8966 case OMPD_flush:
8967 case OMPD_teams:
8968 case OMPD_target_data:
8969 case OMPD_target_exit_data:
8970 case OMPD_target_enter_data:
8971 case OMPD_distribute:
8972 case OMPD_distribute_simd:
8973 case OMPD_distribute_parallel_for:
8974 case OMPD_distribute_parallel_for_simd:
8975 case OMPD_teams_distribute:
8976 case OMPD_teams_distribute_simd:
8977 case OMPD_teams_distribute_parallel_for:
8978 case OMPD_teams_distribute_parallel_for_simd:
8979 case OMPD_target_update:
8980 case OMPD_declare_simd:
8981 case OMPD_declare_target:
8982 case OMPD_end_declare_target:
8983 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00008984 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008985 case OMPD_taskloop:
8986 case OMPD_taskloop_simd:
Kelvin Li1408f912018-09-26 04:28:39 +00008987 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008988 case OMPD_unknown:
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00008989 llvm_unreachable("Unknown target directive for OpenMP device codegen.");
8990 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00008991 return;
8992 }
8993
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008994 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
Alexey Bataev475a7442018-01-12 19:39:11 +00008995 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
Samuel Antaoee8fb302016-01-06 13:42:12 +00008996 return;
8997
8998 scanForTargetRegionsFunctions(
Alexey Bataev475a7442018-01-12 19:39:11 +00008999 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009000 return;
9001 }
9002
9003 // If this is a lambda function, look into its body.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009004 if (const auto *L = dyn_cast<LambdaExpr>(S))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009005 S = L->getBody();
9006
9007 // Keep looking for target regions recursively.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009008 for (const Stmt *II : S->children())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009009 scanForTargetRegionsFunctions(II, ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009010}
9011
9012bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009013 // If emitting code for the host, we do not process FD here. Instead we do
9014 // the normal code generation.
9015 if (!CGM.getLangOpts().OpenMPIsDevice)
9016 return false;
9017
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009018 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009019 StringRef Name = CGM.getMangledName(GD);
9020 // Try to detect target regions in the function.
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009021 if (const auto *FD = dyn_cast<FunctionDecl>(VD))
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009022 scanForTargetRegionsFunctions(FD->getBody(), Name);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009023
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009024 // Do not to emit function if it is not marked as declare target.
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009025 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009026 AlreadyEmittedTargetFunctions.count(Name) == 0;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009027}
9028
9029bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
9030 if (!CGM.getLangOpts().OpenMPIsDevice)
9031 return false;
9032
9033 // Check if there are Ctors/Dtors in this declaration and look for target
9034 // regions in it. We use the complete variant to produce the kernel name
9035 // mangling.
9036 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009037 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
9038 for (const CXXConstructorDecl *Ctor : RD->ctors()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009039 StringRef ParentName =
9040 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
9041 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
9042 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009043 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009044 StringRef ParentName =
9045 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
9046 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
9047 }
9048 }
9049
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009050 // Do not to emit variable if it is not marked as declare target.
Alexey Bataev92327c52018-03-26 16:40:55 +00009051 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009052 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
9053 cast<VarDecl>(GD.getDecl()));
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009054 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link) {
Alexey Bataevd01b7492018-08-15 19:45:12 +00009055 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009056 return true;
9057 }
9058 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009059}
9060
Alexey Bataev1af5bd52019-03-05 17:47:18 +00009061llvm::Constant *
9062CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF,
9063 const VarDecl *VD) {
9064 assert(VD->getType().isConstant(CGM.getContext()) &&
9065 "Expected constant variable.");
9066 StringRef VarName;
9067 llvm::Constant *Addr;
9068 llvm::GlobalValue::LinkageTypes Linkage;
9069 QualType Ty = VD->getType();
9070 SmallString<128> Buffer;
9071 {
9072 unsigned DeviceID;
9073 unsigned FileID;
9074 unsigned Line;
9075 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID,
9076 FileID, Line);
9077 llvm::raw_svector_ostream OS(Buffer);
9078 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID)
9079 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
9080 VarName = OS.str();
9081 }
9082 Linkage = llvm::GlobalValue::InternalLinkage;
9083 Addr =
9084 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName,
9085 getDefaultFirstprivateAddressSpace());
9086 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage);
9087 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty);
9088 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr));
9089 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9090 VarName, Addr, VarSize,
9091 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage);
9092 return Addr;
9093}
9094
Alexey Bataev03f270c2018-03-30 18:31:07 +00009095void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
9096 llvm::Constant *Addr) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009097 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9098 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
9099 if (!Res) {
9100 if (CGM.getLangOpts().OpenMPIsDevice) {
9101 // Register non-target variables being emitted in device code (debug info
9102 // may cause this).
9103 StringRef VarName = CGM.getMangledName(VD);
9104 EmittedNonTargetVariables.try_emplace(VarName, Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009105 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009106 return;
Alexey Bataev03f270c2018-03-30 18:31:07 +00009107 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009108 // Register declare target variables.
9109 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
9110 StringRef VarName;
9111 CharUnits VarSize;
9112 llvm::GlobalValue::LinkageTypes Linkage;
9113 switch (*Res) {
9114 case OMPDeclareTargetDeclAttr::MT_To:
9115 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9116 VarName = CGM.getMangledName(VD);
9117 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) {
9118 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType());
9119 assert(!VarSize.isZero() && "Expected non-zero size of the variable");
9120 } else {
9121 VarSize = CharUnits::Zero();
9122 }
9123 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
9124 // Temp solution to prevent optimizations of the internal variables.
9125 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) {
9126 std::string RefName = getName({VarName, "ref"});
9127 if (!CGM.GetGlobalValue(RefName)) {
9128 llvm::Constant *AddrRef =
9129 getOrCreateInternalVariable(Addr->getType(), RefName);
9130 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef);
9131 GVAddrRef->setConstant(/*Val=*/true);
9132 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage);
9133 GVAddrRef->setInitializer(Addr);
9134 CGM.addCompilerUsedGlobal(GVAddrRef);
9135 }
9136 }
9137 break;
9138 case OMPDeclareTargetDeclAttr::MT_Link:
9139 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink;
9140 if (CGM.getLangOpts().OpenMPIsDevice) {
9141 VarName = Addr->getName();
9142 Addr = nullptr;
9143 } else {
9144 VarName = getAddrOfDeclareTargetLink(VD).getName();
9145 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetLink(VD).getPointer());
9146 }
9147 VarSize = CGM.getPointerSize();
9148 Linkage = llvm::GlobalValue::WeakAnyLinkage;
9149 break;
9150 }
9151 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9152 VarName, Addr, VarSize, Flags, Linkage);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009153}
9154
Samuel Antaoee8fb302016-01-06 13:42:12 +00009155bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009156 if (isa<FunctionDecl>(GD.getDecl()) ||
9157 isa<OMPDeclareReductionDecl>(GD.getDecl()))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009158 return emitTargetFunctions(GD);
9159
9160 return emitTargetGlobalVariable(GD);
9161}
9162
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009163void CGOpenMPRuntime::emitDeferredTargetDecls() const {
9164 for (const VarDecl *VD : DeferredGlobalVariables) {
9165 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009166 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009167 if (!Res)
9168 continue;
9169 if (*Res == OMPDeclareTargetDeclAttr::MT_To) {
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009170 CGM.EmitGlobal(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009171 } else {
9172 assert(*Res == OMPDeclareTargetDeclAttr::MT_Link &&
9173 "Expected to or link clauses.");
9174 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetLink(VD);
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009175 }
9176 }
9177}
9178
Alexey Bataev60705422018-10-30 15:50:12 +00009179void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas(
9180 CodeGenFunction &CGF, const OMPExecutableDirective &D) const {
9181 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) &&
9182 " Expected target-based directive.");
9183}
9184
Alexey Bataevc5687252019-03-21 19:35:27 +00009185bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD,
9186 LangAS &AS) {
9187 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())
9188 return false;
9189 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
9190 switch(A->getAllocatorType()) {
9191 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
9192 // Not supported, fallback to the default mem space.
9193 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
9194 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
9195 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
9196 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
9197 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
9198 case OMPAllocateDeclAttr::OMPConstMemAlloc:
9199 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
9200 AS = LangAS::Default;
9201 return true;
9202 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
9203 llvm_unreachable("Expected predefined allocator for the variables with the "
9204 "static storage.");
9205 }
9206 return false;
9207}
9208
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009209CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
9210 CodeGenModule &CGM)
9211 : CGM(CGM) {
9212 if (CGM.getLangOpts().OpenMPIsDevice) {
9213 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
9214 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
9215 }
9216}
9217
9218CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() {
9219 if (CGM.getLangOpts().OpenMPIsDevice)
9220 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
9221}
9222
Alexey Bataev6d944102018-05-02 15:45:28 +00009223bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009224 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal)
9225 return true;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009226
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009227 StringRef Name = CGM.getMangledName(GD);
Alexey Bataev6d944102018-05-02 15:45:28 +00009228 const auto *D = cast<FunctionDecl>(GD.getDecl());
Alexey Bataev34f8a702018-03-28 14:28:54 +00009229 // Do not to emit function if it is marked as declare target as it was already
9230 // emitted.
Alexey Bataev97b72212018-08-14 18:31:20 +00009231 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009232 if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) {
9233 if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name)))
Alexey Bataev34f8a702018-03-28 14:28:54 +00009234 return !F->isDeclaration();
9235 return false;
9236 }
9237 return true;
9238 }
9239
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009240 return !AlreadyEmittedTargetFunctions.insert(Name).second;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009241}
9242
Samuel Antaoee8fb302016-01-06 13:42:12 +00009243llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() {
9244 // If we have offloading in the current module, we need to emit the entries
9245 // now and register the offloading descriptor.
9246 createOffloadEntriesAndInfoMetadata();
9247
9248 // Create and register the offloading binary descriptors. This is the main
9249 // entity that captures all the information about offloading in the current
9250 // compilation unit.
9251 return createOffloadingBinaryDescriptorRegistration();
9252}
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009253
9254void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
9255 const OMPExecutableDirective &D,
9256 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00009257 llvm::Function *OutlinedFn,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009258 ArrayRef<llvm::Value *> CapturedVars) {
9259 if (!CGF.HaveInsertPoint())
9260 return;
9261
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009262 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009263 CodeGenFunction::RunCleanupsScope Scope(CGF);
9264
9265 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
9266 llvm::Value *Args[] = {
9267 RTLoc,
9268 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
9269 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
9270 llvm::SmallVector<llvm::Value *, 16> RealArgs;
9271 RealArgs.append(std::begin(Args), std::end(Args));
9272 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
9273
James Y Knight9871db02019-02-05 16:42:33 +00009274 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009275 CGF.EmitRuntimeCall(RTLFn, RealArgs);
9276}
9277
9278void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
Carlo Bertollic6872252016-04-04 15:55:02 +00009279 const Expr *NumTeams,
9280 const Expr *ThreadLimit,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009281 SourceLocation Loc) {
9282 if (!CGF.HaveInsertPoint())
9283 return;
9284
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009285 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009286
Carlo Bertollic6872252016-04-04 15:55:02 +00009287 llvm::Value *NumTeamsVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009288 NumTeams
Carlo Bertollic6872252016-04-04 15:55:02 +00009289 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
9290 CGF.CGM.Int32Ty, /* isSigned = */ true)
9291 : CGF.Builder.getInt32(0);
9292
9293 llvm::Value *ThreadLimitVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009294 ThreadLimit
Carlo Bertollic6872252016-04-04 15:55:02 +00009295 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
9296 CGF.CGM.Int32Ty, /* isSigned = */ true)
9297 : CGF.Builder.getInt32(0);
9298
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009299 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
Carlo Bertollic6872252016-04-04 15:55:02 +00009300 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
9301 ThreadLimitVal};
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009302 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams),
9303 PushNumTeamsArgs);
9304}
Samuel Antaodf158d52016-04-27 22:58:19 +00009305
Samuel Antaocc10b852016-07-28 14:23:26 +00009306void CGOpenMPRuntime::emitTargetDataCalls(
9307 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
9308 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009309 if (!CGF.HaveInsertPoint())
9310 return;
9311
Samuel Antaocc10b852016-07-28 14:23:26 +00009312 // Action used to replace the default codegen action and turn privatization
9313 // off.
9314 PrePostActionTy NoPrivAction;
Samuel Antaodf158d52016-04-27 22:58:19 +00009315
9316 // Generate the code for the opening of the data environment. Capture all the
9317 // arguments of the runtime call by reference because they are used in the
9318 // closing of the region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009319 auto &&BeginThenGen = [this, &D, Device, &Info,
9320 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009321 // Fill up the arrays with all the mapped variables.
Samuel Antaocc10b852016-07-28 14:23:26 +00009322 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
Samuel Antaodf158d52016-04-27 22:58:19 +00009323 MappableExprsHandler::MapValuesArrayTy Pointers;
9324 MappableExprsHandler::MapValuesArrayTy Sizes;
9325 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9326
9327 // Get map clause information.
9328 MappableExprsHandler MCHandler(D, CGF);
9329 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
Samuel Antaodf158d52016-04-27 22:58:19 +00009330
9331 // Fill up the arrays and create the arguments.
Samuel Antaocc10b852016-07-28 14:23:26 +00009332 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +00009333
9334 llvm::Value *BasePointersArrayArg = nullptr;
9335 llvm::Value *PointersArrayArg = nullptr;
9336 llvm::Value *SizesArrayArg = nullptr;
9337 llvm::Value *MapTypesArrayArg = nullptr;
9338 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00009339 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +00009340
9341 // Emit device ID if any.
9342 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +00009343 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009344 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009345 CGF.Int64Ty, /*isSigned=*/true);
9346 } else {
9347 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9348 }
Samuel Antaodf158d52016-04-27 22:58:19 +00009349
9350 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009351 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +00009352
9353 llvm::Value *OffloadingArgs[] = {
9354 DeviceID, PointerNum, BasePointersArrayArg,
9355 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009356 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin),
Samuel Antaodf158d52016-04-27 22:58:19 +00009357 OffloadingArgs);
Samuel Antaocc10b852016-07-28 14:23:26 +00009358
9359 // If device pointer privatization is required, emit the body of the region
9360 // here. It will have to be duplicated: with and without privatization.
9361 if (!Info.CaptureDeviceAddrMap.empty())
9362 CodeGen(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +00009363 };
9364
9365 // Generate code for the closing of the data region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009366 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF,
9367 PrePostActionTy &) {
Samuel Antaocc10b852016-07-28 14:23:26 +00009368 assert(Info.isValid() && "Invalid data environment closing arguments.");
Samuel Antaodf158d52016-04-27 22:58:19 +00009369
9370 llvm::Value *BasePointersArrayArg = nullptr;
9371 llvm::Value *PointersArrayArg = nullptr;
9372 llvm::Value *SizesArrayArg = nullptr;
9373 llvm::Value *MapTypesArrayArg = nullptr;
9374 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00009375 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +00009376
9377 // Emit device ID if any.
9378 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +00009379 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009380 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009381 CGF.Int64Ty, /*isSigned=*/true);
9382 } else {
9383 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9384 }
Samuel Antaodf158d52016-04-27 22:58:19 +00009385
9386 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009387 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +00009388
9389 llvm::Value *OffloadingArgs[] = {
9390 DeviceID, PointerNum, BasePointersArrayArg,
9391 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009392 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end),
Samuel Antaodf158d52016-04-27 22:58:19 +00009393 OffloadingArgs);
9394 };
9395
Samuel Antaocc10b852016-07-28 14:23:26 +00009396 // If we need device pointer privatization, we need to emit the body of the
9397 // region with no privatization in the 'else' branch of the conditional.
9398 // Otherwise, we don't have to do anything.
9399 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF,
9400 PrePostActionTy &) {
9401 if (!Info.CaptureDeviceAddrMap.empty()) {
9402 CodeGen.setAction(NoPrivAction);
9403 CodeGen(CGF);
9404 }
9405 };
9406
9407 // We don't have to do anything to close the region if the if clause evaluates
9408 // to false.
9409 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
Samuel Antaodf158d52016-04-27 22:58:19 +00009410
9411 if (IfCond) {
Samuel Antaocc10b852016-07-28 14:23:26 +00009412 emitOMPIfClause(CGF, IfCond, BeginThenGen, BeginElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +00009413 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +00009414 RegionCodeGenTy RCG(BeginThenGen);
9415 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +00009416 }
9417
Samuel Antaocc10b852016-07-28 14:23:26 +00009418 // If we don't require privatization of device pointers, we emit the body in
9419 // between the runtime calls. This avoids duplicating the body code.
9420 if (Info.CaptureDeviceAddrMap.empty()) {
9421 CodeGen.setAction(NoPrivAction);
9422 CodeGen(CGF);
9423 }
Samuel Antaodf158d52016-04-27 22:58:19 +00009424
9425 if (IfCond) {
Samuel Antaocc10b852016-07-28 14:23:26 +00009426 emitOMPIfClause(CGF, IfCond, EndThenGen, EndElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +00009427 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +00009428 RegionCodeGenTy RCG(EndThenGen);
9429 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +00009430 }
9431}
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009432
Samuel Antao8d2d7302016-05-26 18:30:22 +00009433void CGOpenMPRuntime::emitTargetDataStandAloneCall(
Samuel Antao8dd66282016-04-27 23:14:30 +00009434 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
9435 const Expr *Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009436 if (!CGF.HaveInsertPoint())
9437 return;
9438
Samuel Antao8dd66282016-04-27 23:14:30 +00009439 assert((isa<OMPTargetEnterDataDirective>(D) ||
Samuel Antao8d2d7302016-05-26 18:30:22 +00009440 isa<OMPTargetExitDataDirective>(D) ||
9441 isa<OMPTargetUpdateDirective>(D)) &&
9442 "Expecting either target enter, exit data, or update directives.");
Samuel Antao8dd66282016-04-27 23:14:30 +00009443
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009444 CodeGenFunction::OMPTargetDataInfo InputInfo;
9445 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009446 // Generate the code for the opening of the data environment.
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009447 auto &&ThenGen = [this, &D, Device, &InputInfo,
9448 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009449 // Emit device ID if any.
9450 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +00009451 if (Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009452 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009453 CGF.Int64Ty, /*isSigned=*/true);
9454 } else {
9455 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9456 }
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009457
9458 // Emit the number of elements in the offloading arrays.
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009459 llvm::Constant *PointerNum =
9460 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009461
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009462 llvm::Value *OffloadingArgs[] = {DeviceID,
9463 PointerNum,
9464 InputInfo.BasePointersArray.getPointer(),
9465 InputInfo.PointersArray.getPointer(),
9466 InputInfo.SizesArray.getPointer(),
9467 MapTypesArray};
Samuel Antao8d2d7302016-05-26 18:30:22 +00009468
Samuel Antao8d2d7302016-05-26 18:30:22 +00009469 // Select the right runtime function call for each expected standalone
9470 // directive.
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00009471 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Samuel Antao8d2d7302016-05-26 18:30:22 +00009472 OpenMPRTLFunction RTLFn;
9473 switch (D.getDirectiveKind()) {
Samuel Antao8d2d7302016-05-26 18:30:22 +00009474 case OMPD_target_enter_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00009475 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait
9476 : OMPRTL__tgt_target_data_begin;
Samuel Antao8d2d7302016-05-26 18:30:22 +00009477 break;
9478 case OMPD_target_exit_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00009479 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait
9480 : OMPRTL__tgt_target_data_end;
Samuel Antao8d2d7302016-05-26 18:30:22 +00009481 break;
9482 case OMPD_target_update:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00009483 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait
9484 : OMPRTL__tgt_target_data_update;
Samuel Antao8d2d7302016-05-26 18:30:22 +00009485 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009486 case OMPD_parallel:
9487 case OMPD_for:
9488 case OMPD_parallel_for:
9489 case OMPD_parallel_sections:
9490 case OMPD_for_simd:
9491 case OMPD_parallel_for_simd:
9492 case OMPD_cancel:
9493 case OMPD_cancellation_point:
9494 case OMPD_ordered:
9495 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00009496 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009497 case OMPD_task:
9498 case OMPD_simd:
9499 case OMPD_sections:
9500 case OMPD_section:
9501 case OMPD_single:
9502 case OMPD_master:
9503 case OMPD_critical:
9504 case OMPD_taskyield:
9505 case OMPD_barrier:
9506 case OMPD_taskwait:
9507 case OMPD_taskgroup:
9508 case OMPD_atomic:
9509 case OMPD_flush:
9510 case OMPD_teams:
9511 case OMPD_target_data:
9512 case OMPD_distribute:
9513 case OMPD_distribute_simd:
9514 case OMPD_distribute_parallel_for:
9515 case OMPD_distribute_parallel_for_simd:
9516 case OMPD_teams_distribute:
9517 case OMPD_teams_distribute_simd:
9518 case OMPD_teams_distribute_parallel_for:
9519 case OMPD_teams_distribute_parallel_for_simd:
9520 case OMPD_declare_simd:
9521 case OMPD_declare_target:
9522 case OMPD_end_declare_target:
9523 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00009524 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009525 case OMPD_taskloop:
9526 case OMPD_taskloop_simd:
9527 case OMPD_target:
9528 case OMPD_target_simd:
9529 case OMPD_target_teams_distribute:
9530 case OMPD_target_teams_distribute_simd:
9531 case OMPD_target_teams_distribute_parallel_for:
9532 case OMPD_target_teams_distribute_parallel_for_simd:
9533 case OMPD_target_teams:
9534 case OMPD_target_parallel:
9535 case OMPD_target_parallel_for:
9536 case OMPD_target_parallel_for_simd:
Kelvin Li1408f912018-09-26 04:28:39 +00009537 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009538 case OMPD_unknown:
9539 llvm_unreachable("Unexpected standalone target data directive.");
9540 break;
Samuel Antao8d2d7302016-05-26 18:30:22 +00009541 }
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009542 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009543 };
9544
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009545 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray](
9546 CodeGenFunction &CGF, PrePostActionTy &) {
9547 // Fill up the arrays with all the mapped variables.
9548 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
9549 MappableExprsHandler::MapValuesArrayTy Pointers;
9550 MappableExprsHandler::MapValuesArrayTy Sizes;
9551 MappableExprsHandler::MapFlagsArrayTy MapTypes;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009552
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009553 // Get map clause information.
9554 MappableExprsHandler MEHandler(D, CGF);
9555 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
9556
9557 TargetDataInfo Info;
9558 // Fill up the arrays and create the arguments.
9559 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
9560 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
9561 Info.PointersArray, Info.SizesArray,
9562 Info.MapTypesArray, Info);
9563 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
9564 InputInfo.BasePointersArray =
9565 Address(Info.BasePointersArray, CGM.getPointerAlign());
9566 InputInfo.PointersArray =
9567 Address(Info.PointersArray, CGM.getPointerAlign());
9568 InputInfo.SizesArray =
9569 Address(Info.SizesArray, CGM.getPointerAlign());
9570 MapTypesArray = Info.MapTypesArray;
9571 if (D.hasClausesOfKind<OMPDependClause>())
9572 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
9573 else
Alexey Bataev768f1f22018-01-09 19:59:25 +00009574 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009575 };
9576
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009577 if (IfCond) {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009578 emitOMPIfClause(CGF, IfCond, TargetThenGen,
9579 [](CodeGenFunction &CGF, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009580 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009581 RegionCodeGenTy ThenRCG(TargetThenGen);
9582 ThenRCG(CGF);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009583 }
9584}
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009585
9586namespace {
9587 /// Kind of parameter in a function with 'declare simd' directive.
9588 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector };
9589 /// Attribute set of the parameter.
9590 struct ParamAttrTy {
9591 ParamKindTy Kind = Vector;
9592 llvm::APSInt StrideOrArg;
9593 llvm::APSInt Alignment;
9594 };
9595} // namespace
9596
9597static unsigned evaluateCDTSize(const FunctionDecl *FD,
9598 ArrayRef<ParamAttrTy> ParamAttrs) {
9599 // Every vector variant of a SIMD-enabled function has a vector length (VLEN).
9600 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument
9601 // of that clause. The VLEN value must be power of 2.
9602 // In other case the notion of the function`s "characteristic data type" (CDT)
9603 // is used to compute the vector length.
9604 // CDT is defined in the following order:
9605 // a) For non-void function, the CDT is the return type.
9606 // b) If the function has any non-uniform, non-linear parameters, then the
9607 // CDT is the type of the first such parameter.
9608 // c) If the CDT determined by a) or b) above is struct, union, or class
9609 // type which is pass-by-value (except for the type that maps to the
9610 // built-in complex data type), the characteristic data type is int.
9611 // d) If none of the above three cases is applicable, the CDT is int.
9612 // The VLEN is then determined based on the CDT and the size of vector
9613 // register of that ISA for which current vector version is generated. The
9614 // VLEN is computed using the formula below:
9615 // VLEN = sizeof(vector_register) / sizeof(CDT),
9616 // where vector register size specified in section 3.2.1 Registers and the
9617 // Stack Frame of original AMD64 ABI document.
9618 QualType RetType = FD->getReturnType();
9619 if (RetType.isNull())
9620 return 0;
9621 ASTContext &C = FD->getASTContext();
9622 QualType CDT;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009623 if (!RetType.isNull() && !RetType->isVoidType()) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009624 CDT = RetType;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009625 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009626 unsigned Offset = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009627 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009628 if (ParamAttrs[Offset].Kind == Vector)
9629 CDT = C.getPointerType(C.getRecordType(MD->getParent()));
9630 ++Offset;
9631 }
9632 if (CDT.isNull()) {
9633 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
9634 if (ParamAttrs[I + Offset].Kind == Vector) {
9635 CDT = FD->getParamDecl(I)->getType();
9636 break;
9637 }
9638 }
9639 }
9640 }
9641 if (CDT.isNull())
9642 CDT = C.IntTy;
9643 CDT = CDT->getCanonicalTypeUnqualified();
9644 if (CDT->isRecordType() || CDT->isUnionType())
9645 CDT = C.IntTy;
9646 return C.getTypeSize(CDT);
9647}
9648
9649static void
9650emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
Benjamin Kramer81cb4b72016-11-24 16:01:20 +00009651 const llvm::APSInt &VLENVal,
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009652 ArrayRef<ParamAttrTy> ParamAttrs,
9653 OMPDeclareSimdDeclAttr::BranchStateTy State) {
9654 struct ISADataTy {
9655 char ISA;
9656 unsigned VecRegSize;
9657 };
9658 ISADataTy ISAData[] = {
9659 {
9660 'b', 128
9661 }, // SSE
9662 {
9663 'c', 256
9664 }, // AVX
9665 {
9666 'd', 256
9667 }, // AVX2
9668 {
9669 'e', 512
9670 }, // AVX512
9671 };
9672 llvm::SmallVector<char, 2> Masked;
9673 switch (State) {
9674 case OMPDeclareSimdDeclAttr::BS_Undefined:
9675 Masked.push_back('N');
9676 Masked.push_back('M');
9677 break;
9678 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
9679 Masked.push_back('N');
9680 break;
9681 case OMPDeclareSimdDeclAttr::BS_Inbranch:
9682 Masked.push_back('M');
9683 break;
9684 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009685 for (char Mask : Masked) {
9686 for (const ISADataTy &Data : ISAData) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009687 SmallString<256> Buffer;
9688 llvm::raw_svector_ostream Out(Buffer);
9689 Out << "_ZGV" << Data.ISA << Mask;
9690 if (!VLENVal) {
9691 Out << llvm::APSInt::getUnsigned(Data.VecRegSize /
9692 evaluateCDTSize(FD, ParamAttrs));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009693 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009694 Out << VLENVal;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009695 }
9696 for (const ParamAttrTy &ParamAttr : ParamAttrs) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009697 switch (ParamAttr.Kind){
9698 case LinearWithVarStride:
9699 Out << 's' << ParamAttr.StrideOrArg;
9700 break;
9701 case Linear:
9702 Out << 'l';
9703 if (!!ParamAttr.StrideOrArg)
9704 Out << ParamAttr.StrideOrArg;
9705 break;
9706 case Uniform:
9707 Out << 'u';
9708 break;
9709 case Vector:
9710 Out << 'v';
9711 break;
9712 }
9713 if (!!ParamAttr.Alignment)
9714 Out << 'a' << ParamAttr.Alignment;
9715 }
9716 Out << '_' << Fn->getName();
9717 Fn->addFnAttr(Out.str());
9718 }
9719 }
9720}
9721
Alexey Bataeva0a22642019-04-16 13:56:21 +00009722// This are the Functions that are needed to mangle the name of the
9723// vector functions generated by the compiler, according to the rules
9724// defined in the "Vector Function ABI specifications for AArch64",
9725// available at
9726// https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi.
9727
9728/// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI.
9729///
9730/// TODO: Need to implement the behavior for reference marked with a
9731/// var or no linear modifiers (1.b in the section). For this, we
9732/// need to extend ParamKindTy to support the linear modifiers.
9733static bool getAArch64MTV(QualType QT, ParamKindTy Kind) {
9734 QT = QT.getCanonicalType();
9735
9736 if (QT->isVoidType())
9737 return false;
9738
9739 if (Kind == ParamKindTy::Uniform)
9740 return false;
9741
9742 if (Kind == ParamKindTy::Linear)
9743 return false;
9744
9745 // TODO: Handle linear references with modifiers
9746
9747 if (Kind == ParamKindTy::LinearWithVarStride)
9748 return false;
9749
9750 return true;
9751}
9752
9753/// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
9754static bool getAArch64PBV(QualType QT, ASTContext &C) {
9755 QT = QT.getCanonicalType();
9756 unsigned Size = C.getTypeSize(QT);
9757
9758 // Only scalars and complex within 16 bytes wide set PVB to true.
9759 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
9760 return false;
9761
9762 if (QT->isFloatingType())
9763 return true;
9764
9765 if (QT->isIntegerType())
9766 return true;
9767
9768 if (QT->isPointerType())
9769 return true;
9770
9771 // TODO: Add support for complex types (section 3.1.2, item 2).
9772
9773 return false;
9774}
9775
9776/// Computes the lane size (LS) of a return type or of an input parameter,
9777/// as defined by `LS(P)` in 3.2.1 of the AAVFABI.
9778/// TODO: Add support for references, section 3.2.1, item 1.
9779static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) {
9780 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) {
9781 QualType PTy = QT.getCanonicalType()->getPointeeType();
9782 if (getAArch64PBV(PTy, C))
9783 return C.getTypeSize(PTy);
9784 }
9785 if (getAArch64PBV(QT, C))
9786 return C.getTypeSize(QT);
9787
9788 return C.getTypeSize(C.getUIntPtrType());
9789}
9790
9791// Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the
9792// signature of the scalar function, as defined in 3.2.2 of the
9793// AAVFABI.
9794static std::tuple<unsigned, unsigned, bool>
9795getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) {
9796 QualType RetType = FD->getReturnType().getCanonicalType();
9797
9798 ASTContext &C = FD->getASTContext();
9799
9800 bool OutputBecomesInput = false;
9801
9802 llvm::SmallVector<unsigned, 8> Sizes;
9803 if (!RetType->isVoidType()) {
9804 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C));
9805 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {}))
9806 OutputBecomesInput = true;
9807 }
9808 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
9809 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType();
9810 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C));
9811 }
9812
9813 assert(!Sizes.empty() && "Unable to determine NDS and WDS.");
9814 // The LS of a function parameter / return value can only be a power
9815 // of 2, starting from 8 bits, up to 128.
9816 assert(std::all_of(Sizes.begin(), Sizes.end(),
9817 [](unsigned Size) {
9818 return Size == 8 || Size == 16 || Size == 32 ||
9819 Size == 64 || Size == 128;
9820 }) &&
9821 "Invalid size");
9822
9823 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)),
9824 *std::max_element(std::begin(Sizes), std::end(Sizes)),
9825 OutputBecomesInput);
9826}
9827
9828/// Mangle the parameter part of the vector function name according to
9829/// their OpenMP classification. The mangling function is defined in
9830/// section 3.5 of the AAVFABI.
9831static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) {
9832 SmallString<256> Buffer;
9833 llvm::raw_svector_ostream Out(Buffer);
9834 for (const auto &ParamAttr : ParamAttrs) {
9835 switch (ParamAttr.Kind) {
9836 case LinearWithVarStride:
9837 Out << "ls" << ParamAttr.StrideOrArg;
9838 break;
9839 case Linear:
9840 Out << 'l';
9841 // Don't print the step value if it is not present or if it is
9842 // equal to 1.
9843 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1)
9844 Out << ParamAttr.StrideOrArg;
9845 break;
9846 case Uniform:
9847 Out << 'u';
9848 break;
9849 case Vector:
9850 Out << 'v';
9851 break;
9852 }
9853
9854 if (!!ParamAttr.Alignment)
9855 Out << 'a' << ParamAttr.Alignment;
9856 }
9857
9858 return Out.str();
9859}
9860
9861// Function used to add the attribute. The parameter `VLEN` is
9862// templated to allow the use of "x" when targeting scalable functions
9863// for SVE.
9864template <typename T>
9865static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix,
9866 char ISA, StringRef ParSeq,
9867 StringRef MangledName, bool OutputBecomesInput,
9868 llvm::Function *Fn) {
9869 SmallString<256> Buffer;
9870 llvm::raw_svector_ostream Out(Buffer);
9871 Out << Prefix << ISA << LMask << VLEN;
9872 if (OutputBecomesInput)
9873 Out << "v";
9874 Out << ParSeq << "_" << MangledName;
9875 Fn->addFnAttr(Out.str());
9876}
9877
9878// Helper function to generate the Advanced SIMD names depending on
9879// the value of the NDS when simdlen is not present.
9880static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask,
9881 StringRef Prefix, char ISA,
9882 StringRef ParSeq, StringRef MangledName,
9883 bool OutputBecomesInput,
9884 llvm::Function *Fn) {
9885 switch (NDS) {
9886 case 8:
9887 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
9888 OutputBecomesInput, Fn);
9889 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName,
9890 OutputBecomesInput, Fn);
9891 break;
9892 case 16:
9893 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
9894 OutputBecomesInput, Fn);
9895 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
9896 OutputBecomesInput, Fn);
9897 break;
9898 case 32:
9899 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
9900 OutputBecomesInput, Fn);
9901 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
9902 OutputBecomesInput, Fn);
9903 break;
9904 case 64:
9905 case 128:
9906 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
9907 OutputBecomesInput, Fn);
9908 break;
9909 default:
9910 llvm_unreachable("Scalar type is too wide.");
9911 }
9912}
9913
9914/// Emit vector function attributes for AArch64, as defined in the AAVFABI.
9915static void emitAArch64DeclareSimdFunction(
9916 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN,
9917 ArrayRef<ParamAttrTy> ParamAttrs,
9918 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
9919 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) {
9920
9921 // Get basic data for building the vector signature.
9922 const auto Data = getNDSWDS(FD, ParamAttrs);
9923 const unsigned NDS = std::get<0>(Data);
9924 const unsigned WDS = std::get<1>(Data);
9925 const bool OutputBecomesInput = std::get<2>(Data);
9926
9927 // Check the values provided via `simdlen` by the user.
9928 // 1. A `simdlen(1)` doesn't produce vector signatures,
9929 if (UserVLEN == 1) {
9930 unsigned DiagID = CGM.getDiags().getCustomDiagID(
9931 DiagnosticsEngine::Warning,
9932 "The clause simdlen(1) has no effect when targeting aarch64.");
9933 CGM.getDiags().Report(SLoc, DiagID);
9934 return;
9935 }
9936
9937 // 2. Section 3.3.1, item 1: user input must be a power of 2 for
9938 // Advanced SIMD output.
9939 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
9940 unsigned DiagID = CGM.getDiags().getCustomDiagID(
9941 DiagnosticsEngine::Warning, "The value specified in simdlen must be a "
9942 "power of 2 when targeting Advanced SIMD.");
9943 CGM.getDiags().Report(SLoc, DiagID);
9944 return;
9945 }
9946
9947 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural
9948 // limits.
9949 if (ISA == 's' && UserVLEN != 0) {
9950 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
9951 unsigned DiagID = CGM.getDiags().getCustomDiagID(
9952 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit "
9953 "lanes in the architectural constraints "
9954 "for SVE (min is 128-bit, max is "
9955 "2048-bit, by steps of 128-bit)");
9956 CGM.getDiags().Report(SLoc, DiagID) << WDS;
9957 return;
9958 }
9959 }
9960
9961 // Sort out parameter sequence.
9962 const std::string ParSeq = mangleVectorParameters(ParamAttrs);
9963 StringRef Prefix = "_ZGV";
9964 // Generate simdlen from user input (if any).
9965 if (UserVLEN) {
9966 if (ISA == 's') {
9967 // SVE generates only a masked function.
9968 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
9969 OutputBecomesInput, Fn);
9970 } else {
9971 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
9972 // Advanced SIMD generates one or two functions, depending on
9973 // the `[not]inbranch` clause.
9974 switch (State) {
9975 case OMPDeclareSimdDeclAttr::BS_Undefined:
9976 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
9977 OutputBecomesInput, Fn);
9978 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
9979 OutputBecomesInput, Fn);
9980 break;
9981 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
9982 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
9983 OutputBecomesInput, Fn);
9984 break;
9985 case OMPDeclareSimdDeclAttr::BS_Inbranch:
9986 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
9987 OutputBecomesInput, Fn);
9988 break;
9989 }
9990 }
9991 } else {
9992 // If no user simdlen is provided, follow the AAVFABI rules for
9993 // generating the vector length.
9994 if (ISA == 's') {
9995 // SVE, section 3.4.1, item 1.
9996 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName,
9997 OutputBecomesInput, Fn);
9998 } else {
9999 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10000 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or
10001 // two vector names depending on the use of the clause
10002 // `[not]inbranch`.
10003 switch (State) {
10004 case OMPDeclareSimdDeclAttr::BS_Undefined:
10005 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10006 OutputBecomesInput, Fn);
10007 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10008 OutputBecomesInput, Fn);
10009 break;
10010 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10011 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10012 OutputBecomesInput, Fn);
10013 break;
10014 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10015 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10016 OutputBecomesInput, Fn);
10017 break;
10018 }
10019 }
10020 }
10021}
10022
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010023void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
10024 llvm::Function *Fn) {
10025 ASTContext &C = CGM.getContext();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010026 FD = FD->getMostRecentDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010027 // Map params to their positions in function decl.
10028 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
10029 if (isa<CXXMethodDecl>(FD))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010030 ParamPositions.try_emplace(FD, 0);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010031 unsigned ParamPos = ParamPositions.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010032 for (const ParmVarDecl *P : FD->parameters()) {
10033 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010034 ++ParamPos;
10035 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010036 while (FD) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010037 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010038 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
10039 // Mark uniform parameters.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010040 for (const Expr *E : Attr->uniforms()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010041 E = E->IgnoreParenImpCasts();
10042 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010043 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010044 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010045 } else {
10046 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10047 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010048 Pos = ParamPositions[PVD];
10049 }
10050 ParamAttrs[Pos].Kind = Uniform;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010051 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010052 // Get alignment info.
10053 auto NI = Attr->alignments_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010054 for (const Expr *E : Attr->aligneds()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010055 E = E->IgnoreParenImpCasts();
10056 unsigned Pos;
10057 QualType ParmTy;
10058 if (isa<CXXThisExpr>(E)) {
10059 Pos = ParamPositions[FD];
10060 ParmTy = E->getType();
10061 } else {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010062 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10063 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010064 Pos = ParamPositions[PVD];
10065 ParmTy = PVD->getType();
10066 }
10067 ParamAttrs[Pos].Alignment =
10068 (*NI)
10069 ? (*NI)->EvaluateKnownConstInt(C)
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010070 : llvm::APSInt::getUnsigned(
10071 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy))
10072 .getQuantity());
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010073 ++NI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010074 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010075 // Mark linear parameters.
10076 auto SI = Attr->steps_begin();
10077 auto MI = Attr->modifiers_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010078 for (const Expr *E : Attr->linears()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010079 E = E->IgnoreParenImpCasts();
10080 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010081 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010082 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010083 } else {
10084 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10085 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010086 Pos = ParamPositions[PVD];
10087 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010088 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010089 ParamAttr.Kind = Linear;
10090 if (*SI) {
Fangrui Song407659a2018-11-30 23:41:18 +000010091 Expr::EvalResult Result;
10092 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010093 if (const auto *DRE =
10094 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
10095 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010096 ParamAttr.Kind = LinearWithVarStride;
10097 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(
10098 ParamPositions[StridePVD->getCanonicalDecl()]);
10099 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010100 }
Fangrui Song407659a2018-11-30 23:41:18 +000010101 } else {
10102 ParamAttr.StrideOrArg = Result.Val.getInt();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010103 }
10104 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010105 ++SI;
10106 ++MI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010107 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010108 llvm::APSInt VLENVal;
Alexey Bataeva0a22642019-04-16 13:56:21 +000010109 SourceLocation ExprLoc;
10110 const Expr *VLENExpr = Attr->getSimdlen();
10111 if (VLENExpr) {
10112 VLENVal = VLENExpr->EvaluateKnownConstInt(C);
10113 ExprLoc = VLENExpr->getExprLoc();
10114 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010115 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
10116 if (CGM.getTriple().getArch() == llvm::Triple::x86 ||
Alexey Bataeva0a22642019-04-16 13:56:21 +000010117 CGM.getTriple().getArch() == llvm::Triple::x86_64) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010118 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
Alexey Bataeva0a22642019-04-16 13:56:21 +000010119 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) {
10120 unsigned VLEN = VLENVal.getExtValue();
10121 StringRef MangledName = Fn->getName();
10122 if (CGM.getTarget().hasFeature("sve"))
10123 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10124 MangledName, 's', 128, Fn, ExprLoc);
10125 if (CGM.getTarget().hasFeature("neon"))
10126 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10127 MangledName, 'n', 128, Fn, ExprLoc);
10128 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010129 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010130 FD = FD->getPreviousDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010131 }
10132}
Alexey Bataev8b427062016-05-25 12:36:08 +000010133
10134namespace {
10135/// Cleanup action for doacross support.
10136class DoacrossCleanupTy final : public EHScopeStack::Cleanup {
10137public:
10138 static const int DoacrossFinArgs = 2;
10139
10140private:
James Y Knight9871db02019-02-05 16:42:33 +000010141 llvm::FunctionCallee RTLFn;
Alexey Bataev8b427062016-05-25 12:36:08 +000010142 llvm::Value *Args[DoacrossFinArgs];
10143
10144public:
James Y Knight9871db02019-02-05 16:42:33 +000010145 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
10146 ArrayRef<llvm::Value *> CallArgs)
Alexey Bataev8b427062016-05-25 12:36:08 +000010147 : RTLFn(RTLFn) {
10148 assert(CallArgs.size() == DoacrossFinArgs);
10149 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10150 }
10151 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10152 if (!CGF.HaveInsertPoint())
10153 return;
10154 CGF.EmitRuntimeCall(RTLFn, Args);
10155 }
10156};
10157} // namespace
10158
10159void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000010160 const OMPLoopDirective &D,
10161 ArrayRef<Expr *> NumIterations) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010162 if (!CGF.HaveInsertPoint())
10163 return;
10164
10165 ASTContext &C = CGM.getContext();
10166 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
10167 RecordDecl *RD;
10168 if (KmpDimTy.isNull()) {
10169 // Build struct kmp_dim { // loop bounds info casted to kmp_int64
10170 // kmp_int64 lo; // lower
10171 // kmp_int64 up; // upper
10172 // kmp_int64 st; // stride
10173 // };
10174 RD = C.buildImplicitRecord("kmp_dim");
10175 RD->startDefinition();
10176 addFieldToRecordDecl(C, RD, Int64Ty);
10177 addFieldToRecordDecl(C, RD, Int64Ty);
10178 addFieldToRecordDecl(C, RD, Int64Ty);
10179 RD->completeDefinition();
10180 KmpDimTy = C.getRecordType(RD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010181 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010182 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010183 }
Alexey Bataevf138fda2018-08-13 19:04:24 +000010184 llvm::APInt Size(/*numBits=*/32, NumIterations.size());
10185 QualType ArrayTy =
10186 C.getConstantArrayType(KmpDimTy, Size, ArrayType::Normal, 0);
Alexey Bataev8b427062016-05-25 12:36:08 +000010187
Alexey Bataevf138fda2018-08-13 19:04:24 +000010188 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
10189 CGF.EmitNullInitialization(DimsAddr, ArrayTy);
Alexey Bataev8b427062016-05-25 12:36:08 +000010190 enum { LowerFD = 0, UpperFD, StrideFD };
10191 // Fill dims with data.
Alexey Bataevf138fda2018-08-13 19:04:24 +000010192 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +000010193 LValue DimsLVal = CGF.MakeAddrLValue(
10194 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010195 // dims.upper = num_iterations;
10196 LValue UpperLVal = CGF.EmitLValueForField(
10197 DimsLVal, *std::next(RD->field_begin(), UpperFD));
10198 llvm::Value *NumIterVal =
10199 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]),
10200 D.getNumIterations()->getType(), Int64Ty,
10201 D.getNumIterations()->getExprLoc());
10202 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
10203 // dims.stride = 1;
10204 LValue StrideLVal = CGF.EmitLValueForField(
10205 DimsLVal, *std::next(RD->field_begin(), StrideFD));
10206 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
10207 StrideLVal);
10208 }
Alexey Bataev8b427062016-05-25 12:36:08 +000010209
10210 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
10211 // kmp_int32 num_dims, struct kmp_dim * dims);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010212 llvm::Value *Args[] = {
10213 emitUpdateLocation(CGF, D.getBeginLoc()),
10214 getThreadID(CGF, D.getBeginLoc()),
10215 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()),
10216 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knight751fe282019-02-09 22:22:28 +000010217 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(),
Alexey Bataevf138fda2018-08-13 19:04:24 +000010218 CGM.VoidPtrTy)};
Alexey Bataev8b427062016-05-25 12:36:08 +000010219
James Y Knight9871db02019-02-05 16:42:33 +000010220 llvm::FunctionCallee RTLFn =
10221 createRuntimeFunction(OMPRTL__kmpc_doacross_init);
Alexey Bataev8b427062016-05-25 12:36:08 +000010222 CGF.EmitRuntimeCall(RTLFn, Args);
10223 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
Stephen Kelly1c301dc2018-08-09 21:09:38 +000010224 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())};
James Y Knight9871db02019-02-05 16:42:33 +000010225 llvm::FunctionCallee FiniRTLFn =
10226 createRuntimeFunction(OMPRTL__kmpc_doacross_fini);
Alexey Bataev8b427062016-05-25 12:36:08 +000010227 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
10228 llvm::makeArrayRef(FiniArgs));
10229}
10230
10231void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
10232 const OMPDependClause *C) {
10233 QualType Int64Ty =
10234 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010235 llvm::APInt Size(/*numBits=*/32, C->getNumLoops());
10236 QualType ArrayTy = CGM.getContext().getConstantArrayType(
10237 Int64Ty, Size, ArrayType::Normal, 0);
10238 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr");
10239 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) {
10240 const Expr *CounterVal = C->getLoopData(I);
10241 assert(CounterVal);
10242 llvm::Value *CntVal = CGF.EmitScalarConversion(
10243 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
10244 CounterVal->getExprLoc());
James Y Knight751fe282019-02-09 22:22:28 +000010245 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I),
10246 /*Volatile=*/false, Int64Ty);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010247 }
10248 llvm::Value *Args[] = {
10249 emitUpdateLocation(CGF, C->getBeginLoc()),
10250 getThreadID(CGF, C->getBeginLoc()),
James Y Knight751fe282019-02-09 22:22:28 +000010251 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()};
James Y Knight9871db02019-02-05 16:42:33 +000010252 llvm::FunctionCallee RTLFn;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010253 if (C->getDependencyKind() == OMPC_DEPEND_source) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010254 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010255 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010256 assert(C->getDependencyKind() == OMPC_DEPEND_sink);
10257 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait);
10258 }
10259 CGF.EmitRuntimeCall(RTLFn, Args);
10260}
10261
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010262void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000010263 llvm::FunctionCallee Callee,
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010264 ArrayRef<llvm::Value *> Args) const {
10265 assert(Loc.isValid() && "Outlined function call location must be valid.");
Alexey Bataev3c595a62017-08-14 15:01:03 +000010266 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
10267
James Y Knight9871db02019-02-05 16:42:33 +000010268 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010269 if (Fn->doesNotThrow()) {
Alexey Bataev3c595a62017-08-14 15:01:03 +000010270 CGF.EmitNounwindRuntimeCall(Fn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010271 return;
10272 }
10273 }
Alexey Bataev3c595a62017-08-14 15:01:03 +000010274 CGF.EmitRuntimeCall(Callee, Args);
10275}
10276
10277void CGOpenMPRuntime::emitOutlinedFunctionCall(
James Y Knight9871db02019-02-05 16:42:33 +000010278 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn,
Alexey Bataev3c595a62017-08-14 15:01:03 +000010279 ArrayRef<llvm::Value *> Args) const {
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010280 emitCall(CGF, Loc, OutlinedFn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010281}
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010282
10283Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
10284 const VarDecl *NativeParam,
10285 const VarDecl *TargetParam) const {
10286 return CGF.GetAddrOfLocalVar(NativeParam);
10287}
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010288
Alexey Bataev4f680db2019-03-19 16:41:16 +000010289namespace {
10290/// Cleanup action for allocate support.
10291class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup {
10292public:
10293 static const int CleanupArgs = 3;
10294
10295private:
10296 llvm::FunctionCallee RTLFn;
10297 llvm::Value *Args[CleanupArgs];
10298
10299public:
10300 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
10301 ArrayRef<llvm::Value *> CallArgs)
10302 : RTLFn(RTLFn) {
10303 assert(CallArgs.size() == CleanupArgs &&
10304 "Size of arguments does not match.");
10305 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10306 }
10307 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10308 if (!CGF.HaveInsertPoint())
10309 return;
10310 CGF.EmitRuntimeCall(RTLFn, Args);
10311 }
10312};
10313} // namespace
10314
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000010315Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF,
10316 const VarDecl *VD) {
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010317 if (!VD)
10318 return Address::invalid();
Alexey Bataev4f680db2019-03-19 16:41:16 +000010319 const VarDecl *CVD = VD->getCanonicalDecl();
10320 if (!CVD->hasAttr<OMPAllocateDeclAttr>())
10321 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010322 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
10323 // Use the default allocation.
Alexey Bataev0fd3c682019-04-02 19:44:46 +000010324 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
10325 !AA->getAllocator())
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010326 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010327 llvm::Value *Size;
10328 CharUnits Align = CGM.getContext().getDeclAlign(CVD);
10329 if (CVD->getType()->isVariablyModifiedType()) {
10330 Size = CGF.getTypeSize(CVD->getType());
Alexey Bataev9c397812019-04-03 17:57:06 +000010331 // Align the size: ((size + align - 1) / align) * align
10332 Size = CGF.Builder.CreateNUWAdd(
10333 Size, CGM.getSize(Align - CharUnits::fromQuantity(1)));
10334 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align));
10335 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align));
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010336 } else {
10337 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType());
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010338 Size = CGM.getSize(Sz.alignTo(Align));
Alexey Bataev4f680db2019-03-19 16:41:16 +000010339 }
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010340 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc());
10341 assert(AA->getAllocator() &&
10342 "Expected allocator expression for non-default allocator.");
10343 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator());
Alexey Bataev6cf7b712019-04-08 19:06:42 +000010344 // According to the standard, the original allocator type is a enum (integer).
10345 // Convert to pointer type, if required.
10346 if (Allocator->getType()->isIntegerTy())
10347 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy);
10348 else if (Allocator->getType()->isPointerTy())
10349 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator,
10350 CGM.VoidPtrTy);
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010351 llvm::Value *Args[] = {ThreadID, Size, Allocator};
10352
10353 llvm::Value *Addr =
10354 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args,
10355 CVD->getName() + ".void.addr");
10356 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr,
10357 Allocator};
10358 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free);
10359
10360 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
10361 llvm::makeArrayRef(FiniArgs));
10362 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
10363 Addr,
10364 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())),
10365 CVD->getName() + ".addr");
10366 return Address(Addr, Align);
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000010367}
10368
James Y Knight9871db02019-02-05 16:42:33 +000010369llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010370 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
10371 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
10372 llvm_unreachable("Not supported in SIMD-only mode");
10373}
10374
James Y Knight9871db02019-02-05 16:42:33 +000010375llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010376 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
10377 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
10378 llvm_unreachable("Not supported in SIMD-only mode");
10379}
10380
James Y Knight9871db02019-02-05 16:42:33 +000010381llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010382 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
10383 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
10384 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
10385 bool Tied, unsigned &NumberOfParts) {
10386 llvm_unreachable("Not supported in SIMD-only mode");
10387}
10388
10389void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF,
10390 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000010391 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010392 ArrayRef<llvm::Value *> CapturedVars,
10393 const Expr *IfCond) {
10394 llvm_unreachable("Not supported in SIMD-only mode");
10395}
10396
10397void CGOpenMPSIMDRuntime::emitCriticalRegion(
10398 CodeGenFunction &CGF, StringRef CriticalName,
10399 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
10400 const Expr *Hint) {
10401 llvm_unreachable("Not supported in SIMD-only mode");
10402}
10403
10404void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF,
10405 const RegionCodeGenTy &MasterOpGen,
10406 SourceLocation Loc) {
10407 llvm_unreachable("Not supported in SIMD-only mode");
10408}
10409
10410void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
10411 SourceLocation Loc) {
10412 llvm_unreachable("Not supported in SIMD-only mode");
10413}
10414
10415void CGOpenMPSIMDRuntime::emitTaskgroupRegion(
10416 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen,
10417 SourceLocation Loc) {
10418 llvm_unreachable("Not supported in SIMD-only mode");
10419}
10420
10421void CGOpenMPSIMDRuntime::emitSingleRegion(
10422 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen,
10423 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars,
10424 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs,
10425 ArrayRef<const Expr *> AssignmentOps) {
10426 llvm_unreachable("Not supported in SIMD-only mode");
10427}
10428
10429void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF,
10430 const RegionCodeGenTy &OrderedOpGen,
10431 SourceLocation Loc,
10432 bool IsThreads) {
10433 llvm_unreachable("Not supported in SIMD-only mode");
10434}
10435
10436void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF,
10437 SourceLocation Loc,
10438 OpenMPDirectiveKind Kind,
10439 bool EmitChecks,
10440 bool ForceSimpleCall) {
10441 llvm_unreachable("Not supported in SIMD-only mode");
10442}
10443
10444void CGOpenMPSIMDRuntime::emitForDispatchInit(
10445 CodeGenFunction &CGF, SourceLocation Loc,
10446 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
10447 bool Ordered, const DispatchRTInput &DispatchValues) {
10448 llvm_unreachable("Not supported in SIMD-only mode");
10449}
10450
10451void CGOpenMPSIMDRuntime::emitForStaticInit(
10452 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind,
10453 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) {
10454 llvm_unreachable("Not supported in SIMD-only mode");
10455}
10456
10457void CGOpenMPSIMDRuntime::emitDistributeStaticInit(
10458 CodeGenFunction &CGF, SourceLocation Loc,
10459 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) {
10460 llvm_unreachable("Not supported in SIMD-only mode");
10461}
10462
10463void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
10464 SourceLocation Loc,
10465 unsigned IVSize,
10466 bool IVSigned) {
10467 llvm_unreachable("Not supported in SIMD-only mode");
10468}
10469
10470void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF,
10471 SourceLocation Loc,
10472 OpenMPDirectiveKind DKind) {
10473 llvm_unreachable("Not supported in SIMD-only mode");
10474}
10475
10476llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF,
10477 SourceLocation Loc,
10478 unsigned IVSize, bool IVSigned,
10479 Address IL, Address LB,
10480 Address UB, Address ST) {
10481 llvm_unreachable("Not supported in SIMD-only mode");
10482}
10483
10484void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
10485 llvm::Value *NumThreads,
10486 SourceLocation Loc) {
10487 llvm_unreachable("Not supported in SIMD-only mode");
10488}
10489
10490void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF,
10491 OpenMPProcBindClauseKind ProcBind,
10492 SourceLocation Loc) {
10493 llvm_unreachable("Not supported in SIMD-only mode");
10494}
10495
10496Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
10497 const VarDecl *VD,
10498 Address VDAddr,
10499 SourceLocation Loc) {
10500 llvm_unreachable("Not supported in SIMD-only mode");
10501}
10502
10503llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition(
10504 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit,
10505 CodeGenFunction *CGF) {
10506 llvm_unreachable("Not supported in SIMD-only mode");
10507}
10508
10509Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate(
10510 CodeGenFunction &CGF, QualType VarType, StringRef Name) {
10511 llvm_unreachable("Not supported in SIMD-only mode");
10512}
10513
10514void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF,
10515 ArrayRef<const Expr *> Vars,
10516 SourceLocation Loc) {
10517 llvm_unreachable("Not supported in SIMD-only mode");
10518}
10519
10520void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
10521 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000010522 llvm::Function *TaskFunction,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010523 QualType SharedsTy, Address Shareds,
10524 const Expr *IfCond,
10525 const OMPTaskDataTy &Data) {
10526 llvm_unreachable("Not supported in SIMD-only mode");
10527}
10528
10529void CGOpenMPSIMDRuntime::emitTaskLoopCall(
10530 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000010531 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010532 const Expr *IfCond, const OMPTaskDataTy &Data) {
10533 llvm_unreachable("Not supported in SIMD-only mode");
10534}
10535
10536void CGOpenMPSIMDRuntime::emitReduction(
10537 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates,
10538 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
10539 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) {
10540 assert(Options.SimpleReduction && "Only simple reduction is expected.");
10541 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
10542 ReductionOps, Options);
10543}
10544
10545llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit(
10546 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
10547 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
10548 llvm_unreachable("Not supported in SIMD-only mode");
10549}
10550
10551void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
10552 SourceLocation Loc,
10553 ReductionCodeGen &RCG,
10554 unsigned N) {
10555 llvm_unreachable("Not supported in SIMD-only mode");
10556}
10557
10558Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
10559 SourceLocation Loc,
10560 llvm::Value *ReductionsPtr,
10561 LValue SharedLVal) {
10562 llvm_unreachable("Not supported in SIMD-only mode");
10563}
10564
10565void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
10566 SourceLocation Loc) {
10567 llvm_unreachable("Not supported in SIMD-only mode");
10568}
10569
10570void CGOpenMPSIMDRuntime::emitCancellationPointCall(
10571 CodeGenFunction &CGF, SourceLocation Loc,
10572 OpenMPDirectiveKind CancelRegion) {
10573 llvm_unreachable("Not supported in SIMD-only mode");
10574}
10575
10576void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF,
10577 SourceLocation Loc, const Expr *IfCond,
10578 OpenMPDirectiveKind CancelRegion) {
10579 llvm_unreachable("Not supported in SIMD-only mode");
10580}
10581
10582void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction(
10583 const OMPExecutableDirective &D, StringRef ParentName,
10584 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
10585 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
10586 llvm_unreachable("Not supported in SIMD-only mode");
10587}
10588
10589void CGOpenMPSIMDRuntime::emitTargetCall(CodeGenFunction &CGF,
10590 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000010591 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010592 llvm::Value *OutlinedFnID,
James Y Knight9871db02019-02-05 16:42:33 +000010593 const Expr *IfCond,
10594 const Expr *Device) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010595 llvm_unreachable("Not supported in SIMD-only mode");
10596}
10597
10598bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) {
10599 llvm_unreachable("Not supported in SIMD-only mode");
10600}
10601
10602bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
10603 llvm_unreachable("Not supported in SIMD-only mode");
10604}
10605
10606bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) {
10607 return false;
10608}
10609
10610llvm::Function *CGOpenMPSIMDRuntime::emitRegistrationFunction() {
10611 return nullptr;
10612}
10613
10614void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF,
10615 const OMPExecutableDirective &D,
10616 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000010617 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010618 ArrayRef<llvm::Value *> CapturedVars) {
10619 llvm_unreachable("Not supported in SIMD-only mode");
10620}
10621
10622void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
10623 const Expr *NumTeams,
10624 const Expr *ThreadLimit,
10625 SourceLocation Loc) {
10626 llvm_unreachable("Not supported in SIMD-only mode");
10627}
10628
10629void CGOpenMPSIMDRuntime::emitTargetDataCalls(
10630 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10631 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
10632 llvm_unreachable("Not supported in SIMD-only mode");
10633}
10634
10635void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
10636 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10637 const Expr *Device) {
10638 llvm_unreachable("Not supported in SIMD-only mode");
10639}
10640
10641void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000010642 const OMPLoopDirective &D,
10643 ArrayRef<Expr *> NumIterations) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010644 llvm_unreachable("Not supported in SIMD-only mode");
10645}
10646
10647void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
10648 const OMPDependClause *C) {
10649 llvm_unreachable("Not supported in SIMD-only mode");
10650}
10651
10652const VarDecl *
10653CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD,
10654 const VarDecl *NativeParam) const {
10655 llvm_unreachable("Not supported in SIMD-only mode");
10656}
10657
10658Address
10659CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF,
10660 const VarDecl *NativeParam,
10661 const VarDecl *TargetParam) const {
10662 llvm_unreachable("Not supported in SIMD-only mode");
10663}