blob: 1e1251efea571c2fadb86b8a6a7828108fc06a8d [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
Mandeep Singh Grangb14fb6a22017-11-28 20:41:13 +00004701static bool stable_sort_comparator(const PrivateDataTy P1,
4702 const PrivateDataTy P2) {
4703 return P1.first > P2.first;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004704}
4705
Alexey Bataevf93095a2016-05-05 08:46:22 +00004706/// Emit initialization for private variables in task-based directives.
Alexey Bataev8a831592016-05-10 10:36:51 +00004707static void emitPrivatesInit(CodeGenFunction &CGF,
Alexey Bataevf93095a2016-05-05 08:46:22 +00004708 const OMPExecutableDirective &D,
4709 Address KmpTaskSharedsPtr, LValue TDBase,
4710 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4711 QualType SharedsTy, QualType SharedsPtrTy,
4712 const OMPTaskDataTy &Data,
4713 ArrayRef<PrivateDataTy> Privates, bool ForDup) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004714 ASTContext &C = CGF.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004715 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
4716 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004717 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind())
4718 ? OMPD_taskloop
4719 : OMPD_task;
4720 const CapturedStmt &CS = *D.getCapturedStmt(Kind);
4721 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004722 LValue SrcBase;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004723 bool IsTargetTask =
4724 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) ||
4725 isOpenMPTargetExecutionDirective(D.getDirectiveKind());
4726 // For target-based directives skip 3 firstprivate arrays BasePointersArray,
4727 // PointersArray and SizesArray. The original variables for these arrays are
4728 // not captured and we get their addresses explicitly.
4729 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) ||
Alexey Bataev8451efa2018-01-15 19:06:12 +00004730 (IsTargetTask && KmpTaskSharedsPtr.isValid())) {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004731 SrcBase = CGF.MakeAddrLValue(
4732 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
4733 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)),
4734 SharedsTy);
4735 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004736 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004737 for (const PrivateDataTy &Pair : Privates) {
4738 const VarDecl *VD = Pair.second.PrivateCopy;
4739 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004740 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) &&
4741 !CGF.isTrivialInitializer(Init)))) {
Alexey Bataev8a831592016-05-10 10:36:51 +00004742 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004743 if (const VarDecl *Elem = Pair.second.PrivateElemInit) {
4744 const VarDecl *OriginalVD = Pair.second.Original;
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004745 // Check if the variable is the target-based BasePointersArray,
4746 // PointersArray or SizesArray.
4747 LValue SharedRefLValue;
Alexey Bataevab41ea62019-03-13 20:46:28 +00004748 QualType Type = PrivateLValue.getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004749 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004750 if (IsTargetTask && !SharedField) {
4751 assert(isa<ImplicitParamDecl>(OriginalVD) &&
4752 isa<CapturedDecl>(OriginalVD->getDeclContext()) &&
4753 cast<CapturedDecl>(OriginalVD->getDeclContext())
4754 ->getNumParams() == 0 &&
4755 isa<TranslationUnitDecl>(
4756 cast<CapturedDecl>(OriginalVD->getDeclContext())
4757 ->getDeclContext()) &&
4758 "Expected artificial target data variable.");
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004759 SharedRefLValue =
4760 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type);
4761 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004762 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField);
4763 SharedRefLValue = CGF.MakeAddrLValue(
4764 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)),
4765 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl),
4766 SharedRefLValue.getTBAAInfo());
4767 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004768 if (Type->isArrayType()) {
4769 // Initialize firstprivate array.
4770 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) {
4771 // Perform simple memcpy.
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00004772 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004773 } else {
4774 // Initialize firstprivate array using element-by-element
Simon Pilgrim2c518802017-03-30 14:13:19 +00004775 // initialization.
Alexey Bataevf93095a2016-05-05 08:46:22 +00004776 CGF.EmitOMPAggregateAssign(
4777 PrivateLValue.getAddress(), SharedRefLValue.getAddress(), Type,
4778 [&CGF, Elem, Init, &CapturesInfo](Address DestElement,
4779 Address SrcElement) {
4780 // Clean up any temporaries needed by the initialization.
4781 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4782 InitScope.addPrivate(
4783 Elem, [SrcElement]() -> Address { return SrcElement; });
4784 (void)InitScope.Privatize();
4785 // Emit initialization for single element.
4786 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(
4787 CGF, &CapturesInfo);
4788 CGF.EmitAnyExprToMem(Init, DestElement,
4789 Init->getType().getQualifiers(),
4790 /*IsInitializer=*/false);
4791 });
4792 }
4793 } else {
4794 CodeGenFunction::OMPPrivateScope InitScope(CGF);
4795 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address {
4796 return SharedRefLValue.getAddress();
4797 });
4798 (void)InitScope.Privatize();
4799 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo);
4800 CGF.EmitExprAsInit(Init, VD, PrivateLValue,
4801 /*capturedByInit=*/false);
4802 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004803 } else {
Alexey Bataevf93095a2016-05-05 08:46:22 +00004804 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004805 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004806 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004807 ++FI;
4808 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004809}
4810
4811/// Check if duplication function is required for taskloops.
4812static bool checkInitIsRequired(CodeGenFunction &CGF,
4813 ArrayRef<PrivateDataTy> Privates) {
4814 bool InitRequired = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004815 for (const PrivateDataTy &Pair : Privates) {
4816 const VarDecl *VD = Pair.second.PrivateCopy;
4817 const Expr *Init = VD->getAnyInitializer();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004818 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) &&
4819 !CGF.isTrivialInitializer(Init));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004820 if (InitRequired)
4821 break;
Alexey Bataevf93095a2016-05-05 08:46:22 +00004822 }
4823 return InitRequired;
4824}
4825
4826
4827/// Emit task_dup function (for initialization of
4828/// private/firstprivate/lastprivate vars and last_iter flag)
4829/// \code
4830/// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int
4831/// lastpriv) {
4832/// // setup lastprivate flag
4833/// task_dst->last = lastpriv;
4834/// // could be constructor calls here...
4835/// }
4836/// \endcode
4837static llvm::Value *
4838emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc,
4839 const OMPExecutableDirective &D,
4840 QualType KmpTaskTWithPrivatesPtrQTy,
4841 const RecordDecl *KmpTaskTWithPrivatesQTyRD,
4842 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy,
4843 QualType SharedsPtrTy, const OMPTaskDataTy &Data,
4844 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004845 ASTContext &C = CGM.getContext();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004846 FunctionArgList Args;
Alexey Bataev56223232017-06-09 13:40:18 +00004847 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4848 KmpTaskTWithPrivatesPtrQTy,
4849 ImplicitParamDecl::Other);
4850 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
4851 KmpTaskTWithPrivatesPtrQTy,
4852 ImplicitParamDecl::Other);
4853 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy,
4854 ImplicitParamDecl::Other);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004855 Args.push_back(&DstArg);
4856 Args.push_back(&SrcArg);
4857 Args.push_back(&LastprivArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004858 const auto &TaskDupFnInfo =
Alexey Bataevf93095a2016-05-05 08:46:22 +00004859 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004860 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00004861 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""});
4862 auto *TaskDup = llvm::Function::Create(
4863 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00004864 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004865 TaskDup->setDoesNotRecurse();
Alexey Bataevf93095a2016-05-05 08:46:22 +00004866 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00004867 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc,
4868 Loc);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004869
4870 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4871 CGF.GetAddrOfLocalVar(&DstArg),
4872 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4873 // task_dst->liter = lastpriv;
4874 if (WithLastIter) {
4875 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter);
4876 LValue Base = CGF.EmitLValueForField(
4877 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4878 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI);
4879 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar(
4880 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc);
4881 CGF.EmitStoreOfScalar(Lastpriv, LILVal);
4882 }
4883
4884 // Emit initial values for private copies (if any).
4885 assert(!Privates.empty());
4886 Address KmpTaskSharedsPtr = Address::invalid();
4887 if (!Data.FirstprivateVars.empty()) {
4888 LValue TDBase = CGF.EmitLoadOfPointerLValue(
4889 CGF.GetAddrOfLocalVar(&SrcArg),
4890 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>());
4891 LValue Base = CGF.EmitLValueForField(
4892 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin());
4893 KmpTaskSharedsPtr = Address(
4894 CGF.EmitLoadOfScalar(CGF.EmitLValueForField(
4895 Base, *std::next(KmpTaskTQTyRD->field_begin(),
4896 KmpTaskTShareds)),
4897 Loc),
4898 CGF.getNaturalTypeAlignment(SharedsTy));
4899 }
Alexey Bataev8a831592016-05-10 10:36:51 +00004900 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD,
4901 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true);
Alexey Bataevf93095a2016-05-05 08:46:22 +00004902 CGF.FinishFunction();
4903 return TaskDup;
4904}
4905
Alexey Bataev8a831592016-05-10 10:36:51 +00004906/// Checks if destructor function is required to be generated.
4907/// \return true if cleanups are required, false otherwise.
4908static bool
4909checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) {
4910 bool NeedsCleanup = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004911 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1);
4912 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl());
4913 for (const FieldDecl *FD : PrivateRD->fields()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00004914 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType();
4915 if (NeedsCleanup)
4916 break;
4917 }
4918 return NeedsCleanup;
4919}
4920
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004921CGOpenMPRuntime::TaskResultTy
4922CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc,
4923 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00004924 llvm::Function *TaskFunction, QualType SharedsTy,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004925 Address Shareds, const OMPTaskDataTy &Data) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004926 ASTContext &C = CGM.getContext();
Alexey Bataev7292c292016-04-25 12:22:29 +00004927 llvm::SmallVector<PrivateDataTy, 4> Privates;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004928 // Aggregate privates and sort them by the alignment.
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004929 auto I = Data.PrivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004930 for (const Expr *E : Data.PrivateVars) {
4931 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00004932 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00004933 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00004934 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00004935 /*PrivateElemInit=*/nullptr));
Alexey Bataev36c1eb92015-04-30 06:51:57 +00004936 ++I;
4937 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00004938 I = Data.FirstprivateCopies.begin();
4939 auto IElemInitRef = Data.FirstprivateInits.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004940 for (const Expr *E : Data.FirstprivateVars) {
4941 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00004942 Privates.emplace_back(
Alexey Bataevc71a4092015-09-11 10:29:41 +00004943 C.getDeclAlign(VD),
Alexey Bataev9e034042015-05-05 04:05:12 +00004944 PrivateHelpersTy(
4945 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00004946 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl())));
Richard Trieucc3949d2016-02-18 22:34:54 +00004947 ++I;
4948 ++IElemInitRef;
Alexey Bataev9e034042015-05-05 04:05:12 +00004949 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00004950 I = Data.LastprivateCopies.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004951 for (const Expr *E : Data.LastprivateVars) {
4952 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev43a919f2018-04-13 17:48:43 +00004953 Privates.emplace_back(
Alexey Bataevf93095a2016-05-05 08:46:22 +00004954 C.getDeclAlign(VD),
4955 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()),
Alexey Bataev43a919f2018-04-13 17:48:43 +00004956 /*PrivateElemInit=*/nullptr));
Alexey Bataevf93095a2016-05-05 08:46:22 +00004957 ++I;
4958 }
Mandeep Singh Grangb14fb6a22017-11-28 20:41:13 +00004959 std::stable_sort(Privates.begin(), Privates.end(), stable_sort_comparator);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004960 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004961 // Build type kmp_routine_entry_t (if not built yet).
4962 emitKmpRoutineEntryT(KmpInt32Ty);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004963 // Build type kmp_task_t (if not built yet).
Alexey Bataeve213f3e2017-10-11 15:29:40 +00004964 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) {
4965 if (SavedKmpTaskloopTQTy.isNull()) {
4966 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl(
4967 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
4968 }
4969 KmpTaskTQTy = SavedKmpTaskloopTQTy;
Alexey Bataev3a03a7f2017-10-11 15:56:38 +00004970 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00004971 assert((D.getDirectiveKind() == OMPD_task ||
4972 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) ||
4973 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) &&
4974 "Expected taskloop, task or target directive");
Alexey Bataeve213f3e2017-10-11 15:29:40 +00004975 if (SavedKmpTaskTQTy.isNull()) {
4976 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl(
4977 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy));
4978 }
4979 KmpTaskTQTy = SavedKmpTaskTQTy;
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004980 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004981 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl());
Alexey Bataev62b63b12015-03-10 07:28:44 +00004982 // Build particular struct kmp_task_t for the given task.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004983 const RecordDecl *KmpTaskTWithPrivatesQTyRD =
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004984 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004985 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00004986 QualType KmpTaskTWithPrivatesPtrQTy =
4987 C.getPointerType(KmpTaskTWithPrivatesQTy);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004988 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy);
4989 llvm::Type *KmpTaskTWithPrivatesPtrTy =
4990 KmpTaskTWithPrivatesTy->getPointerTo();
4991 llvm::Value *KmpTaskTWithPrivatesTySize =
4992 CGF.getTypeSize(KmpTaskTWithPrivatesQTy);
Alexey Bataev62b63b12015-03-10 07:28:44 +00004993 QualType SharedsPtrTy = C.getPointerType(SharedsTy);
4994
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004995 // Emit initial values for private copies (if any).
4996 llvm::Value *TaskPrivatesMap = nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00004997 llvm::Type *TaskPrivatesMapTy =
James Y Knight9871db02019-02-05 16:42:33 +00004998 std::next(TaskFunction->arg_begin(), 3)->getType();
Alexey Bataev3ae88e22015-05-22 08:56:35 +00004999 if (!Privates.empty()) {
5000 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataevf93095a2016-05-05 08:46:22 +00005001 TaskPrivatesMap = emitTaskPrivateMappingFunction(
5002 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars,
5003 FI->getType(), Privates);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00005004 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5005 TaskPrivatesMap, TaskPrivatesMapTy);
5006 } else {
5007 TaskPrivatesMap = llvm::ConstantPointerNull::get(
5008 cast<llvm::PointerType>(TaskPrivatesMapTy));
5009 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005010 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid,
5011 // kmp_task_t *tt);
James Y Knight9871db02019-02-05 16:42:33 +00005012 llvm::Function *TaskEntry = emitProxyTaskFunction(
Alexey Bataev7292c292016-04-25 12:22:29 +00005013 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5014 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction,
5015 TaskPrivatesMap);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005016
5017 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid,
5018 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds,
5019 // kmp_routine_entry_t *task_entry);
5020 // Task flags. Format is taken from
James Y Knight5d71fc52019-01-29 16:37:27 +00005021 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h,
Alexey Bataev62b63b12015-03-10 07:28:44 +00005022 // description of kmp_tasking_flags struct.
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005023 enum {
5024 TiedFlag = 0x1,
5025 FinalFlag = 0x2,
5026 DestructorsFlag = 0x8,
5027 PriorityFlag = 0x20
5028 };
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005029 unsigned Flags = Data.Tied ? TiedFlag : 0;
Alexey Bataev8a831592016-05-10 10:36:51 +00005030 bool NeedsCleanup = false;
5031 if (!Privates.empty()) {
5032 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD);
5033 if (NeedsCleanup)
5034 Flags = Flags | DestructorsFlag;
5035 }
Alexey Bataev1e1e2862016-05-10 12:21:02 +00005036 if (Data.Priority.getInt())
5037 Flags = Flags | PriorityFlag;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005038 llvm::Value *TaskFlags =
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005039 Data.Final.getPointer()
5040 ? CGF.Builder.CreateSelect(Data.Final.getPointer(),
Alexey Bataev62b63b12015-03-10 07:28:44 +00005041 CGF.Builder.getInt32(FinalFlag),
5042 CGF.Builder.getInt32(/*C=*/0))
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005043 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0);
Alexey Bataev62b63b12015-03-10 07:28:44 +00005044 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005045 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005046 llvm::Value *AllocArgs[] = {emitUpdateLocation(CGF, Loc),
5047 getThreadID(CGF, Loc), TaskFlags,
5048 KmpTaskTWithPrivatesTySize, SharedsSize,
5049 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5050 TaskEntry, KmpRoutineEntryPtrTy)};
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005051 llvm::Value *NewTask = CGF.EmitRuntimeCall(
Alexey Bataev62b63b12015-03-10 07:28:44 +00005052 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005053 llvm::Value *NewTaskNewTaskTTy =
5054 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5055 NewTask, KmpTaskTWithPrivatesPtrTy);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005056 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy,
5057 KmpTaskTWithPrivatesQTy);
5058 LValue TDBase =
5059 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin());
Alexey Bataev62b63b12015-03-10 07:28:44 +00005060 // Fill the data in the resulting kmp_task_t record.
5061 // Copy shareds if there are any.
John McCall7f416cc2015-09-08 08:05:57 +00005062 Address KmpTaskSharedsPtr = Address::invalid();
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005063 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +00005064 KmpTaskSharedsPtr =
5065 Address(CGF.EmitLoadOfScalar(
5066 CGF.EmitLValueForField(
5067 TDBase, *std::next(KmpTaskTQTyRD->field_begin(),
5068 KmpTaskTShareds)),
5069 Loc),
5070 CGF.getNaturalTypeAlignment(SharedsTy));
Ivan A. Kosarev1860b522018-01-25 14:21:55 +00005071 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy);
5072 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy);
Richard Smithe78fac52018-04-05 20:52:58 +00005073 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap);
Alexey Bataev8fc69dc2015-05-18 07:54:53 +00005074 }
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005075 // Emit initial values for private copies (if any).
Alexey Bataevf93095a2016-05-05 08:46:22 +00005076 TaskResultTy Result;
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005077 if (!Privates.empty()) {
Alexey Bataev8a831592016-05-10 10:36:51 +00005078 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD,
5079 SharedsTy, SharedsPtrTy, Data, Privates,
5080 /*ForDup=*/false);
Alexey Bataevf93095a2016-05-05 08:46:22 +00005081 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
5082 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) {
5083 Result.TaskDupFn = emitTaskDupFunction(
5084 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD,
5085 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates,
5086 /*WithLastIter=*/!Data.LastprivateVars.empty());
Alexey Bataev36c1eb92015-04-30 06:51:57 +00005087 }
5088 }
Alexey Bataevad537bb2016-05-30 09:06:50 +00005089 // Fields of union "kmp_cmplrdata_t" for destructors and priority.
5090 enum { Priority = 0, Destructors = 1 };
Alexey Bataev62b63b12015-03-10 07:28:44 +00005091 // Provide pointer to function with destructors for privates.
Alexey Bataevad537bb2016-05-30 09:06:50 +00005092 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005093 const RecordDecl *KmpCmplrdataUD =
5094 (*FI)->getType()->getAsUnionType()->getDecl();
Alexey Bataevad537bb2016-05-30 09:06:50 +00005095 if (NeedsCleanup) {
5096 llvm::Value *DestructorFn = emitDestructorsFunction(
5097 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy,
5098 KmpTaskTWithPrivatesQTy);
5099 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI);
5100 LValue DestructorsLV = CGF.EmitLValueForField(
5101 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors));
5102 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5103 DestructorFn, KmpRoutineEntryPtrTy),
5104 DestructorsLV);
5105 }
5106 // Set priority.
5107 if (Data.Priority.getInt()) {
5108 LValue Data2LV = CGF.EmitLValueForField(
5109 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2));
5110 LValue PriorityLV = CGF.EmitLValueForField(
5111 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority));
5112 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV);
5113 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005114 Result.NewTask = NewTask;
5115 Result.TaskEntry = TaskEntry;
5116 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy;
5117 Result.TDBase = TDBase;
5118 Result.KmpTaskTQTyRD = KmpTaskTQTyRD;
5119 return Result;
Alexey Bataev7292c292016-04-25 12:22:29 +00005120}
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005121
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005122void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
5123 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005124 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005125 QualType SharedsTy, Address Shareds,
5126 const Expr *IfCond,
5127 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005128 if (!CGF.HaveInsertPoint())
5129 return;
5130
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005131 TaskResultTy Result =
5132 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
5133 llvm::Value *NewTask = Result.NewTask;
James Y Knight9871db02019-02-05 16:42:33 +00005134 llvm::Function *TaskEntry = Result.TaskEntry;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005135 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy;
5136 LValue TDBase = Result.TDBase;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005137 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD;
5138 ASTContext &C = CGM.getContext();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005139 // Process list of dependences.
John McCall7f416cc2015-09-08 08:05:57 +00005140 Address DependenciesArray = Address::invalid();
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005141 unsigned NumDependencies = Data.Dependences.size();
John McCall7f416cc2015-09-08 08:05:57 +00005142 if (NumDependencies) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005143 // Dependence kind for RTL.
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005144 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 };
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005145 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags };
5146 RecordDecl *KmpDependInfoRD;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005147 QualType FlagsTy =
5148 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005149 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy);
5150 if (KmpDependInfoTy.isNull()) {
5151 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info");
5152 KmpDependInfoRD->startDefinition();
5153 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType());
5154 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType());
5155 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy);
5156 KmpDependInfoRD->completeDefinition();
5157 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005158 } else {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005159 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005160 }
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005161 // Define type kmp_depend_info[<Dependences.size()>];
5162 QualType KmpDependInfoArrayTy = C.getConstantArrayType(
John McCall7f416cc2015-09-08 08:05:57 +00005163 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005164 ArrayType::Normal, /*IndexTypeQuals=*/0);
5165 // kmp_depend_info[<Dependences.size()>] deps;
Alexey Bataev48591dd2016-04-20 04:01:36 +00005166 DependenciesArray =
5167 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005168 for (unsigned I = 0; I < NumDependencies; ++I) {
5169 const Expr *E = Data.Dependences[I].second;
5170 LValue Addr = CGF.EmitLValue(E);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005171 llvm::Value *Size;
5172 QualType Ty = E->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005173 if (const auto *ASE =
5174 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) {
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005175 LValue UpAddrLVal =
5176 CGF.EmitOMPArraySectionExpr(ASE, /*LowerBound=*/false);
5177 llvm::Value *UpAddr =
John McCall7f416cc2015-09-08 08:05:57 +00005178 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005179 llvm::Value *LowIntPtr =
John McCall7f416cc2015-09-08 08:05:57 +00005180 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy);
Alexey Bataevd6fdc8b2015-08-31 07:32:19 +00005181 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy);
5182 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005183 } else {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005184 Size = CGF.getTypeSize(Ty);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005185 }
5186 LValue Base = CGF.MakeAddrLValue(
James Y Knight751fe282019-02-09 22:22:28 +00005187 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005188 KmpDependInfoTy);
5189 // deps[i].base_addr = &<Dependences[i].second>;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005190 LValue BaseAddrLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005191 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr));
John McCall7f416cc2015-09-08 08:05:57 +00005192 CGF.EmitStoreOfScalar(
5193 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy),
5194 BaseAddrLVal);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005195 // deps[i].len = sizeof(<Dependences[i].second>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005196 LValue LenLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005197 Base, *std::next(KmpDependInfoRD->field_begin(), Len));
5198 CGF.EmitStoreOfScalar(Size, LenLVal);
5199 // deps[i].flags = <Dependences[i].first>;
5200 RTLDependenceKindTy DepKind;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005201 switch (Data.Dependences[I].first) {
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005202 case OMPC_DEPEND_in:
5203 DepKind = DepIn;
5204 break;
Alexey Bataev92e82f92015-11-23 13:33:42 +00005205 // Out and InOut dependencies must use the same code.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005206 case OMPC_DEPEND_out:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005207 case OMPC_DEPEND_inout:
5208 DepKind = DepInOut;
5209 break;
Sergi Mateo Bellido31df1ad2019-02-04 07:33:19 +00005210 case OMPC_DEPEND_mutexinoutset:
5211 DepKind = DepMutexInOutSet;
5212 break;
Alexey Bataeveb482352015-12-18 05:05:56 +00005213 case OMPC_DEPEND_source:
Alexey Bataeva636c7f2015-12-23 10:27:45 +00005214 case OMPC_DEPEND_sink:
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005215 case OMPC_DEPEND_unknown:
5216 llvm_unreachable("Unknown task dependence type");
5217 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005218 LValue FlagsLVal = CGF.EmitLValueForField(
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005219 Base, *std::next(KmpDependInfoRD->field_begin(), Flags));
5220 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind),
5221 FlagsLVal);
5222 }
John McCall7f416cc2015-09-08 08:05:57 +00005223 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knightf5f1b0e2019-02-08 15:34:12 +00005224 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005225 }
5226
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005227 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev62b63b12015-03-10 07:28:44 +00005228 // libcall.
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005229 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid,
5230 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list,
5231 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence
5232 // list is not empty
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005233 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5234 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
John McCall7f416cc2015-09-08 08:05:57 +00005235 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask };
5236 llvm::Value *DepTaskArgs[7];
5237 if (NumDependencies) {
5238 DepTaskArgs[0] = UpLoc;
5239 DepTaskArgs[1] = ThreadID;
5240 DepTaskArgs[2] = NewTask;
5241 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies);
5242 DepTaskArgs[4] = DependenciesArray.getPointer();
5243 DepTaskArgs[5] = CGF.Builder.getInt32(0);
5244 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5245 }
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005246 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies,
5247 &TaskArgs,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005248 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005249 if (!Data.Tied) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005250 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005251 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI);
Alexey Bataev48591dd2016-04-20 04:01:36 +00005252 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal);
5253 }
John McCall7f416cc2015-09-08 08:05:57 +00005254 if (NumDependencies) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005255 CGF.EmitRuntimeCall(
Alexey Bataev48591dd2016-04-20 04:01:36 +00005256 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs);
John McCall7f416cc2015-09-08 08:05:57 +00005257 } else {
Alexey Bataev48591dd2016-04-20 04:01:36 +00005258 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task),
John McCall7f416cc2015-09-08 08:05:57 +00005259 TaskArgs);
5260 }
Alexey Bataev48591dd2016-04-20 04:01:36 +00005261 // Check if parent region is untied and build return for untied task;
5262 if (auto *Region =
5263 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
5264 Region->emitUntiedSwitch(CGF);
Alexey Bataev1d677132015-04-22 13:57:31 +00005265 };
John McCall7f416cc2015-09-08 08:05:57 +00005266
5267 llvm::Value *DepWaitTaskArgs[6];
5268 if (NumDependencies) {
5269 DepWaitTaskArgs[0] = UpLoc;
5270 DepWaitTaskArgs[1] = ThreadID;
5271 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies);
5272 DepWaitTaskArgs[3] = DependenciesArray.getPointer();
5273 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
5274 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
5275 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005276 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry,
Alexey Bataev3c595a62017-08-14 15:01:03 +00005277 NumDependencies, &DepWaitTaskArgs,
5278 Loc](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005279 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005280 CodeGenFunction::RunCleanupsScope LocalScope(CGF);
5281 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
5282 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
5283 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
5284 // is specified.
John McCall7f416cc2015-09-08 08:05:57 +00005285 if (NumDependencies)
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005286 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps),
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005287 DepWaitTaskArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005288 // Call proxy_task_entry(gtid, new_task);
Alexey Bataev3c595a62017-08-14 15:01:03 +00005289 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy,
5290 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005291 Action.Enter(CGF);
5292 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy};
Alexey Bataev3c595a62017-08-14 15:01:03 +00005293 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry,
Alexey Bataev2c7eee52017-08-04 19:10:54 +00005294 OutlinedFnArgs);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005295 };
5296
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005297 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid,
5298 // kmp_task_t *new_task);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005299 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid,
5300 // kmp_task_t *new_task);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005301 RegionCodeGenTy RCG(CodeGen);
5302 CommonActionTy Action(
5303 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs,
5304 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs);
5305 RCG.setAction(Action);
5306 RCG(CGF);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00005307 };
John McCall7f416cc2015-09-08 08:05:57 +00005308
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005309 if (IfCond) {
Alexey Bataev1d677132015-04-22 13:57:31 +00005310 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005311 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005312 RegionCodeGenTy ThenRCG(ThenCodeGen);
5313 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00005314 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00005315}
5316
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005317void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc,
5318 const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00005319 llvm::Function *TaskFunction,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005320 QualType SharedsTy, Address Shareds,
5321 const Expr *IfCond,
5322 const OMPTaskDataTy &Data) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005323 if (!CGF.HaveInsertPoint())
5324 return;
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005325 TaskResultTy Result =
5326 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data);
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005327 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc()
Alexey Bataev7292c292016-04-25 12:22:29 +00005328 // libcall.
5329 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int
5330 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int
5331 // sched, kmp_uint64 grainsize, void *task_dup);
5332 llvm::Value *ThreadID = getThreadID(CGF, Loc);
5333 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
5334 llvm::Value *IfVal;
5335 if (IfCond) {
5336 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy,
5337 /*isSigned=*/true);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005338 } else {
Alexey Bataev7292c292016-04-25 12:22:29 +00005339 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005340 }
Alexey Bataev7292c292016-04-25 12:22:29 +00005341
5342 LValue LBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005343 Result.TDBase,
5344 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005345 const auto *LBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005346 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl());
5347 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(),
5348 /*IsInitializer=*/true);
5349 LValue UBLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005350 Result.TDBase,
5351 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005352 const auto *UBVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005353 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl());
5354 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(),
5355 /*IsInitializer=*/true);
5356 LValue StLVal = CGF.EmitLValueForField(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005357 Result.TDBase,
5358 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005359 const auto *StVar =
Alexey Bataev7292c292016-04-25 12:22:29 +00005360 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl());
5361 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(),
5362 /*IsInitializer=*/true);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005363 // Store reductions address.
5364 LValue RedLVal = CGF.EmitLValueForField(
5365 Result.TDBase,
5366 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005367 if (Data.Reductions) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005368 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005369 } else {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005370 CGF.EmitNullInitialization(RedLVal.getAddress(),
5371 CGF.getContext().VoidPtrTy);
5372 }
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005373 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 };
Alexey Bataev7292c292016-04-25 12:22:29 +00005374 llvm::Value *TaskArgs[] = {
Alexey Bataev33446032017-07-12 18:09:32 +00005375 UpLoc,
5376 ThreadID,
5377 Result.NewTask,
5378 IfVal,
5379 LBLVal.getPointer(),
5380 UBLVal.getPointer(),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00005381 CGF.EmitLoadOfScalar(StLVal, Loc),
Alexey Bataevac6e4de2018-10-24 19:06:37 +00005382 llvm::ConstantInt::getSigned(
5383 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005384 llvm::ConstantInt::getSigned(
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005385 CGF.IntTy, Data.Schedule.getPointer()
5386 ? Data.Schedule.getInt() ? NumTasks : Grainsize
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005387 : NoSchedule),
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005388 Data.Schedule.getPointer()
5389 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty,
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005390 /*isSigned=*/false)
5391 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0),
Alexey Bataev33446032017-07-12 18:09:32 +00005392 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5393 Result.TaskDupFn, CGF.VoidPtrTy)
5394 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)};
Alexey Bataev7292c292016-04-25 12:22:29 +00005395 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs);
5396}
5397
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005398/// Emit reduction operation for each element of array (required for
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005399/// array sections) LHS op = RHS.
5400/// \param Type Type of array.
5401/// \param LHSVar Variable on the left side of the reduction operation
5402/// (references element of array in original variable).
5403/// \param RHSVar Variable on the right side of the reduction operation
5404/// (references element of array in original variable).
5405/// \param RedOpGen Generator of reduction operation with use of LHSVar and
5406/// RHSVar.
Benjamin Kramere003ca22015-10-28 13:54:16 +00005407static void EmitOMPAggregateReduction(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005408 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar,
5409 const VarDecl *RHSVar,
5410 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *,
5411 const Expr *, const Expr *)> &RedOpGen,
5412 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr,
5413 const Expr *UpExpr = nullptr) {
5414 // Perform element-by-element initialization.
5415 QualType ElementTy;
5416 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar);
5417 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar);
5418
5419 // Drill down to the base element type on both arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005420 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe();
5421 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005422
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005423 llvm::Value *RHSBegin = RHSAddr.getPointer();
5424 llvm::Value *LHSBegin = LHSAddr.getPointer();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005425 // Cast from pointer to array type to pointer to single element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005426 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005427 // The basic structure here is a while-do loop.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005428 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body");
5429 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done");
5430 llvm::Value *IsEmpty =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005431 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty");
5432 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
5433
5434 // Enter the loop body, making that address the current address.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005435 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005436 CGF.EmitBlock(BodyBB);
5437
5438 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy);
5439
5440 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI(
5441 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast");
5442 RHSElementPHI->addIncoming(RHSBegin, EntryBB);
5443 Address RHSElementCurrent =
5444 Address(RHSElementPHI,
5445 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5446
5447 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI(
5448 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast");
5449 LHSElementPHI->addIncoming(LHSBegin, EntryBB);
5450 Address LHSElementCurrent =
5451 Address(LHSElementPHI,
5452 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize));
5453
5454 // Emit copy.
5455 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005456 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; });
5457 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005458 Scope.Privatize();
5459 RedOpGen(CGF, XExpr, EExpr, UpExpr);
5460 Scope.ForceCleanup();
5461
5462 // Shift the address forward by one element.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005463 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005464 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005465 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32(
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005466 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
5467 // Check whether we've reached the end.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005468 llvm::Value *Done =
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005469 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done");
5470 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB);
5471 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock());
5472 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock());
5473
5474 // Done.
5475 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
5476}
5477
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005478/// Emit reduction combiner. If the combiner is a simple expression emit it as
5479/// is, otherwise consider it as combiner of UDR decl and emit it as a call of
5480/// UDR combiner function.
5481static void emitReductionCombiner(CodeGenFunction &CGF,
5482 const Expr *ReductionOp) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005483 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp))
5484 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee()))
5485 if (const auto *DRE =
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005486 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts()))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005487 if (const auto *DRD =
5488 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) {
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005489 std::pair<llvm::Function *, llvm::Function *> Reduction =
5490 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD);
5491 RValue Func = RValue::get(Reduction.first);
5492 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func);
5493 CGF.EmitIgnoredExpr(ReductionOp);
5494 return;
5495 }
5496 CGF.EmitIgnoredExpr(ReductionOp);
5497}
5498
James Y Knight9871db02019-02-05 16:42:33 +00005499llvm::Function *CGOpenMPRuntime::emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005500 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates,
5501 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
5502 ArrayRef<const Expr *> ReductionOps) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005503 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005504
5505 // void reduction_func(void *LHSArg, void *RHSArg);
5506 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005507 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5508 ImplicitParamDecl::Other);
5509 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5510 ImplicitParamDecl::Other);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005511 Args.push_back(&LHSArg);
5512 Args.push_back(&RHSArg);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005513 const auto &CGFI =
5514 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataev18fa2322018-05-02 14:20:50 +00005515 std::string Name = getName({"omp", "reduction", "reduction_func"});
5516 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI),
5517 llvm::GlobalValue::InternalLinkage, Name,
5518 &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00005519 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00005520 Fn->setDoesNotRecurse();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005521 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005522 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005523
5524 // Dst = (void*[n])(LHSArg);
5525 // Src = (void*[n])(RHSArg);
John McCall7f416cc2015-09-08 08:05:57 +00005526 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5527 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)),
5528 ArgsType), CGF.getPointerAlign());
5529 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
5530 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)),
5531 ArgsType), CGF.getPointerAlign());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005532
5533 // ...
5534 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]);
5535 // ...
5536 CodeGenFunction::OMPPrivateScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005537 auto IPriv = Privates.begin();
5538 unsigned Idx = 0;
5539 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005540 const auto *RHSVar =
5541 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl());
5542 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005543 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005544 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005545 const auto *LHSVar =
5546 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl());
5547 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005548 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar);
John McCall7f416cc2015-09-08 08:05:57 +00005549 });
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005550 QualType PrivTy = (*IPriv)->getType();
Alexey Bataev1189bd02016-01-26 12:20:39 +00005551 if (PrivTy->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005552 // Get array size and emit VLA type.
5553 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005554 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005555 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005556 const VariableArrayType *VLA =
5557 CGF.getContext().getAsVariableArrayType(PrivTy);
5558 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr());
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005559 CodeGenFunction::OpaqueValueMapping OpaqueMap(
Alexey Bataev1189bd02016-01-26 12:20:39 +00005560 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy)));
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005561 CGF.EmitVariablyModifiedType(PrivTy);
5562 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005563 }
5564 Scope.Privatize();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005565 IPriv = Privates.begin();
5566 auto ILHS = LHSExprs.begin();
5567 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005568 for (const Expr *E : ReductionOps) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005569 if ((*IPriv)->getType()->isArrayType()) {
5570 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005571 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5572 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005573 EmitOMPAggregateReduction(
5574 CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5575 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5576 emitReductionCombiner(CGF, E);
5577 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005578 } else {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005579 // Emit reduction for array subscript or single variable.
Alexey Bataeva839ddd2016-03-17 10:19:46 +00005580 emitReductionCombiner(CGF, E);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005581 }
Richard Trieucc3949d2016-02-18 22:34:54 +00005582 ++IPriv;
5583 ++ILHS;
5584 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005585 }
5586 Scope.ForceCleanup();
5587 CGF.FinishFunction();
5588 return Fn;
5589}
5590
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005591void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF,
5592 const Expr *ReductionOp,
5593 const Expr *PrivateRef,
5594 const DeclRefExpr *LHS,
5595 const DeclRefExpr *RHS) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005596 if (PrivateRef->getType()->isArrayType()) {
5597 // Emit reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005598 const auto *LHSVar = cast<VarDecl>(LHS->getDecl());
5599 const auto *RHSVar = cast<VarDecl>(RHS->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005600 EmitOMPAggregateReduction(
5601 CGF, PrivateRef->getType(), LHSVar, RHSVar,
5602 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) {
5603 emitReductionCombiner(CGF, ReductionOp);
5604 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005605 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005606 // Emit reduction for array subscript or single variable.
5607 emitReductionCombiner(CGF, ReductionOp);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005608 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005609}
5610
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005611void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005612 ArrayRef<const Expr *> Privates,
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005613 ArrayRef<const Expr *> LHSExprs,
5614 ArrayRef<const Expr *> RHSExprs,
5615 ArrayRef<const Expr *> ReductionOps,
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005616 ReductionOptionsTy Options) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00005617 if (!CGF.HaveInsertPoint())
5618 return;
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005619
5620 bool WithNowait = Options.WithNowait;
5621 bool SimpleReduction = Options.SimpleReduction;
5622
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005623 // Next code should be emitted for reduction:
5624 //
5625 // static kmp_critical_name lock = { 0 };
5626 //
5627 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) {
5628 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]);
5629 // ...
5630 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1],
5631 // *(Type<n>-1*)rhs[<n>-1]);
5632 // }
5633 //
5634 // ...
5635 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]};
5636 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5637 // RedList, reduce_func, &<lock>)) {
5638 // case 1:
5639 // ...
5640 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5641 // ...
5642 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5643 // break;
5644 // case 2:
5645 // ...
5646 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5647 // ...
Alexey Bataev69a47792015-05-07 03:54:03 +00005648 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);]
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005649 // break;
5650 // default:;
5651 // }
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005652 //
5653 // if SimpleReduction is true, only the next code is generated:
5654 // ...
5655 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5656 // ...
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005657
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005658 ASTContext &C = CGM.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005659
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005660 if (SimpleReduction) {
5661 CodeGenFunction::RunCleanupsScope Scope(CGF);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005662 auto IPriv = Privates.begin();
5663 auto ILHS = LHSExprs.begin();
5664 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005665 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005666 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5667 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005668 ++IPriv;
5669 ++ILHS;
5670 ++IRHS;
Alexey Bataev89e7e8e2015-06-17 06:21:39 +00005671 }
5672 return;
5673 }
5674
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005675 // 1. Build a list of reduction variables.
5676 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]};
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005677 auto Size = RHSExprs.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005678 for (const Expr *E : Privates) {
Alexey Bataev1189bd02016-01-26 12:20:39 +00005679 if (E->getType()->isVariablyModifiedType())
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005680 // Reserve place for array size.
5681 ++Size;
5682 }
5683 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005684 QualType ReductionArrayTy =
5685 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal,
5686 /*IndexTypeQuals=*/0);
John McCall7f416cc2015-09-08 08:05:57 +00005687 Address ReductionList =
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005688 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list");
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005689 auto IPriv = Privates.begin();
5690 unsigned Idx = 0;
5691 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) {
James Y Knight751fe282019-02-09 22:22:28 +00005692 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
John McCall7f416cc2015-09-08 08:05:57 +00005693 CGF.Builder.CreateStore(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005694 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
John McCall7f416cc2015-09-08 08:05:57 +00005695 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy),
5696 Elem);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005697 if ((*IPriv)->getType()->isVariablyModifiedType()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005698 // Store array size.
5699 ++Idx;
James Y Knight751fe282019-02-09 22:22:28 +00005700 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx);
Alexey Bataev1189bd02016-01-26 12:20:39 +00005701 llvm::Value *Size = CGF.Builder.CreateIntCast(
5702 CGF.getVLASize(
5703 CGF.getContext().getAsVariableArrayType((*IPriv)->getType()))
Sander de Smalen891af03a2018-02-03 13:55:59 +00005704 .NumElts,
Alexey Bataev1189bd02016-01-26 12:20:39 +00005705 CGF.SizeTy, /*isSigned=*/false);
5706 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy),
5707 Elem);
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005708 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005709 }
5710
5711 // 2. Emit reduce_func().
James Y Knight9871db02019-02-05 16:42:33 +00005712 llvm::Function *ReductionFn = emitReductionFunction(
Alexey Bataev982a35e2019-03-19 17:09:52 +00005713 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates,
5714 LHSExprs, RHSExprs, ReductionOps);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005715
5716 // 3. Create static kmp_critical_name lock = { 0 };
Alexey Bataev18fa2322018-05-02 14:20:50 +00005717 std::string Name = getName({"reduction"});
5718 llvm::Value *Lock = getCriticalRegionLock(Name);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005719
5720 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList),
5721 // RedList, reduce_func, &<lock>);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005722 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE);
5723 llvm::Value *ThreadId = getThreadID(CGF, Loc);
5724 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy);
5725 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
Samuel Antao4c8035b2016-12-12 18:00:20 +00005726 ReductionList.getPointer(), CGF.VoidPtrTy);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005727 llvm::Value *Args[] = {
5728 IdentTLoc, // ident_t *<loc>
5729 ThreadId, // i32 <gtid>
5730 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n>
5731 ReductionArrayTySize, // size_type sizeof(RedList)
5732 RL, // void *RedList
5733 ReductionFn, // void (*) (void *, void *) <reduce_func>
5734 Lock // kmp_critical_name *&<lock>
5735 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005736 llvm::Value *Res = CGF.EmitRuntimeCall(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005737 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait
5738 : OMPRTL__kmpc_reduce),
5739 Args);
5740
5741 // 5. Build switch(res)
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005742 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default");
5743 llvm::SwitchInst *SwInst =
5744 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005745
5746 // 6. Build case 1:
5747 // ...
5748 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]);
5749 // ...
5750 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5751 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005752 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005753 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB);
5754 CGF.EmitBlock(Case1BB);
5755
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005756 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>);
5757 llvm::Value *EndArgs[] = {
5758 IdentTLoc, // ident_t *<loc>
5759 ThreadId, // i32 <gtid>
5760 Lock // kmp_critical_name *&<lock>
5761 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005762 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps](
5763 CodeGenFunction &CGF, PrePostActionTy &Action) {
5764 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005765 auto IPriv = Privates.begin();
5766 auto ILHS = LHSExprs.begin();
5767 auto IRHS = RHSExprs.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005768 for (const Expr *E : ReductionOps) {
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005769 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS),
5770 cast<DeclRefExpr>(*IRHS));
Richard Trieucc3949d2016-02-18 22:34:54 +00005771 ++IPriv;
5772 ++ILHS;
5773 ++IRHS;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005774 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005775 };
5776 RegionCodeGenTy RCG(CodeGen);
5777 CommonActionTy Action(
5778 nullptr, llvm::None,
5779 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait
5780 : OMPRTL__kmpc_end_reduce),
5781 EndArgs);
5782 RCG.setAction(Action);
5783 RCG(CGF);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005784
5785 CGF.EmitBranch(DefaultBB);
5786
5787 // 7. Build case 2:
5788 // ...
5789 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]));
5790 // ...
5791 // break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005792 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2");
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005793 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB);
5794 CGF.EmitBlock(Case2BB);
5795
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005796 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps](
5797 CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005798 auto ILHS = LHSExprs.begin();
5799 auto IRHS = RHSExprs.begin();
5800 auto IPriv = Privates.begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005801 for (const Expr *E : ReductionOps) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005802 const Expr *XExpr = nullptr;
5803 const Expr *EExpr = nullptr;
5804 const Expr *UpExpr = nullptr;
5805 BinaryOperatorKind BO = BO_Comma;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005806 if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005807 if (BO->getOpcode() == BO_Assign) {
5808 XExpr = BO->getLHS();
5809 UpExpr = BO->getRHS();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005810 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005811 }
5812 // Try to emit update expression as a simple atomic.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005813 const Expr *RHSExpr = UpExpr;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005814 if (RHSExpr) {
5815 // Analyze RHS part of the whole expression.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005816 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005817 RHSExpr->IgnoreParenImpCasts())) {
5818 // If this is a conditional operator, analyze its condition for
5819 // min/max reduction operator.
5820 RHSExpr = ACO->getCond();
Alexey Bataev69a47792015-05-07 03:54:03 +00005821 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005822 if (const auto *BORHS =
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005823 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) {
5824 EExpr = BORHS->getRHS();
5825 BO = BORHS->getOpcode();
Alexey Bataevf24e7b12015-10-08 09:10:53 +00005826 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005827 }
5828 if (XExpr) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005829 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005830 auto &&AtomicRedGen = [BO, VD,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005831 Loc](CodeGenFunction &CGF, const Expr *XExpr,
5832 const Expr *EExpr, const Expr *UpExpr) {
5833 LValue X = CGF.EmitLValue(XExpr);
5834 RValue E;
5835 if (EExpr)
5836 E = CGF.EmitAnyExpr(EExpr);
5837 CGF.EmitOMPAtomicSimpleUpdateExpr(
JF Bastien92f4ef12016-04-06 17:26:42 +00005838 X, E, BO, /*IsXLHSInRHSPart=*/true,
5839 llvm::AtomicOrdering::Monotonic, Loc,
Malcolm Parsonsc6e45832017-01-13 18:55:32 +00005840 [&CGF, UpExpr, VD, Loc](RValue XRValue) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005841 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5842 PrivateScope.addPrivate(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005843 VD, [&CGF, VD, XRValue, Loc]() {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005844 Address LHSTemp = CGF.CreateMemTemp(VD->getType());
5845 CGF.emitOMPSimpleStore(
5846 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue,
5847 VD->getType().getNonReferenceType(), Loc);
5848 return LHSTemp;
5849 });
5850 (void)PrivateScope.Privatize();
5851 return CGF.EmitAnyExpr(UpExpr);
5852 });
5853 };
5854 if ((*IPriv)->getType()->isArrayType()) {
5855 // Emit atomic reduction for array section.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005856 const auto *RHSVar =
5857 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005858 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar,
5859 AtomicRedGen, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005860 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005861 // Emit atomic reduction for array subscript or single variable.
5862 AtomicRedGen(CGF, XExpr, EExpr, UpExpr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005863 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005864 } else {
5865 // Emit as a critical region.
5866 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *,
Alexey Bataev18fa2322018-05-02 14:20:50 +00005867 const Expr *, const Expr *) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005868 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev18fa2322018-05-02 14:20:50 +00005869 std::string Name = RT.getName({"atomic_reduction"});
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005870 RT.emitCriticalRegion(
Alexey Bataev18fa2322018-05-02 14:20:50 +00005871 CGF, Name,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005872 [=](CodeGenFunction &CGF, PrePostActionTy &Action) {
5873 Action.Enter(CGF);
5874 emitReductionCombiner(CGF, E);
5875 },
5876 Loc);
5877 };
5878 if ((*IPriv)->getType()->isArrayType()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005879 const auto *LHSVar =
5880 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
5881 const auto *RHSVar =
5882 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005883 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar,
5884 CritRedGen);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005885 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005886 CritRedGen(CGF, nullptr, nullptr, nullptr);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005887 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005888 }
Richard Trieucc3949d2016-02-18 22:34:54 +00005889 ++ILHS;
5890 ++IRHS;
5891 ++IPriv;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005892 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005893 };
5894 RegionCodeGenTy AtomicRCG(AtomicCodeGen);
5895 if (!WithNowait) {
5896 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>);
5897 llvm::Value *EndArgs[] = {
5898 IdentTLoc, // ident_t *<loc>
5899 ThreadId, // i32 <gtid>
5900 Lock // kmp_critical_name *&<lock>
5901 };
5902 CommonActionTy Action(nullptr, llvm::None,
5903 createRuntimeFunction(OMPRTL__kmpc_end_reduce),
5904 EndArgs);
5905 AtomicRCG.setAction(Action);
5906 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005907 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00005908 AtomicRCG(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005909 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00005910
5911 CGF.EmitBranch(DefaultBB);
5912 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true);
5913}
5914
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005915/// Generates unique name for artificial threadprivate variables.
Alexey Bataev1c44e152018-03-06 18:59:43 +00005916/// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>"
5917static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix,
5918 const Expr *Ref) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005919 SmallString<256> Buffer;
5920 llvm::raw_svector_ostream Out(Buffer);
Alexey Bataev1c44e152018-03-06 18:59:43 +00005921 const clang::DeclRefExpr *DE;
5922 const VarDecl *D = ::getBaseDecl(Ref, DE);
5923 if (!D)
5924 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl());
5925 D = D->getCanonicalDecl();
Alexey Bataev18fa2322018-05-02 14:20:50 +00005926 std::string Name = CGM.getOpenMPRuntime().getName(
5927 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)});
5928 Out << Prefix << Name << "_"
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005929 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005930 return Out.str();
5931}
5932
5933/// Emits reduction initializer function:
5934/// \code
5935/// void @.red_init(void* %arg) {
5936/// %0 = bitcast void* %arg to <type>*
5937/// store <type> <init>, <type>* %0
5938/// ret void
5939/// }
5940/// \endcode
5941static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM,
5942 SourceLocation Loc,
5943 ReductionCodeGen &RCG, unsigned N) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005944 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005945 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005946 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
5947 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005948 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005949 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005950 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00005951 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00005952 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005953 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00005954 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00005955 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00005956 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005957 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00005958 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005959 Address PrivateAddr = CGF.EmitLoadOfPointer(
5960 CGF.GetAddrOfLocalVar(&Param),
5961 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
5962 llvm::Value *Size = nullptr;
5963 // If the size of the reduction item is non-constant, load it from global
5964 // threadprivate variable.
5965 if (RCG.getSizes(N).second) {
5966 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
5967 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00005968 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00005969 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
5970 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005971 }
5972 RCG.emitAggregateType(CGF, N, Size);
5973 LValue SharedLVal;
5974 // If initializer uses initializer from declare reduction construct, emit a
5975 // pointer to the address of the original reduction item (reuired by reduction
5976 // initializer)
5977 if (RCG.usesReductionInitializer(N)) {
5978 Address SharedAddr =
5979 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
5980 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00005981 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataev21dab122018-03-09 15:20:30 +00005982 SharedAddr = CGF.EmitLoadOfPointer(
5983 SharedAddr,
5984 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00005985 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy);
5986 } else {
5987 SharedLVal = CGF.MakeNaturalAlignAddrLValue(
5988 llvm::ConstantPointerNull::get(CGM.VoidPtrTy),
5989 CGM.getContext().VoidPtrTy);
5990 }
5991 // Emit the initializer:
5992 // %0 = bitcast void* %arg to <type>*
5993 // store <type> <init>, <type>* %0
5994 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal,
5995 [](CodeGenFunction &) { return false; });
5996 CGF.FinishFunction();
5997 return Fn;
5998}
5999
6000/// Emits reduction combiner function:
6001/// \code
6002/// void @.red_comb(void* %arg0, void* %arg1) {
6003/// %lhs = bitcast void* %arg0 to <type>*
6004/// %rhs = bitcast void* %arg1 to <type>*
6005/// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs)
6006/// store <type> %2, <type>* %lhs
6007/// ret void
6008/// }
6009/// \endcode
6010static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM,
6011 SourceLocation Loc,
6012 ReductionCodeGen &RCG, unsigned N,
6013 const Expr *ReductionOp,
6014 const Expr *LHS, const Expr *RHS,
6015 const Expr *PrivateRef) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006016 ASTContext &C = CGM.getContext();
6017 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl());
6018 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl());
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006019 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006020 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr,
6021 C.VoidPtrTy, ImplicitParamDecl::Other);
6022 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6023 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006024 Args.emplace_back(&ParamInOut);
6025 Args.emplace_back(&ParamIn);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006026 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006027 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006028 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006029 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006030 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006031 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006032 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006033 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006034 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006035 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006036 llvm::Value *Size = nullptr;
6037 // If the size of the reduction item is non-constant, load it from global
6038 // threadprivate variable.
6039 if (RCG.getSizes(N).second) {
6040 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6041 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006042 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006043 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6044 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006045 }
6046 RCG.emitAggregateType(CGF, N, Size);
6047 // Remap lhs and rhs variables to the addresses of the function arguments.
6048 // %lhs = bitcast void* %arg0 to <type>*
6049 // %rhs = bitcast void* %arg1 to <type>*
6050 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006051 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006052 // Pull out the pointer to the variable.
6053 Address PtrAddr = CGF.EmitLoadOfPointer(
6054 CGF.GetAddrOfLocalVar(&ParamInOut),
6055 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6056 return CGF.Builder.CreateElementBitCast(
6057 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType()));
6058 });
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006059 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006060 // Pull out the pointer to the variable.
6061 Address PtrAddr = CGF.EmitLoadOfPointer(
6062 CGF.GetAddrOfLocalVar(&ParamIn),
6063 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6064 return CGF.Builder.CreateElementBitCast(
6065 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType()));
6066 });
6067 PrivateScope.Privatize();
6068 // Emit the combiner body:
6069 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs)
6070 // store <type> %2, <type>* %lhs
6071 CGM.getOpenMPRuntime().emitSingleReductionCombiner(
6072 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS),
6073 cast<DeclRefExpr>(RHS));
6074 CGF.FinishFunction();
6075 return Fn;
6076}
6077
6078/// Emits reduction finalizer function:
6079/// \code
6080/// void @.red_fini(void* %arg) {
6081/// %0 = bitcast void* %arg to <type>*
6082/// <destroy>(<type>* %0)
6083/// ret void
6084/// }
6085/// \endcode
6086static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM,
6087 SourceLocation Loc,
6088 ReductionCodeGen &RCG, unsigned N) {
6089 if (!RCG.needCleanups(N))
6090 return nullptr;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006091 ASTContext &C = CGM.getContext();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006092 FunctionArgList Args;
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006093 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy,
6094 ImplicitParamDecl::Other);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006095 Args.emplace_back(&Param);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006096 const auto &FnInfo =
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006097 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006098 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo);
Alexey Bataev18fa2322018-05-02 14:20:50 +00006099 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""});
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006100 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006101 Name, &CGM.getModule());
Rafael Espindola51ec5a92018-02-28 23:46:35 +00006102 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00006103 Fn->setDoesNotRecurse();
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006104 CodeGenFunction CGF(CGM);
Alexey Bataev7cae94e2018-01-04 19:45:16 +00006105 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006106 Address PrivateAddr = CGF.EmitLoadOfPointer(
6107 CGF.GetAddrOfLocalVar(&Param),
6108 C.getPointerType(C.VoidPtrTy).castAs<PointerType>());
6109 llvm::Value *Size = nullptr;
6110 // If the size of the reduction item is non-constant, load it from global
6111 // threadprivate variable.
6112 if (RCG.getSizes(N).second) {
6113 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate(
6114 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006115 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00006116 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false,
6117 CGM.getContext().getSizeType(), Loc);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006118 }
6119 RCG.emitAggregateType(CGF, N, Size);
6120 // Emit the finalizer body:
6121 // <destroy>(<type>* %0)
6122 RCG.emitCleanups(CGF, N, PrivateAddr);
6123 CGF.FinishFunction();
6124 return Fn;
6125}
6126
6127llvm::Value *CGOpenMPRuntime::emitTaskReductionInit(
6128 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
6129 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
6130 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty())
6131 return nullptr;
6132
6133 // Build typedef struct:
6134 // kmp_task_red_input {
6135 // void *reduce_shar; // shared reduction item
6136 // size_t reduce_size; // size of data item
6137 // void *reduce_init; // data initialization routine
6138 // void *reduce_fini; // data finalization routine
6139 // void *reduce_comb; // data combiner routine
6140 // kmp_task_red_flags_t flags; // flags for additional info from compiler
6141 // } kmp_task_red_input_t;
6142 ASTContext &C = CGM.getContext();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006143 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t");
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006144 RD->startDefinition();
6145 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6146 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType());
6147 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6148 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6149 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy);
6150 const FieldDecl *FlagsFD = addFieldToRecordDecl(
6151 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false));
6152 RD->completeDefinition();
6153 QualType RDType = C.getRecordType(RD);
6154 unsigned Size = Data.ReductionVars.size();
6155 llvm::APInt ArraySize(/*numBits=*/64, Size);
6156 QualType ArrayRDType = C.getConstantArrayType(
6157 RDType, ArraySize, ArrayType::Normal, /*IndexTypeQuals=*/0);
6158 // kmp_task_red_input_t .rd_input.[Size];
6159 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input.");
6160 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies,
6161 Data.ReductionOps);
6162 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) {
6163 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt];
6164 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0),
6165 llvm::ConstantInt::get(CGM.SizeTy, Cnt)};
6166 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP(
6167 TaskRedInput.getPointer(), Idxs,
6168 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc,
6169 ".rd_input.gep.");
6170 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType);
6171 // ElemLVal.reduce_shar = &Shareds[Cnt];
6172 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD);
6173 RCG.emitSharedLValue(CGF, Cnt);
6174 llvm::Value *CastedShared =
6175 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer());
6176 CGF.EmitStoreOfScalar(CastedShared, SharedLVal);
6177 RCG.emitAggregateType(CGF, Cnt);
6178 llvm::Value *SizeValInChars;
6179 llvm::Value *SizeVal;
6180 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt);
6181 // We use delayed creation/initialization for VLAs, array sections and
6182 // custom reduction initializations. It is required because runtime does not
6183 // provide the way to pass the sizes of VLAs/array sections to
6184 // initializer/combiner/finalizer functions and does not pass the pointer to
6185 // original reduction item to the initializer. Instead threadprivate global
6186 // variables are used to store these values and use them in the functions.
6187 bool DelayedCreation = !!SizeVal;
6188 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy,
6189 /*isSigned=*/false);
6190 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD);
6191 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal);
6192 // ElemLVal.reduce_init = init;
6193 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD);
6194 llvm::Value *InitAddr =
6195 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt));
6196 CGF.EmitStoreOfScalar(InitAddr, InitLVal);
6197 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt);
6198 // ElemLVal.reduce_fini = fini;
6199 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD);
6200 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt);
6201 llvm::Value *FiniAddr = Fini
6202 ? CGF.EmitCastToVoidPtr(Fini)
6203 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy);
6204 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal);
6205 // ElemLVal.reduce_comb = comb;
6206 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD);
6207 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction(
6208 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt],
6209 RHSExprs[Cnt], Data.ReductionCopies[Cnt]));
6210 CGF.EmitStoreOfScalar(CombAddr, CombLVal);
6211 // ElemLVal.flags = 0;
6212 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD);
6213 if (DelayedCreation) {
6214 CGF.EmitStoreOfScalar(
6215 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*IsSigned=*/true),
6216 FlagsLVal);
6217 } else
6218 CGF.EmitNullInitialization(FlagsLVal.getAddress(), FlagsLVal.getType());
6219 }
6220 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void
6221 // *data);
6222 llvm::Value *Args[] = {
6223 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6224 /*isSigned=*/true),
6225 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true),
6226 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(),
6227 CGM.VoidPtrTy)};
6228 return CGF.EmitRuntimeCall(
6229 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args);
6230}
6231
6232void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
6233 SourceLocation Loc,
6234 ReductionCodeGen &RCG,
6235 unsigned N) {
6236 auto Sizes = RCG.getSizes(N);
6237 // Emit threadprivate global variable if the type is non-constant
6238 // (Sizes.second = nullptr).
6239 if (Sizes.second) {
6240 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy,
6241 /*isSigned=*/false);
6242 Address SizeAddr = getAddrOfArtificialThreadPrivate(
6243 CGF, CGM.getContext().getSizeType(),
Alexey Bataev1c44e152018-03-06 18:59:43 +00006244 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006245 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false);
6246 }
6247 // Store address of the original reduction item if custom initializer is used.
6248 if (RCG.usesReductionInitializer(N)) {
6249 Address SharedAddr = getAddrOfArtificialThreadPrivate(
6250 CGF, CGM.getContext().VoidPtrTy,
Alexey Bataev1c44e152018-03-06 18:59:43 +00006251 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N)));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00006252 CGF.Builder.CreateStore(
6253 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
6254 RCG.getSharedLValue(N).getPointer(), CGM.VoidPtrTy),
6255 SharedAddr, /*IsVolatile=*/false);
6256 }
6257}
6258
6259Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF,
6260 SourceLocation Loc,
6261 llvm::Value *ReductionsPtr,
6262 LValue SharedLVal) {
6263 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void
6264 // *d);
6265 llvm::Value *Args[] = {
6266 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy,
6267 /*isSigned=*/true),
6268 ReductionsPtr,
6269 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(SharedLVal.getPointer(),
6270 CGM.VoidPtrTy)};
6271 return Address(
6272 CGF.EmitRuntimeCall(
6273 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args),
6274 SharedLVal.getAlignment());
6275}
6276
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006277void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
6278 SourceLocation Loc) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006279 if (!CGF.HaveInsertPoint())
6280 return;
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006281 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
6282 // global_tid);
6283 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
6284 // Ignore return result until untied tasks are supported.
6285 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args);
Alexey Bataev48591dd2016-04-20 04:01:36 +00006286 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
6287 Region->emitUntiedSwitch(CGF);
Alexey Bataev8b8e2022015-04-27 05:22:09 +00006288}
6289
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006290void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF,
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006291 OpenMPDirectiveKind InnerKind,
Alexey Bataev25e5b442015-09-15 12:52:43 +00006292 const RegionCodeGenTy &CodeGen,
6293 bool HasCancel) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006294 if (!CGF.HaveInsertPoint())
6295 return;
Alexey Bataev25e5b442015-09-15 12:52:43 +00006296 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00006297 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr);
Alexey Bataev8cbe0a62015-02-26 10:27:34 +00006298}
6299
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006300namespace {
6301enum RTCancelKind {
6302 CancelNoreq = 0,
6303 CancelParallel = 1,
6304 CancelLoop = 2,
6305 CancelSections = 3,
6306 CancelTaskgroup = 4
6307};
Eugene Zelenko0a4f3f42016-02-10 19:11:58 +00006308} // anonymous namespace
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006309
6310static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) {
6311 RTCancelKind CancelKind = CancelNoreq;
Alexey Bataev0f34da12015-07-02 04:17:07 +00006312 if (CancelRegion == OMPD_parallel)
6313 CancelKind = CancelParallel;
6314 else if (CancelRegion == OMPD_for)
6315 CancelKind = CancelLoop;
6316 else if (CancelRegion == OMPD_sections)
6317 CancelKind = CancelSections;
6318 else {
6319 assert(CancelRegion == OMPD_taskgroup);
6320 CancelKind = CancelTaskgroup;
6321 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006322 return CancelKind;
6323}
6324
6325void CGOpenMPRuntime::emitCancellationPointCall(
6326 CodeGenFunction &CGF, SourceLocation Loc,
6327 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006328 if (!CGF.HaveInsertPoint())
6329 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006330 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32
6331 // global_tid, kmp_int32 cncl_kind);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006332 if (auto *OMPRegionInfo =
6333 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Jonas Hahnfeldb07931f2017-02-17 18:32:58 +00006334 // For 'cancellation point taskgroup', the task region info may not have a
6335 // cancel. This may instead happen in another adjacent task.
6336 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) {
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006337 llvm::Value *Args[] = {
6338 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc),
6339 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006340 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006341 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006342 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args);
6343 // if (__kmpc_cancellationpoint()) {
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006344 // exit from construct;
6345 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006346 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6347 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6348 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006349 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6350 CGF.EmitBlock(ExitBB);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006351 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006352 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev25e5b442015-09-15 12:52:43 +00006353 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
Alexey Bataev81c7ea02015-07-03 09:56:58 +00006354 CGF.EmitBranchThroughCleanup(CancelDest);
6355 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6356 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006357 }
Alexey Bataev0f34da12015-07-02 04:17:07 +00006358}
6359
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006360void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc,
Alexey Bataev87933c72015-09-18 08:07:34 +00006361 const Expr *IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006362 OpenMPDirectiveKind CancelRegion) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00006363 if (!CGF.HaveInsertPoint())
6364 return;
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006365 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid,
6366 // kmp_int32 cncl_kind);
6367 if (auto *OMPRegionInfo =
6368 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006369 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF,
6370 PrePostActionTy &) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006371 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime();
Alexey Bataev87933c72015-09-18 08:07:34 +00006372 llvm::Value *Args[] = {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006373 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc),
Alexey Bataev87933c72015-09-18 08:07:34 +00006374 CGF.Builder.getInt32(getCancellationKind(CancelRegion))};
6375 // Ignore return result until untied tasks are supported.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006376 llvm::Value *Result = CGF.EmitRuntimeCall(
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006377 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args);
Alexey Bataev87933c72015-09-18 08:07:34 +00006378 // if (__kmpc_cancel()) {
Alexey Bataev87933c72015-09-18 08:07:34 +00006379 // exit from construct;
6380 // }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006381 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit");
6382 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue");
6383 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result);
Alexey Bataev87933c72015-09-18 08:07:34 +00006384 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB);
6385 CGF.EmitBlock(ExitBB);
Alexey Bataev87933c72015-09-18 08:07:34 +00006386 // exit from construct;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006387 CodeGenFunction::JumpDest CancelDest =
Alexey Bataev87933c72015-09-18 08:07:34 +00006388 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind());
6389 CGF.EmitBranchThroughCleanup(CancelDest);
6390 CGF.EmitBlock(ContBB, /*IsFinished=*/true);
6391 };
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006392 if (IfCond) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006393 emitOMPIfClause(CGF, IfCond, ThenGen,
6394 [](CodeGenFunction &, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006395 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006396 RegionCodeGenTy ThenRCG(ThenGen);
6397 ThenRCG(CGF);
6398 }
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00006399 }
6400}
Samuel Antaobed3c462015-10-02 16:14:20 +00006401
Samuel Antaoee8fb302016-01-06 13:42:12 +00006402void CGOpenMPRuntime::emitTargetOutlinedFunction(
6403 const OMPExecutableDirective &D, StringRef ParentName,
6404 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00006405 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00006406 assert(!ParentName.empty() && "Invalid target region parent name!");
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006407 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID,
6408 IsOffloadEntry, CodeGen);
6409}
6410
6411void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper(
6412 const OMPExecutableDirective &D, StringRef ParentName,
6413 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
6414 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
Samuel Antao2de62b02016-02-13 23:35:10 +00006415 // Create a unique name for the entry function using the source location
6416 // information of the current target region. The name will be something like:
Samuel Antaoee8fb302016-01-06 13:42:12 +00006417 //
Samuel Antao2de62b02016-02-13 23:35:10 +00006418 // __omp_offloading_DD_FFFF_PP_lBB
Samuel Antaoee8fb302016-01-06 13:42:12 +00006419 //
6420 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the
Samuel Antao2de62b02016-02-13 23:35:10 +00006421 // mangled name of the function that encloses the target region and BB is the
6422 // line number of the target region.
Samuel Antaoee8fb302016-01-06 13:42:12 +00006423
6424 unsigned DeviceID;
6425 unsigned FileID;
6426 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00006427 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID,
Samuel Antao2de62b02016-02-13 23:35:10 +00006428 Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006429 SmallString<64> EntryFnName;
6430 {
6431 llvm::raw_svector_ostream OS(EntryFnName);
Samuel Antao2de62b02016-02-13 23:35:10 +00006432 OS << "__omp_offloading" << llvm::format("_%x", DeviceID)
6433 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line;
Samuel Antaoee8fb302016-01-06 13:42:12 +00006434 }
6435
Alexey Bataev475a7442018-01-12 19:39:11 +00006436 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Arpith Chacko Jacob5c309e42016-03-22 01:48:56 +00006437
Samuel Antaobed3c462015-10-02 16:14:20 +00006438 CodeGenFunction CGF(CGM, true);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006439 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName);
Samuel Antaobed3c462015-10-02 16:14:20 +00006440 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006441
Samuel Antao6d004262016-06-16 18:39:34 +00006442 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS);
Samuel Antaoee8fb302016-01-06 13:42:12 +00006443
6444 // If this target outline function is not an offload entry, we don't need to
6445 // register it.
6446 if (!IsOffloadEntry)
6447 return;
6448
6449 // The target region ID is used by the runtime library to identify the current
6450 // target region, so it only has to be unique and not necessarily point to
6451 // anything. It could be the pointer to the outlined function that implements
6452 // the target region, but we aren't using that so that the compiler doesn't
6453 // need to keep that, and could therefore inline the host function if proven
6454 // worthwhile during optimization. In the other hand, if emitting code for the
6455 // device, the ID has to be the function address so that it can retrieved from
6456 // the offloading entry and launched by the runtime library. We also mark the
6457 // outlined function to have external linkage in case we are emitting code for
6458 // the device, because these functions will be entry points to the device.
6459
6460 if (CGM.getLangOpts().OpenMPIsDevice) {
6461 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy);
Alexey Bataev9a700172018-05-08 14:16:57 +00006462 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
Rafael Espindolacbca4872018-01-11 22:15:12 +00006463 OutlinedFn->setDSOLocal(false);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006464 } else {
Alexey Bataevc15ea702018-05-09 18:02:37 +00006465 std::string Name = getName({EntryFnName, "region_id"});
Samuel Antaoee8fb302016-01-06 13:42:12 +00006466 OutlinedFnID = new llvm::GlobalVariable(
6467 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true,
Alexey Bataev9a700172018-05-08 14:16:57 +00006468 llvm::GlobalValue::WeakAnyLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00006469 llvm::Constant::getNullValue(CGM.Int8Ty), Name);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006470 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00006471
6472 // Register the information for the entry associated with this target region.
6473 OffloadEntriesInfoManager.registerTargetRegionEntryInfo(
Samuel Antaof83efdb2017-01-05 16:02:49 +00006474 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID,
Alexey Bataev03f270c2018-03-30 18:31:07 +00006475 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion);
Samuel Antaobed3c462015-10-02 16:14:20 +00006476}
6477
Alexey Bataev5c427362019-04-10 19:11:33 +00006478/// Checks if the expression is constant or does not have non-trivial function
6479/// calls.
6480static bool isTrivial(ASTContext &Ctx, const Expr * E) {
6481 // We can skip constant expressions.
6482 // We can skip expressions with trivial calls or simple expressions.
6483 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) ||
6484 !E->hasNonTrivialCall(Ctx)) &&
6485 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true);
6486}
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006487
Alexey Bataev5c427362019-04-10 19:11:33 +00006488const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx,
6489 const Stmt *Body) {
6490 const Stmt *Child = Body->IgnoreContainers();
6491 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) {
6492 Child = nullptr;
6493 for (const Stmt *S : C->body()) {
6494 if (const auto *E = dyn_cast<Expr>(S)) {
6495 if (isTrivial(Ctx, E))
6496 continue;
6497 }
6498 // Some of the statements can be ignored.
6499 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) ||
6500 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S))
6501 continue;
6502 // Analyze declarations.
6503 if (const auto *DS = dyn_cast<DeclStmt>(S)) {
6504 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) {
6505 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) ||
6506 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) ||
6507 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) ||
6508 isa<UsingDirectiveDecl>(D) ||
6509 isa<OMPDeclareReductionDecl>(D) ||
6510 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D))
6511 return true;
6512 const auto *VD = dyn_cast<VarDecl>(D);
6513 if (!VD)
6514 return false;
6515 return VD->isConstexpr() ||
6516 ((VD->getType().isTrivialType(Ctx) ||
6517 VD->getType()->isReferenceType()) &&
6518 (!VD->hasInit() || isTrivial(Ctx, VD->getInit())));
6519 }))
6520 continue;
6521 }
6522 // Found multiple children - cannot get the one child only.
6523 if (Child)
6524 return nullptr;
6525 Child = S;
6526 }
6527 if (Child)
6528 Child = Child->IgnoreContainers();
6529 }
6530 return Child;
Carlo Bertolli6eee9062016-04-29 01:37:30 +00006531}
6532
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006533/// Emit the number of teams for a target directive. Inspect the num_teams
6534/// clause associated with a teams construct combined or closely nested
6535/// with the target directive.
6536///
6537/// Emit a team of size one for directives such as 'target parallel' that
6538/// have no associated teams construct.
6539///
6540/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006541static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006542emitNumTeamsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006543 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006544 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6545 "Clauses associated with the teams directive expected to be emitted "
6546 "only for the host!");
6547 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6548 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6549 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006550 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006551 switch (DirectiveKind) {
6552 case OMPD_target: {
6553 const auto *CS = D.getInnermostCapturedStmt();
6554 const auto *Body =
6555 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
6556 const Stmt *ChildStmt =
6557 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body);
6558 if (const auto *NestedDir =
6559 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
6560 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) {
6561 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) {
6562 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6563 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6564 const Expr *NumTeams =
6565 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6566 llvm::Value *NumTeamsVal =
6567 CGF.EmitScalarExpr(NumTeams,
6568 /*IgnoreResultAssign*/ true);
6569 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
6570 /*IsSigned=*/true);
6571 }
6572 return Bld.getInt32(0);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006573 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006574 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) ||
6575 isOpenMPSimdDirective(NestedDir->getDirectiveKind()))
6576 return Bld.getInt32(1);
Alexey Bataev50a1c782017-12-01 21:31:08 +00006577 return Bld.getInt32(0);
6578 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006579 return nullptr;
Samuel Antaob68e2db2016-03-03 16:20:23 +00006580 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006581 case OMPD_target_teams:
6582 case OMPD_target_teams_distribute:
6583 case OMPD_target_teams_distribute_simd:
6584 case OMPD_target_teams_distribute_parallel_for:
6585 case OMPD_target_teams_distribute_parallel_for_simd: {
6586 if (D.hasClausesOfKind<OMPNumTeamsClause>()) {
6587 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF);
6588 const Expr *NumTeams =
6589 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams();
6590 llvm::Value *NumTeamsVal =
6591 CGF.EmitScalarExpr(NumTeams,
6592 /*IgnoreResultAssign*/ true);
6593 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty,
6594 /*IsSigned=*/true);
6595 }
6596 return Bld.getInt32(0);
6597 }
6598 case OMPD_target_parallel:
6599 case OMPD_target_parallel_for:
6600 case OMPD_target_parallel_for_simd:
6601 case OMPD_target_simd:
6602 return Bld.getInt32(1);
6603 case OMPD_parallel:
6604 case OMPD_for:
6605 case OMPD_parallel_for:
6606 case OMPD_parallel_sections:
6607 case OMPD_for_simd:
6608 case OMPD_parallel_for_simd:
6609 case OMPD_cancel:
6610 case OMPD_cancellation_point:
6611 case OMPD_ordered:
6612 case OMPD_threadprivate:
6613 case OMPD_allocate:
6614 case OMPD_task:
6615 case OMPD_simd:
6616 case OMPD_sections:
6617 case OMPD_section:
6618 case OMPD_single:
6619 case OMPD_master:
6620 case OMPD_critical:
6621 case OMPD_taskyield:
6622 case OMPD_barrier:
6623 case OMPD_taskwait:
6624 case OMPD_taskgroup:
6625 case OMPD_atomic:
6626 case OMPD_flush:
6627 case OMPD_teams:
6628 case OMPD_target_data:
6629 case OMPD_target_exit_data:
6630 case OMPD_target_enter_data:
6631 case OMPD_distribute:
6632 case OMPD_distribute_simd:
6633 case OMPD_distribute_parallel_for:
6634 case OMPD_distribute_parallel_for_simd:
6635 case OMPD_teams_distribute:
6636 case OMPD_teams_distribute_simd:
6637 case OMPD_teams_distribute_parallel_for:
6638 case OMPD_teams_distribute_parallel_for_simd:
6639 case OMPD_target_update:
6640 case OMPD_declare_simd:
6641 case OMPD_declare_target:
6642 case OMPD_end_declare_target:
6643 case OMPD_declare_reduction:
6644 case OMPD_declare_mapper:
6645 case OMPD_taskloop:
6646 case OMPD_taskloop_simd:
6647 case OMPD_requires:
6648 case OMPD_unknown:
6649 break;
6650 }
6651 llvm_unreachable("Unexpected directive kind.");
6652}
Samuel Antaob68e2db2016-03-03 16:20:23 +00006653
Alexey Bataev5c427362019-04-10 19:11:33 +00006654static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS,
6655 llvm::Value *DefaultThreadLimitVal) {
6656 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6657 CGF.getContext(), CS->getCapturedStmt());
6658 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6659 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) {
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006660 llvm::Value *NumThreads = nullptr;
6661 llvm::Value *CondVal = nullptr;
6662 // Handle if clause. If if clause present, the number of threads is
6663 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6664 if (Dir->hasClausesOfKind<OMPIfClause>()) {
6665 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6666 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6667 const OMPIfClause *IfClause = nullptr;
6668 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) {
6669 if (C->getNameModifier() == OMPD_unknown ||
6670 C->getNameModifier() == OMPD_parallel) {
6671 IfClause = C;
6672 break;
6673 }
6674 }
6675 if (IfClause) {
6676 const Expr *Cond = IfClause->getCondition();
6677 bool Result;
6678 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6679 if (!Result)
6680 return CGF.Builder.getInt32(1);
6681 } else {
6682 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange());
6683 if (const auto *PreInit =
6684 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) {
6685 for (const auto *I : PreInit->decls()) {
6686 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6687 CGF.EmitVarDecl(cast<VarDecl>(*I));
6688 } else {
6689 CodeGenFunction::AutoVarEmission Emission =
6690 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6691 CGF.EmitAutoVarCleanups(Emission);
6692 }
6693 }
6694 }
6695 CondVal = CGF.EvaluateExprAsBool(Cond);
6696 }
6697 }
6698 }
6699 // Check the value of num_threads clause iff if clause was not specified
6700 // or is not evaluated to false.
Alexey Bataev5c427362019-04-10 19:11:33 +00006701 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) {
6702 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6703 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6704 const auto *NumThreadsClause =
6705 Dir->getSingleClause<OMPNumThreadsClause>();
6706 CodeGenFunction::LexicalScope Scope(
6707 CGF, NumThreadsClause->getNumThreads()->getSourceRange());
6708 if (const auto *PreInit =
6709 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) {
6710 for (const auto *I : PreInit->decls()) {
6711 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6712 CGF.EmitVarDecl(cast<VarDecl>(*I));
6713 } else {
6714 CodeGenFunction::AutoVarEmission Emission =
6715 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6716 CGF.EmitAutoVarCleanups(Emission);
6717 }
6718 }
6719 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006720 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads());
Alexey Bataev5c427362019-04-10 19:11:33 +00006721 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty,
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006722 /*IsSigned=*/false);
6723 if (DefaultThreadLimitVal)
6724 NumThreads = CGF.Builder.CreateSelect(
6725 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads),
6726 DefaultThreadLimitVal, NumThreads);
6727 } else {
6728 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal
6729 : CGF.Builder.getInt32(0);
Alexey Bataev5c427362019-04-10 19:11:33 +00006730 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006731 // Process condition of the if clause.
6732 if (CondVal) {
6733 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads,
6734 CGF.Builder.getInt32(1));
6735 }
6736 return NumThreads;
Alexey Bataev5c427362019-04-10 19:11:33 +00006737 }
6738 if (isOpenMPSimdDirective(Dir->getDirectiveKind()))
6739 return CGF.Builder.getInt32(1);
6740 return DefaultThreadLimitVal;
6741 }
6742 return DefaultThreadLimitVal ? DefaultThreadLimitVal
6743 : CGF.Builder.getInt32(0);
Samuel Antaob68e2db2016-03-03 16:20:23 +00006744}
6745
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006746/// Emit the number of threads for a target directive. Inspect the
6747/// thread_limit clause associated with a teams construct combined or closely
6748/// nested with the target directive.
6749///
6750/// Emit the num_threads clause for directives such as 'target parallel' that
6751/// have no associated teams construct.
6752///
6753/// Otherwise, return nullptr.
Samuel Antaob68e2db2016-03-03 16:20:23 +00006754static llvm::Value *
Alexey Bataev5c427362019-04-10 19:11:33 +00006755emitNumThreadsForTargetDirective(CodeGenFunction &CGF,
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006756 const OMPExecutableDirective &D) {
Alexey Bataev5c427362019-04-10 19:11:33 +00006757 assert(!CGF.getLangOpts().OpenMPIsDevice &&
6758 "Clauses associated with the teams directive expected to be emitted "
6759 "only for the host!");
6760 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind();
6761 assert(isOpenMPTargetExecutionDirective(DirectiveKind) &&
6762 "Expected target-based executable directive.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00006763 CGBuilderTy &Bld = CGF.Builder;
Alexey Bataev5c427362019-04-10 19:11:33 +00006764 llvm::Value *ThreadLimitVal = nullptr;
6765 llvm::Value *NumThreadsVal = nullptr;
6766 switch (DirectiveKind) {
6767 case OMPD_target: {
6768 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6769 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6770 return NumThreads;
6771 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6772 CGF.getContext(), CS->getCapturedStmt());
6773 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6774 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) {
6775 CGOpenMPInnerExprInfo CGInfo(CGF, *CS);
6776 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo);
6777 const auto *ThreadLimitClause =
6778 Dir->getSingleClause<OMPThreadLimitClause>();
6779 CodeGenFunction::LexicalScope Scope(
6780 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange());
6781 if (const auto *PreInit =
6782 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) {
6783 for (const auto *I : PreInit->decls()) {
6784 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
6785 CGF.EmitVarDecl(cast<VarDecl>(*I));
6786 } else {
6787 CodeGenFunction::AutoVarEmission Emission =
6788 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
6789 CGF.EmitAutoVarCleanups(Emission);
6790 }
6791 }
6792 }
6793 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6794 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6795 ThreadLimitVal =
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006796 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*IsSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006797 }
6798 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) &&
6799 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) {
6800 CS = Dir->getInnermostCapturedStmt();
6801 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6802 CGF.getContext(), CS->getCapturedStmt());
6803 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child);
6804 }
6805 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) &&
6806 !isOpenMPSimdDirective(Dir->getDirectiveKind())) {
6807 CS = Dir->getInnermostCapturedStmt();
6808 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6809 return NumThreads;
6810 }
6811 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind()))
6812 return Bld.getInt32(1);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006813 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006814 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6815 }
6816 case OMPD_target_teams: {
6817 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6818 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6819 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6820 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6821 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6822 ThreadLimitVal =
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006823 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*IsSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006824 }
6825 const CapturedStmt *CS = D.getInnermostCapturedStmt();
6826 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6827 return NumThreads;
6828 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild(
6829 CGF.getContext(), CS->getCapturedStmt());
6830 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) {
6831 if (Dir->getDirectiveKind() == OMPD_distribute) {
6832 CS = Dir->getInnermostCapturedStmt();
6833 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal))
6834 return NumThreads;
6835 }
6836 }
6837 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0);
6838 }
6839 case OMPD_target_teams_distribute:
6840 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6841 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6842 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6843 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6844 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6845 ThreadLimitVal =
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006846 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*IsSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006847 }
6848 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal);
6849 case OMPD_target_parallel:
6850 case OMPD_target_parallel_for:
6851 case OMPD_target_parallel_for_simd:
6852 case OMPD_target_teams_distribute_parallel_for:
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006853 case OMPD_target_teams_distribute_parallel_for_simd: {
6854 llvm::Value *CondVal = nullptr;
6855 // Handle if clause. If if clause present, the number of threads is
6856 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1.
6857 if (D.hasClausesOfKind<OMPIfClause>()) {
6858 const OMPIfClause *IfClause = nullptr;
6859 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) {
6860 if (C->getNameModifier() == OMPD_unknown ||
6861 C->getNameModifier() == OMPD_parallel) {
6862 IfClause = C;
6863 break;
6864 }
6865 }
6866 if (IfClause) {
6867 const Expr *Cond = IfClause->getCondition();
6868 bool Result;
6869 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) {
6870 if (!Result)
6871 return Bld.getInt32(1);
6872 } else {
6873 CodeGenFunction::RunCleanupsScope Scope(CGF);
6874 CondVal = CGF.EvaluateExprAsBool(Cond);
6875 }
6876 }
6877 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006878 if (D.hasClausesOfKind<OMPThreadLimitClause>()) {
6879 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF);
6880 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>();
6881 llvm::Value *ThreadLimit = CGF.EmitScalarExpr(
6882 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true);
6883 ThreadLimitVal =
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006884 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*IsSigned=*/false);
Alexey Bataev5c427362019-04-10 19:11:33 +00006885 }
6886 if (D.hasClausesOfKind<OMPNumThreadsClause>()) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006887 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
Alexey Bataev5c427362019-04-10 19:11:33 +00006888 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>();
6889 llvm::Value *NumThreads = CGF.EmitScalarExpr(
6890 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true);
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00006891 NumThreadsVal =
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006892 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*IsSigned=*/false);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006893 ThreadLimitVal = ThreadLimitVal
Alexey Bataev5c427362019-04-10 19:11:33 +00006894 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal,
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00006895 ThreadLimitVal),
6896 NumThreadsVal, ThreadLimitVal)
6897 : NumThreadsVal;
Alexey Bataev50a1c782017-12-01 21:31:08 +00006898 }
Alexey Bataevdc9e7dc2019-04-17 16:53:08 +00006899 if (!ThreadLimitVal)
6900 ThreadLimitVal = Bld.getInt32(0);
6901 if (CondVal)
6902 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1));
6903 return ThreadLimitVal;
6904 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006905 case OMPD_target_teams_distribute_simd:
6906 case OMPD_target_simd:
6907 return Bld.getInt32(1);
6908 case OMPD_parallel:
6909 case OMPD_for:
6910 case OMPD_parallel_for:
6911 case OMPD_parallel_sections:
6912 case OMPD_for_simd:
6913 case OMPD_parallel_for_simd:
6914 case OMPD_cancel:
6915 case OMPD_cancellation_point:
6916 case OMPD_ordered:
6917 case OMPD_threadprivate:
6918 case OMPD_allocate:
6919 case OMPD_task:
6920 case OMPD_simd:
6921 case OMPD_sections:
6922 case OMPD_section:
6923 case OMPD_single:
6924 case OMPD_master:
6925 case OMPD_critical:
6926 case OMPD_taskyield:
6927 case OMPD_barrier:
6928 case OMPD_taskwait:
6929 case OMPD_taskgroup:
6930 case OMPD_atomic:
6931 case OMPD_flush:
6932 case OMPD_teams:
6933 case OMPD_target_data:
6934 case OMPD_target_exit_data:
6935 case OMPD_target_enter_data:
6936 case OMPD_distribute:
6937 case OMPD_distribute_simd:
6938 case OMPD_distribute_parallel_for:
6939 case OMPD_distribute_parallel_for_simd:
6940 case OMPD_teams_distribute:
6941 case OMPD_teams_distribute_simd:
6942 case OMPD_teams_distribute_parallel_for:
6943 case OMPD_teams_distribute_parallel_for_simd:
6944 case OMPD_target_update:
6945 case OMPD_declare_simd:
6946 case OMPD_declare_target:
6947 case OMPD_end_declare_target:
6948 case OMPD_declare_reduction:
6949 case OMPD_declare_mapper:
6950 case OMPD_taskloop:
6951 case OMPD_taskloop_simd:
6952 case OMPD_requires:
6953 case OMPD_unknown:
6954 break;
Samuel Antaob68e2db2016-03-03 16:20:23 +00006955 }
Alexey Bataev5c427362019-04-10 19:11:33 +00006956 llvm_unreachable("Unsupported directive kind.");
Samuel Antaob68e2db2016-03-03 16:20:23 +00006957}
6958
Samuel Antao86ace552016-04-27 22:40:57 +00006959namespace {
Alexey Bataevb3638132018-07-19 16:34:13 +00006960LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
6961
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006962// Utility to handle information from clauses associated with a given
Samuel Antao86ace552016-04-27 22:40:57 +00006963// construct that use mappable expressions (e.g. 'map' clause, 'to' clause).
6964// It provides a convenient interface to obtain the information and generate
6965// code for that information.
6966class MappableExprsHandler {
6967public:
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006968 /// Values for bit flags used to specify the mapping type for
Samuel Antao86ace552016-04-27 22:40:57 +00006969 /// offloading.
Alexey Bataevb3638132018-07-19 16:34:13 +00006970 enum OpenMPOffloadMappingFlags : uint64_t {
6971 /// No flags
6972 OMP_MAP_NONE = 0x0,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006973 /// Allocate memory on the device and move data from host to device.
Samuel Antao86ace552016-04-27 22:40:57 +00006974 OMP_MAP_TO = 0x01,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006975 /// Allocate memory on the device and move data from device to host.
Samuel Antao86ace552016-04-27 22:40:57 +00006976 OMP_MAP_FROM = 0x02,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006977 /// Always perform the requested mapping action on the element, even
Samuel Antao86ace552016-04-27 22:40:57 +00006978 /// if it was already mapped before.
6979 OMP_MAP_ALWAYS = 0x04,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006980 /// Delete the element from the device environment, ignoring the
Samuel Antao86ace552016-04-27 22:40:57 +00006981 /// current reference count associated with the element.
Samuel Antao6782e942016-05-26 16:48:10 +00006982 OMP_MAP_DELETE = 0x08,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006983 /// The element being mapped is a pointer-pointee pair; both the
George Rokos065755d2017-11-07 18:27:04 +00006984 /// pointer and the pointee should be mapped.
6985 OMP_MAP_PTR_AND_OBJ = 0x10,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006986 /// This flags signals that the base address of an entry should be
George Rokos065755d2017-11-07 18:27:04 +00006987 /// passed to the target kernel as an argument.
6988 OMP_MAP_TARGET_PARAM = 0x20,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006989 /// Signal that the runtime library has to return the device pointer
George Rokos065755d2017-11-07 18:27:04 +00006990 /// in the current position for the data being mapped. Used when we have the
6991 /// use_device_ptr clause.
6992 OMP_MAP_RETURN_PARAM = 0x40,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006993 /// This flag signals that the reference being passed is a pointer to
Samuel Antaod486f842016-05-26 16:53:38 +00006994 /// private data.
George Rokos065755d2017-11-07 18:27:04 +00006995 OMP_MAP_PRIVATE = 0x80,
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006996 /// Pass the element to the device by value.
George Rokos065755d2017-11-07 18:27:04 +00006997 OMP_MAP_LITERAL = 0x100,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00006998 /// Implicit map
6999 OMP_MAP_IMPLICIT = 0x200,
Alexey Bataevb3638132018-07-19 16:34:13 +00007000 /// The 16 MSBs of the flags indicate whether the entry is member of some
7001 /// struct/class.
7002 OMP_MAP_MEMBER_OF = 0xffff000000000000,
7003 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF),
Samuel Antao86ace552016-04-27 22:40:57 +00007004 };
7005
Samuel Antaocc10b852016-07-28 14:23:26 +00007006 /// Class that associates information with a base pointer to be passed to the
7007 /// runtime library.
7008 class BasePointerInfo {
7009 /// The base pointer.
7010 llvm::Value *Ptr = nullptr;
7011 /// The base declaration that refers to this device pointer, or null if
7012 /// there is none.
7013 const ValueDecl *DevPtrDecl = nullptr;
7014
7015 public:
7016 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr)
7017 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {}
7018 llvm::Value *operator*() const { return Ptr; }
7019 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; }
7020 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; }
7021 };
7022
Alexey Bataevb3638132018-07-19 16:34:13 +00007023 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>;
7024 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>;
7025 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>;
7026
7027 /// Map between a struct and the its lowest & highest elements which have been
7028 /// mapped.
7029 /// [ValueDecl *] --> {LE(FieldIndex, Pointer),
7030 /// HE(FieldIndex, Pointer)}
7031 struct StructRangeInfoTy {
7032 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = {
7033 0, Address::invalid()};
7034 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = {
7035 0, Address::invalid()};
7036 Address Base = Address::invalid();
7037 };
Samuel Antao86ace552016-04-27 22:40:57 +00007038
7039private:
Alexey Bataevb3638132018-07-19 16:34:13 +00007040 /// Kind that defines how a device pointer has to be returned.
7041 struct MapInfo {
7042 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
7043 OpenMPMapClauseKind MapType = OMPC_MAP_unknown;
Kelvin Lief579432018-12-18 22:18:41 +00007044 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataevb3638132018-07-19 16:34:13 +00007045 bool ReturnDevicePointer = false;
7046 bool IsImplicit = false;
7047
7048 MapInfo() = default;
7049 MapInfo(
7050 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Kelvin Lief579432018-12-18 22:18:41 +00007051 OpenMPMapClauseKind MapType,
7052 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007053 bool ReturnDevicePointer, bool IsImplicit)
Kelvin Lief579432018-12-18 22:18:41 +00007054 : Components(Components), MapType(MapType), MapModifiers(MapModifiers),
Alexey Bataevb3638132018-07-19 16:34:13 +00007055 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {}
7056 };
7057
7058 /// If use_device_ptr is used on a pointer which is a struct member and there
7059 /// is no map information about it, then emission of that entry is deferred
7060 /// until the whole struct has been processed.
7061 struct DeferredDevicePtrEntryTy {
7062 const Expr *IE = nullptr;
7063 const ValueDecl *VD = nullptr;
7064
7065 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD)
7066 : IE(IE), VD(VD) {}
7067 };
7068
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007069 /// Directive from where the map clauses were extracted.
Samuel Antao44bcdb32016-07-28 15:31:29 +00007070 const OMPExecutableDirective &CurDir;
Samuel Antao86ace552016-04-27 22:40:57 +00007071
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007072 /// Function the directive is being generated for.
Samuel Antao86ace552016-04-27 22:40:57 +00007073 CodeGenFunction &CGF;
7074
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007075 /// Set of all first private variables in the current directive.
Samuel Antaod486f842016-05-26 16:53:38 +00007076 llvm::SmallPtrSet<const VarDecl *, 8> FirstPrivateDecls;
7077
Samuel Antao6890b092016-07-28 14:25:09 +00007078 /// Map between device pointer declarations and their expression components.
7079 /// The key value for declarations in 'this' is null.
7080 llvm::DenseMap<
7081 const ValueDecl *,
7082 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>>
7083 DevPointersMap;
7084
Samuel Antao86ace552016-04-27 22:40:57 +00007085 llvm::Value *getExprTypeSize(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007086 QualType ExprTy = E->getType().getCanonicalType();
Samuel Antao86ace552016-04-27 22:40:57 +00007087
7088 // Reference types are ignored for mapping purposes.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007089 if (const auto *RefTy = ExprTy->getAs<ReferenceType>())
Samuel Antao86ace552016-04-27 22:40:57 +00007090 ExprTy = RefTy->getPointeeType().getCanonicalType();
7091
7092 // Given that an array section is considered a built-in type, we need to
7093 // do the calculation based on the length of the section instead of relying
7094 // on CGF.getTypeSize(E->getType()).
7095 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) {
7096 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType(
7097 OAE->getBase()->IgnoreParenImpCasts())
7098 .getCanonicalType();
7099
7100 // If there is no length associated with the expression, that means we
7101 // are using the whole length of the base.
7102 if (!OAE->getLength() && OAE->getColonLoc().isValid())
7103 return CGF.getTypeSize(BaseTy);
7104
7105 llvm::Value *ElemSize;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007106 if (const auto *PTy = BaseTy->getAs<PointerType>()) {
Samuel Antao86ace552016-04-27 22:40:57 +00007107 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007108 } else {
7109 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr());
Samuel Antao86ace552016-04-27 22:40:57 +00007110 assert(ATy && "Expecting array type if not a pointer type.");
7111 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType());
7112 }
7113
7114 // If we don't have a length at this point, that is because we have an
7115 // array section with a single element.
7116 if (!OAE->getLength())
7117 return ElemSize;
7118
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007119 llvm::Value *LengthVal = CGF.EmitScalarExpr(OAE->getLength());
Samuel Antao86ace552016-04-27 22:40:57 +00007120 LengthVal =
7121 CGF.Builder.CreateIntCast(LengthVal, CGF.SizeTy, /*isSigned=*/false);
7122 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize);
7123 }
7124 return CGF.getTypeSize(ExprTy);
7125 }
7126
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007127 /// Return the corresponding bits for a given map clause modifier. Add
Samuel Antao86ace552016-04-27 22:40:57 +00007128 /// a flag marking the map as a pointer if requested. Add a flag marking the
Samuel Antao6782e942016-05-26 16:48:10 +00007129 /// map as the first one of a series of maps that relate to the same map
7130 /// expression.
Kelvin Lief579432018-12-18 22:18:41 +00007131 OpenMPOffloadMappingFlags getMapTypeBits(
7132 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers,
7133 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const {
Alexey Bataevb3638132018-07-19 16:34:13 +00007134 OpenMPOffloadMappingFlags Bits =
7135 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE;
Samuel Antao86ace552016-04-27 22:40:57 +00007136 switch (MapType) {
7137 case OMPC_MAP_alloc:
Samuel Antao6782e942016-05-26 16:48:10 +00007138 case OMPC_MAP_release:
7139 // alloc and release is the default behavior in the runtime library, i.e.
7140 // if we don't pass any bits alloc/release that is what the runtime is
7141 // going to do. Therefore, we don't need to signal anything for these two
7142 // type modifiers.
Samuel Antao86ace552016-04-27 22:40:57 +00007143 break;
7144 case OMPC_MAP_to:
Alexey Bataevb3638132018-07-19 16:34:13 +00007145 Bits |= OMP_MAP_TO;
Samuel Antao86ace552016-04-27 22:40:57 +00007146 break;
7147 case OMPC_MAP_from:
Alexey Bataevb3638132018-07-19 16:34:13 +00007148 Bits |= OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007149 break;
7150 case OMPC_MAP_tofrom:
Alexey Bataevb3638132018-07-19 16:34:13 +00007151 Bits |= OMP_MAP_TO | OMP_MAP_FROM;
Samuel Antao86ace552016-04-27 22:40:57 +00007152 break;
7153 case OMPC_MAP_delete:
Alexey Bataevb3638132018-07-19 16:34:13 +00007154 Bits |= OMP_MAP_DELETE;
Samuel Antao86ace552016-04-27 22:40:57 +00007155 break;
Alexey Bataevb3638132018-07-19 16:34:13 +00007156 case OMPC_MAP_unknown:
Samuel Antao86ace552016-04-27 22:40:57 +00007157 llvm_unreachable("Unexpected map type!");
Samuel Antao86ace552016-04-27 22:40:57 +00007158 }
7159 if (AddPtrFlag)
George Rokos065755d2017-11-07 18:27:04 +00007160 Bits |= OMP_MAP_PTR_AND_OBJ;
7161 if (AddIsTargetParamFlag)
7162 Bits |= OMP_MAP_TARGET_PARAM;
Kelvin Lief579432018-12-18 22:18:41 +00007163 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always)
7164 != MapModifiers.end())
Samuel Antao86ace552016-04-27 22:40:57 +00007165 Bits |= OMP_MAP_ALWAYS;
7166 return Bits;
7167 }
7168
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007169 /// Return true if the provided expression is a final array section. A
Samuel Antao86ace552016-04-27 22:40:57 +00007170 /// final array section, is one whose length can't be proved to be one.
7171 bool isFinalArraySectionExpression(const Expr *E) const {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007172 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E);
Samuel Antao86ace552016-04-27 22:40:57 +00007173
7174 // It is not an array section and therefore not a unity-size one.
7175 if (!OASE)
7176 return false;
7177
7178 // An array section with no colon always refer to a single element.
7179 if (OASE->getColonLoc().isInvalid())
7180 return false;
7181
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007182 const Expr *Length = OASE->getLength();
Samuel Antao86ace552016-04-27 22:40:57 +00007183
7184 // If we don't have a length we have to check if the array has size 1
7185 // for this dimension. Also, we should always expect a length if the
7186 // base type is pointer.
7187 if (!Length) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007188 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType(
7189 OASE->getBase()->IgnoreParenImpCasts())
7190 .getCanonicalType();
7191 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
Samuel Antao86ace552016-04-27 22:40:57 +00007192 return ATy->getSize().getSExtValue() != 1;
7193 // If we don't have a constant dimension length, we have to consider
7194 // the current section as having any size, so it is not necessarily
7195 // unitary. If it happen to be unity size, that's user fault.
7196 return true;
7197 }
7198
7199 // Check if the length evaluates to 1.
Fangrui Song407659a2018-11-30 23:41:18 +00007200 Expr::EvalResult Result;
7201 if (!Length->EvaluateAsInt(Result, CGF.getContext()))
Samuel Antao86ace552016-04-27 22:40:57 +00007202 return true; // Can have more that size 1.
7203
Fangrui Song407659a2018-11-30 23:41:18 +00007204 llvm::APSInt ConstLength = Result.Val.getInt();
Samuel Antao86ace552016-04-27 22:40:57 +00007205 return ConstLength.getSExtValue() != 1;
7206 }
7207
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007208 /// Generate the base pointers, section pointers, sizes and map type
Samuel Antao86ace552016-04-27 22:40:57 +00007209 /// bits for the provided map type, map modifier, and expression components.
7210 /// \a IsFirstComponent should be set to true if the provided set of
7211 /// components is the first associated with a capture.
7212 void generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00007213 OpenMPMapClauseKind MapType,
7214 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Samuel Antao86ace552016-04-27 22:40:57 +00007215 OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
Samuel Antaocc10b852016-07-28 14:23:26 +00007216 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007217 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
Alexey Bataevb3638132018-07-19 16:34:13 +00007218 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007219 bool IsImplicit,
7220 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
7221 OverlappedElements = llvm::None) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007222 // The following summarizes what has to be generated for each map and the
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00007223 // types below. The generated information is expressed in this order:
Samuel Antao86ace552016-04-27 22:40:57 +00007224 // base pointer, section pointer, size, flags
7225 // (to add to the ones that come from the map type and modifier).
7226 //
7227 // double d;
7228 // int i[100];
7229 // float *p;
7230 //
7231 // struct S1 {
7232 // int i;
7233 // float f[50];
7234 // }
7235 // struct S2 {
7236 // int i;
7237 // float f[50];
7238 // S1 s;
7239 // double *p;
7240 // struct S2 *ps;
7241 // }
7242 // S2 s;
7243 // S2 *ps;
7244 //
7245 // map(d)
Alexey Bataevb3638132018-07-19 16:34:13 +00007246 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007247 //
7248 // map(i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007249 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007250 //
7251 // map(i[1:23])
Alexey Bataevb3638132018-07-19 16:34:13 +00007252 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007253 //
7254 // map(p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007255 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007256 //
7257 // map(p[1:24])
Alexey Bataevb3638132018-07-19 16:34:13 +00007258 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007259 //
7260 // map(s)
Alexey Bataevb3638132018-07-19 16:34:13 +00007261 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007262 //
7263 // map(s.i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007264 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007265 //
7266 // map(s.s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007267 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007268 //
7269 // map(s.p)
Alexey Bataevb3638132018-07-19 16:34:13 +00007270 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007271 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007272 // map(to: s.p[:22])
7273 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*)
7274 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**)
7275 // &(s.p), &(s.p[0]), 22*sizeof(double),
7276 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***)
7277 // (*) alloc space for struct members, only this is a target parameter
7278 // (**) map the pointer (nothing to be mapped in this example) (the compiler
7279 // optimizes this entry out, same in the examples below)
7280 // (***) map the pointee (map: to)
Samuel Antao86ace552016-04-27 22:40:57 +00007281 //
7282 // map(s.ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007283 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007284 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007285 // map(from: s.ps->s.i)
7286 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7287 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7288 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007289 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007290 // map(to: s.ps->ps)
7291 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7292 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7293 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007294 //
7295 // map(s.ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007296 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7297 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7298 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7299 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007300 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007301 // map(to: s.ps->ps->s.f[:22])
7302 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM
7303 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1)
7304 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7305 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007306 //
7307 // map(ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007308 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007309 //
7310 // map(ps->i)
Alexey Bataevb3638132018-07-19 16:34:13 +00007311 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007312 //
7313 // map(ps->s.f)
Alexey Bataevb3638132018-07-19 16:34:13 +00007314 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007315 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007316 // map(from: ps->p)
7317 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007318 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007319 // map(to: ps->p[:22])
7320 // ps, &(ps->p), sizeof(double*), TARGET_PARAM
7321 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1)
7322 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO
Samuel Antao86ace552016-04-27 22:40:57 +00007323 //
7324 // map(ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007325 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007326 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007327 // map(from: ps->ps->s.i)
7328 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7329 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7330 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007331 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007332 // map(from: ps->ps->ps)
7333 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7334 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7335 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007336 //
7337 // map(ps->ps->ps->ps)
Alexey Bataevb3638132018-07-19 16:34:13 +00007338 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7339 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7340 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7341 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM
Samuel Antao86ace552016-04-27 22:40:57 +00007342 //
Alexey Bataevb3638132018-07-19 16:34:13 +00007343 // map(to: ps->ps->ps->s.f[:22])
7344 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM
7345 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1)
7346 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ
7347 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO
7348 //
7349 // map(to: s.f[:22]) map(from: s.p[:33])
7350 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) +
7351 // sizeof(double*) (**), TARGET_PARAM
7352 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO
7353 // &s, &(s.p), sizeof(double*), MEMBER_OF(1)
7354 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM
7355 // (*) allocate contiguous space needed to fit all mapped members even if
7356 // we allocate space for members not mapped (in this example,
7357 // s.f[22..49] and s.s are not mapped, yet we must allocate space for
7358 // them as well because they fall between &s.f[0] and &s.p)
7359 //
7360 // map(from: s.f[:22]) map(to: ps->p[:33])
7361 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM
7362 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7363 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*)
7364 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO
7365 // (*) the struct this entry pertains to is the 2nd element in the list of
7366 // arguments, hence MEMBER_OF(2)
7367 //
7368 // map(from: s.f[:22], s.s) map(to: ps->p[:33])
7369 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM
7370 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM
7371 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM
7372 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM
7373 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*)
7374 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO
7375 // (*) the struct this entry pertains to is the 4th element in the list
7376 // of arguments, hence MEMBER_OF(4)
Samuel Antao86ace552016-04-27 22:40:57 +00007377
7378 // Track if the map information being generated is the first for a capture.
7379 bool IsCaptureFirstInfo = IsFirstComponentList;
Alexey Bataev92327c52018-03-26 16:40:55 +00007380 bool IsLink = false; // Is this variable a "declare target link"?
Samuel Antao86ace552016-04-27 22:40:57 +00007381
7382 // Scan the components from the base to the complete expression.
7383 auto CI = Components.rbegin();
7384 auto CE = Components.rend();
7385 auto I = CI;
7386
7387 // Track if the map information being generated is the first for a list of
7388 // components.
7389 bool IsExpressionFirstInfo = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00007390 Address BP = Address::invalid();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007391 const Expr *AssocExpr = I->getAssociatedExpression();
7392 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr);
7393 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr);
Samuel Antao86ace552016-04-27 22:40:57 +00007394
Patrick Lystere13b1e32019-01-02 19:28:48 +00007395 if (isa<MemberExpr>(AssocExpr)) {
Samuel Antao86ace552016-04-27 22:40:57 +00007396 // The base is the 'this' pointer. The content of the pointer is going
7397 // to be the base of the field being mapped.
Alexey Bataevb3638132018-07-19 16:34:13 +00007398 BP = CGF.LoadCXXThisAddress();
Patrick Lystere13b1e32019-01-02 19:28:48 +00007399 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) ||
7400 (OASE &&
7401 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) {
7402 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
Samuel Antao86ace552016-04-27 22:40:57 +00007403 } else {
7404 // The base is the reference to the variable.
7405 // BP = &Var.
Patrick Lystere13b1e32019-01-02 19:28:48 +00007406 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress();
Alexey Bataev92327c52018-03-26 16:40:55 +00007407 if (const auto *VD =
7408 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) {
7409 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00007410 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD))
Alexey Bataev2c1dffe2018-04-16 20:34:41 +00007411 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) {
7412 IsLink = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00007413 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetLink(VD);
Alexey Bataev2c1dffe2018-04-16 20:34:41 +00007414 }
Alexey Bataev92327c52018-03-26 16:40:55 +00007415 }
Samuel Antao86ace552016-04-27 22:40:57 +00007416
7417 // If the variable is a pointer and is being dereferenced (i.e. is not
Nico Webera6916892016-06-10 18:53:04 +00007418 // the last component), the base has to be the pointer itself, not its
Samuel Antao403ffd42016-07-27 22:49:49 +00007419 // reference. References are ignored for mapping purposes.
7420 QualType Ty =
7421 I->getAssociatedDeclaration()->getType().getNonReferenceType();
7422 if (Ty->isAnyPointerType() && std::next(I) != CE) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007423 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>());
Samuel Antao86ace552016-04-27 22:40:57 +00007424
7425 // We do not need to generate individual map information for the
7426 // pointer, it can be associated with the combined storage.
7427 ++I;
7428 }
7429 }
7430
Alexey Bataevb3638132018-07-19 16:34:13 +00007431 // Track whether a component of the list should be marked as MEMBER_OF some
7432 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry
7433 // in a component list should be marked as MEMBER_OF, all subsequent entries
7434 // do not belong to the base struct. E.g.
7435 // struct S2 s;
7436 // s.ps->ps->ps->f[:]
7437 // (1) (2) (3) (4)
7438 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a
7439 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3)
7440 // is the pointee of ps(2) which is not member of struct s, so it should not
7441 // be marked as such (it is still PTR_AND_OBJ).
7442 // The variable is initialized to false so that PTR_AND_OBJ entries which
7443 // are not struct members are not considered (e.g. array of pointers to
7444 // data).
7445 bool ShouldBeMemberOf = false;
7446
7447 // Variable keeping track of whether or not we have encountered a component
7448 // in the component list which is a member expression. Useful when we have a
7449 // pointer or a final array section, in which case it is the previous
7450 // component in the list which tells us whether we have a member expression.
7451 // E.g. X.f[:]
7452 // While processing the final array section "[:]" it is "f" which tells us
7453 // whether we are dealing with a member of a declared struct.
7454 const MemberExpr *EncounteredME = nullptr;
7455
Samuel Antao86ace552016-04-27 22:40:57 +00007456 for (; I != CE; ++I) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007457 // If the current component is member of a struct (parent struct) mark it.
7458 if (!EncounteredME) {
7459 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression());
7460 // If we encounter a PTR_AND_OBJ entry from now on it should be marked
7461 // as MEMBER_OF the parent struct.
7462 if (EncounteredME)
7463 ShouldBeMemberOf = true;
7464 }
7465
Samuel Antao86ace552016-04-27 22:40:57 +00007466 auto Next = std::next(I);
7467
7468 // We need to generate the addresses and sizes if this is the last
7469 // component, if the component is a pointer or if it is an array section
7470 // whose length can't be proved to be one. If this is a pointer, it
7471 // becomes the base address for the following components.
7472
7473 // A final array section, is one whose length can't be proved to be one.
7474 bool IsFinalArraySection =
7475 isFinalArraySectionExpression(I->getAssociatedExpression());
7476
7477 // Get information on whether the element is a pointer. Have to do a
7478 // special treatment for array sections given that they are built-in
7479 // types.
7480 const auto *OASE =
7481 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression());
7482 bool IsPointer =
Alexey Bataevb3638132018-07-19 16:34:13 +00007483 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE)
7484 .getCanonicalType()
7485 ->isAnyPointerType()) ||
Samuel Antao86ace552016-04-27 22:40:57 +00007486 I->getAssociatedExpression()->getType()->isAnyPointerType();
7487
7488 if (Next == CE || IsPointer || IsFinalArraySection) {
Samuel Antao86ace552016-04-27 22:40:57 +00007489 // If this is not the last component, we expect the pointer to be
7490 // associated with an array expression or member expression.
7491 assert((Next == CE ||
7492 isa<MemberExpr>(Next->getAssociatedExpression()) ||
7493 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) ||
7494 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) &&
7495 "Unexpected expression");
7496
Alexey Bataevb3638132018-07-19 16:34:13 +00007497 Address LB =
7498 CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getAddress();
Samuel Antao86ace552016-04-27 22:40:57 +00007499
Alexey Bataevb3638132018-07-19 16:34:13 +00007500 // If this component is a pointer inside the base struct then we don't
7501 // need to create any entry for it - it will be combined with the object
7502 // it is pointing to into a single PTR_AND_OBJ entry.
7503 bool IsMemberPointer =
7504 IsPointer && EncounteredME &&
7505 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) ==
7506 EncounteredME);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007507 if (!OverlappedElements.empty()) {
7508 // Handle base element with the info for overlapped elements.
7509 assert(!PartialStruct.Base.isValid() && "The base element is set.");
7510 assert(Next == CE &&
7511 "Expected last element for the overlapped elements.");
7512 assert(!IsPointer &&
7513 "Unexpected base element with the pointer type.");
7514 // Mark the whole struct as the struct that requires allocation on the
7515 // device.
7516 PartialStruct.LowestElem = {0, LB};
7517 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars(
7518 I->getAssociatedExpression()->getType());
7519 Address HB = CGF.Builder.CreateConstGEP(
7520 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB,
7521 CGF.VoidPtrTy),
James Y Knight751fe282019-02-09 22:22:28 +00007522 TypeSize.getQuantity() - 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007523 PartialStruct.HighestElem = {
7524 std::numeric_limits<decltype(
7525 PartialStruct.HighestElem.first)>::max(),
7526 HB};
7527 PartialStruct.Base = BP;
7528 // Emit data for non-overlapped data.
7529 OpenMPOffloadMappingFlags Flags =
7530 OMP_MAP_MEMBER_OF |
Kelvin Lief579432018-12-18 22:18:41 +00007531 getMapTypeBits(MapType, MapModifiers, IsImplicit,
Alexey Bataeve82445f2018-09-20 13:54:02 +00007532 /*AddPtrFlag=*/false,
7533 /*AddIsTargetParamFlag=*/false);
7534 LB = BP;
7535 llvm::Value *Size = nullptr;
7536 // Do bitcopy of all non-overlapped structure elements.
7537 for (OMPClauseMappableExprCommon::MappableExprComponentListRef
7538 Component : OverlappedElements) {
7539 Address ComponentLB = Address::invalid();
7540 for (const OMPClauseMappableExprCommon::MappableComponent &MC :
7541 Component) {
7542 if (MC.getAssociatedDeclaration()) {
7543 ComponentLB =
7544 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression())
7545 .getAddress();
7546 Size = CGF.Builder.CreatePtrDiff(
7547 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()),
7548 CGF.EmitCastToVoidPtr(LB.getPointer()));
7549 break;
7550 }
7551 }
7552 BasePointers.push_back(BP.getPointer());
7553 Pointers.push_back(LB.getPointer());
7554 Sizes.push_back(Size);
7555 Types.push_back(Flags);
James Y Knight751fe282019-02-09 22:22:28 +00007556 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1);
Alexey Bataeve82445f2018-09-20 13:54:02 +00007557 }
7558 BasePointers.push_back(BP.getPointer());
7559 Pointers.push_back(LB.getPointer());
7560 Size = CGF.Builder.CreatePtrDiff(
7561 CGF.EmitCastToVoidPtr(
James Y Knight751fe282019-02-09 22:22:28 +00007562 CGF.Builder.CreateConstGEP(HB, 1).getPointer()),
Alexey Bataeve82445f2018-09-20 13:54:02 +00007563 CGF.EmitCastToVoidPtr(LB.getPointer()));
7564 Sizes.push_back(Size);
7565 Types.push_back(Flags);
7566 break;
7567 }
7568 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression());
Alexey Bataevb3638132018-07-19 16:34:13 +00007569 if (!IsMemberPointer) {
7570 BasePointers.push_back(BP.getPointer());
7571 Pointers.push_back(LB.getPointer());
7572 Sizes.push_back(Size);
Samuel Antao03a3cec2016-07-27 22:52:16 +00007573
Alexey Bataevb3638132018-07-19 16:34:13 +00007574 // We need to add a pointer flag for each map that comes from the
7575 // same expression except for the first one. We also need to signal
7576 // this map is the first one that relates with the current capture
7577 // (there is a set of entries for each capture).
7578 OpenMPOffloadMappingFlags Flags = getMapTypeBits(
Kelvin Lief579432018-12-18 22:18:41 +00007579 MapType, MapModifiers, IsImplicit,
Alexey Bataevb3638132018-07-19 16:34:13 +00007580 !IsExpressionFirstInfo || IsLink, IsCaptureFirstInfo && !IsLink);
7581
7582 if (!IsExpressionFirstInfo) {
7583 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well,
7584 // then we reset the TO/FROM/ALWAYS/DELETE flags.
7585 if (IsPointer)
7586 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS |
7587 OMP_MAP_DELETE);
7588
7589 if (ShouldBeMemberOf) {
7590 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag
7591 // should be later updated with the correct value of MEMBER_OF.
7592 Flags |= OMP_MAP_MEMBER_OF;
7593 // From now on, all subsequent PTR_AND_OBJ entries should not be
7594 // marked as MEMBER_OF.
7595 ShouldBeMemberOf = false;
7596 }
7597 }
7598
7599 Types.push_back(Flags);
Samuel Antao03a3cec2016-07-27 22:52:16 +00007600 }
7601
Alexey Bataevb3638132018-07-19 16:34:13 +00007602 // If we have encountered a member expression so far, keep track of the
7603 // mapped member. If the parent is "*this", then the value declaration
7604 // is nullptr.
7605 if (EncounteredME) {
7606 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl());
7607 unsigned FieldIndex = FD->getFieldIndex();
Samuel Antao03a3cec2016-07-27 22:52:16 +00007608
Alexey Bataevb3638132018-07-19 16:34:13 +00007609 // Update info about the lowest and highest elements for this struct
7610 if (!PartialStruct.Base.isValid()) {
7611 PartialStruct.LowestElem = {FieldIndex, LB};
7612 PartialStruct.HighestElem = {FieldIndex, LB};
7613 PartialStruct.Base = BP;
7614 } else if (FieldIndex < PartialStruct.LowestElem.first) {
7615 PartialStruct.LowestElem = {FieldIndex, LB};
7616 } else if (FieldIndex > PartialStruct.HighestElem.first) {
7617 PartialStruct.HighestElem = {FieldIndex, LB};
7618 }
7619 }
Samuel Antao86ace552016-04-27 22:40:57 +00007620
7621 // If we have a final array section, we are done with this expression.
7622 if (IsFinalArraySection)
7623 break;
7624
7625 // The pointer becomes the base for the next element.
7626 if (Next != CE)
7627 BP = LB;
7628
7629 IsExpressionFirstInfo = false;
7630 IsCaptureFirstInfo = false;
Samuel Antao86ace552016-04-27 22:40:57 +00007631 }
7632 }
7633 }
7634
Alexey Bataevb3638132018-07-19 16:34:13 +00007635 /// Return the adjusted map modifiers if the declaration a capture refers to
7636 /// appears in a first-private clause. This is expected to be used only with
7637 /// directives that start with 'target'.
7638 MappableExprsHandler::OpenMPOffloadMappingFlags
7639 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const {
7640 assert(Cap.capturesVariable() && "Expected capture by reference only!");
7641
7642 // A first private variable captured by reference will use only the
7643 // 'private ptr' and 'map to' flag. Return the right flags if the captured
7644 // declaration is known as first-private in this handler.
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007645 if (FirstPrivateDecls.count(Cap.getCapturedVar())) {
7646 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) &&
7647 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef)
7648 return MappableExprsHandler::OMP_MAP_ALWAYS |
7649 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataevc2b831f2019-04-02 16:03:40 +00007650 if (Cap.getCapturedVar()->getType()->isAnyPointerType())
7651 return MappableExprsHandler::OMP_MAP_TO |
7652 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ;
Alexey Bataevb3638132018-07-19 16:34:13 +00007653 return MappableExprsHandler::OMP_MAP_PRIVATE |
7654 MappableExprsHandler::OMP_MAP_TO;
Alexey Bataev1af5bd52019-03-05 17:47:18 +00007655 }
Alexey Bataevb3638132018-07-19 16:34:13 +00007656 return MappableExprsHandler::OMP_MAP_TO |
7657 MappableExprsHandler::OMP_MAP_FROM;
7658 }
7659
7660 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) {
7661 // Member of is given by the 16 MSB of the flag, so rotate by 48 bits.
7662 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1)
7663 << 48);
7664 }
7665
7666 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags,
7667 OpenMPOffloadMappingFlags MemberOfFlag) {
7668 // If the entry is PTR_AND_OBJ but has not been marked with the special
7669 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be
7670 // marked as MEMBER_OF.
7671 if ((Flags & OMP_MAP_PTR_AND_OBJ) &&
7672 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF))
7673 return;
7674
7675 // Reset the placeholder value to prepare the flag for the assignment of the
7676 // proper MEMBER_OF value.
7677 Flags &= ~OMP_MAP_MEMBER_OF;
7678 Flags |= MemberOfFlag;
7679 }
7680
Alexey Bataeve82445f2018-09-20 13:54:02 +00007681 void getPlainLayout(const CXXRecordDecl *RD,
7682 llvm::SmallVectorImpl<const FieldDecl *> &Layout,
7683 bool AsBase) const {
7684 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD);
7685
7686 llvm::StructType *St =
7687 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType();
7688
7689 unsigned NumElements = St->getNumElements();
7690 llvm::SmallVector<
7691 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4>
7692 RecordLayout(NumElements);
7693
7694 // Fill bases.
7695 for (const auto &I : RD->bases()) {
7696 if (I.isVirtual())
7697 continue;
7698 const auto *Base = I.getType()->getAsCXXRecordDecl();
7699 // Ignore empty bases.
7700 if (Base->isEmpty() || CGF.getContext()
7701 .getASTRecordLayout(Base)
7702 .getNonVirtualSize()
7703 .isZero())
7704 continue;
7705
7706 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base);
7707 RecordLayout[FieldIndex] = Base;
7708 }
7709 // Fill in virtual bases.
7710 for (const auto &I : RD->vbases()) {
7711 const auto *Base = I.getType()->getAsCXXRecordDecl();
7712 // Ignore empty bases.
7713 if (Base->isEmpty())
7714 continue;
7715 unsigned FieldIndex = RL.getVirtualBaseIndex(Base);
7716 if (RecordLayout[FieldIndex])
7717 continue;
7718 RecordLayout[FieldIndex] = Base;
7719 }
7720 // Fill in all the fields.
7721 assert(!RD->isUnion() && "Unexpected union.");
7722 for (const auto *Field : RD->fields()) {
7723 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
7724 // will fill in later.)
7725 if (!Field->isBitField()) {
7726 unsigned FieldIndex = RL.getLLVMFieldNo(Field);
7727 RecordLayout[FieldIndex] = Field;
7728 }
7729 }
7730 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>
7731 &Data : RecordLayout) {
7732 if (Data.isNull())
7733 continue;
7734 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>())
7735 getPlainLayout(Base, Layout, /*AsBase=*/true);
7736 else
7737 Layout.push_back(Data.get<const FieldDecl *>());
7738 }
7739 }
7740
Alexey Bataevb3638132018-07-19 16:34:13 +00007741public:
7742 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF)
7743 : CurDir(Dir), CGF(CGF) {
7744 // Extract firstprivate clause information.
7745 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>())
7746 for (const auto *D : C->varlists())
7747 FirstPrivateDecls.insert(
7748 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl());
7749 // Extract device pointer clause information.
7750 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>())
7751 for (auto L : C->component_lists())
7752 DevPointersMap[L.first].push_back(L.second);
7753 }
7754
7755 /// Generate code for the combined entry if we have a partially mapped struct
7756 /// and take care of the mapping flags of the arguments corresponding to
7757 /// individual struct members.
7758 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers,
7759 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7760 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes,
7761 const StructRangeInfoTy &PartialStruct) const {
7762 // Base is the base of the struct
7763 BasePointers.push_back(PartialStruct.Base.getPointer());
7764 // Pointer is the address of the lowest element
7765 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer();
7766 Pointers.push_back(LB);
7767 // Size is (addr of {highest+1} element) - (addr of lowest element)
7768 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer();
7769 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1);
7770 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy);
7771 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy);
7772 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr);
7773 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.SizeTy,
7774 /*isSinged=*/false);
7775 Sizes.push_back(Size);
7776 // Map type is always TARGET_PARAM
7777 Types.push_back(OMP_MAP_TARGET_PARAM);
7778 // Remove TARGET_PARAM flag from the first element
7779 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM;
7780
7781 // All other current entries will be MEMBER_OF the combined entry
7782 // (except for PTR_AND_OBJ entries which do not have a placeholder value
7783 // 0xFFFF in the MEMBER_OF field).
7784 OpenMPOffloadMappingFlags MemberOfFlag =
7785 getMemberOfFlag(BasePointers.size() - 1);
7786 for (auto &M : CurTypes)
7787 setCorrectMemberOfFlag(M, MemberOfFlag);
7788 }
7789
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007790 /// Generate all the base pointers, section pointers, sizes and map
Samuel Antaocc10b852016-07-28 14:23:26 +00007791 /// types for the extracted mappable expressions. Also, for each item that
7792 /// relates with a device pointer, a pair of the relevant declaration and
7793 /// index where it occurs is appended to the device pointers info array.
7794 void generateAllInfo(MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00007795 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7796 MapFlagsArrayTy &Types) const {
Samuel Antao86ace552016-04-27 22:40:57 +00007797 // We have to process the component lists that relate with the same
7798 // declaration in a single chunk so that we can generate the map flags
7799 // correctly. Therefore, we organize all lists in a map.
Alexey Bataev5d1c3f62017-06-27 15:46:42 +00007800 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info;
Samuel Antao8d2d7302016-05-26 18:30:22 +00007801
7802 // Helper function to fill the information map for the different supported
7803 // clauses.
Samuel Antaocc10b852016-07-28 14:23:26 +00007804 auto &&InfoGen = [&Info](
7805 const ValueDecl *D,
7806 OMPClauseMappableExprCommon::MappableExprComponentListRef L,
Kelvin Lief579432018-12-18 22:18:41 +00007807 OpenMPMapClauseKind MapType,
7808 ArrayRef<OpenMPMapModifierKind> MapModifiers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007809 bool ReturnDevicePointer, bool IsImplicit) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007810 const ValueDecl *VD =
7811 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr;
Kelvin Lief579432018-12-18 22:18:41 +00007812 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer,
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007813 IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00007814 };
Samuel Antao8d2d7302016-05-26 18:30:22 +00007815
Paul Robinson78fb1322016-08-01 22:12:46 +00007816 // FIXME: MSVC 2013 seems to require this-> to find member CurDir.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007817 for (const auto *C : this->CurDir.getClausesOfKind<OMPMapClause>())
7818 for (const auto &L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007819 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(),
Alexey Bataevb3638132018-07-19 16:34:13 +00007820 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007821 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007822 for (const auto *C : this->CurDir.getClausesOfKind<OMPToClause>())
7823 for (const auto &L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007824 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007825 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007826 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007827 for (const auto *C : this->CurDir.getClausesOfKind<OMPFromClause>())
7828 for (const auto &L : C->component_lists()) {
Kelvin Lief579432018-12-18 22:18:41 +00007829 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007830 /*ReturnDevicePointer=*/false, C->isImplicit());
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007831 }
Samuel Antao86ace552016-04-27 22:40:57 +00007832
Samuel Antaocc10b852016-07-28 14:23:26 +00007833 // Look at the use_device_ptr clause information and mark the existing map
7834 // entries as such. If there is no map information for an entry in the
7835 // use_device_ptr list, we create one with map type 'alloc' and zero size
Alexey Bataevb3638132018-07-19 16:34:13 +00007836 // section. It is the user fault if that was not mapped before. If there is
7837 // no map information and the pointer is a struct member, then we defer the
7838 // emission of that entry until the whole struct has been processed.
7839 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>>
7840 DeferredInfo;
7841
Paul Robinson78fb1322016-08-01 22:12:46 +00007842 // FIXME: MSVC 2013 seems to require this-> to find member CurDir.
Alexey Bataevb3638132018-07-19 16:34:13 +00007843 for (const auto *C :
7844 this->CurDir.getClausesOfKind<OMPUseDevicePtrClause>()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007845 for (const auto &L : C->component_lists()) {
Samuel Antaocc10b852016-07-28 14:23:26 +00007846 assert(!L.second.empty() && "Not expecting empty list of components!");
7847 const ValueDecl *VD = L.second.back().getAssociatedDeclaration();
7848 VD = cast<ValueDecl>(VD->getCanonicalDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007849 const Expr *IE = L.second.back().getAssociatedExpression();
Samuel Antaocc10b852016-07-28 14:23:26 +00007850 // If the first component is a member expression, we have to look into
7851 // 'this', which maps to null in the map of map information. Otherwise
7852 // look directly for the information.
7853 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD);
7854
7855 // We potentially have map information for this declaration already.
7856 // Look for the first set of components that refer to it.
7857 if (It != Info.end()) {
7858 auto CI = std::find_if(
7859 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) {
7860 return MI.Components.back().getAssociatedDeclaration() == VD;
7861 });
7862 // If we found a map entry, signal that the pointer has to be returned
7863 // and move on to the next declaration.
7864 if (CI != It->second.end()) {
Alexey Bataevb3638132018-07-19 16:34:13 +00007865 CI->ReturnDevicePointer = true;
Samuel Antaocc10b852016-07-28 14:23:26 +00007866 continue;
7867 }
7868 }
7869
7870 // We didn't find any match in our map information - generate a zero
Alexey Bataevb3638132018-07-19 16:34:13 +00007871 // size array section - if the pointer is a struct member we defer this
7872 // action until the whole struct has been processed.
Paul Robinson78fb1322016-08-01 22:12:46 +00007873 // FIXME: MSVC 2013 seems to require this-> to find member CGF.
Alexey Bataevb3638132018-07-19 16:34:13 +00007874 if (isa<MemberExpr>(IE)) {
7875 // Insert the pointer into Info to be processed by
7876 // generateInfoForComponentList. Because it is a member pointer
7877 // without a pointee, no entry will be generated for it, therefore
7878 // we need to generate one after the whole struct has been processed.
7879 // Nonetheless, generateInfoForComponentList must be called to take
7880 // the pointer into account for the calculation of the range of the
7881 // partial struct.
Kelvin Lief579432018-12-18 22:18:41 +00007882 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None,
Alexey Bataevb3638132018-07-19 16:34:13 +00007883 /*ReturnDevicePointer=*/false, C->isImplicit());
7884 DeferredInfo[nullptr].emplace_back(IE, VD);
7885 } else {
7886 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar(
7887 this->CGF.EmitLValue(IE), IE->getExprLoc());
7888 BasePointers.emplace_back(Ptr, VD);
7889 Pointers.push_back(Ptr);
7890 Sizes.push_back(llvm::Constant::getNullValue(this->CGF.SizeTy));
7891 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM);
7892 }
Samuel Antaocc10b852016-07-28 14:23:26 +00007893 }
Alexey Bataevb3638132018-07-19 16:34:13 +00007894 }
Samuel Antaocc10b852016-07-28 14:23:26 +00007895
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007896 for (const auto &M : Info) {
Samuel Antao86ace552016-04-27 22:40:57 +00007897 // We need to know when we generate information for the first component
7898 // associated with a capture, because the mapping flags depend on it.
7899 bool IsFirstComponentList = true;
Alexey Bataevb3638132018-07-19 16:34:13 +00007900
7901 // Temporary versions of arrays
7902 MapBaseValuesArrayTy CurBasePointers;
7903 MapValuesArrayTy CurPointers;
7904 MapValuesArrayTy CurSizes;
7905 MapFlagsArrayTy CurTypes;
7906 StructRangeInfoTy PartialStruct;
7907
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007908 for (const MapInfo &L : M.second) {
Samuel Antao86ace552016-04-27 22:40:57 +00007909 assert(!L.Components.empty() &&
7910 "Not expecting declaration with no component lists.");
Samuel Antaocc10b852016-07-28 14:23:26 +00007911
7912 // Remember the current base pointer index.
Alexey Bataevb3638132018-07-19 16:34:13 +00007913 unsigned CurrentBasePointersIdx = CurBasePointers.size();
Paul Robinson78fb1322016-08-01 22:12:46 +00007914 // FIXME: MSVC 2013 seems to require this-> to find the member method.
Alexey Bataevf47c4b42017-09-26 13:47:31 +00007915 this->generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00007916 L.MapType, L.MapModifiers, L.Components, CurBasePointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00007917 CurPointers, CurSizes, CurTypes, PartialStruct,
7918 IsFirstComponentList, L.IsImplicit);
Samuel Antaocc10b852016-07-28 14:23:26 +00007919
7920 // If this entry relates with a device pointer, set the relevant
7921 // declaration and add the 'return pointer' flag.
Alexey Bataevb3638132018-07-19 16:34:13 +00007922 if (L.ReturnDevicePointer) {
7923 assert(CurBasePointers.size() > CurrentBasePointersIdx &&
Samuel Antaocc10b852016-07-28 14:23:26 +00007924 "Unexpected number of mapped base pointers.");
7925
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00007926 const ValueDecl *RelevantVD =
7927 L.Components.back().getAssociatedDeclaration();
Samuel Antaocc10b852016-07-28 14:23:26 +00007928 assert(RelevantVD &&
7929 "No relevant declaration related with device pointer??");
7930
Alexey Bataevb3638132018-07-19 16:34:13 +00007931 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD);
7932 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM;
Samuel Antaocc10b852016-07-28 14:23:26 +00007933 }
Samuel Antao86ace552016-04-27 22:40:57 +00007934 IsFirstComponentList = false;
7935 }
Alexey Bataevb3638132018-07-19 16:34:13 +00007936
7937 // Append any pending zero-length pointers which are struct members and
7938 // used with use_device_ptr.
7939 auto CI = DeferredInfo.find(M.first);
7940 if (CI != DeferredInfo.end()) {
7941 for (const DeferredDevicePtrEntryTy &L : CI->second) {
7942 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer();
7943 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar(
7944 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc());
7945 CurBasePointers.emplace_back(BasePtr, L.VD);
7946 CurPointers.push_back(Ptr);
7947 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.SizeTy));
7948 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder
7949 // value MEMBER_OF=FFFF so that the entry is later updated with the
7950 // correct value of MEMBER_OF.
7951 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM |
7952 OMP_MAP_MEMBER_OF);
7953 }
7954 }
7955
7956 // If there is an entry in PartialStruct it means we have a struct with
7957 // individual members mapped. Emit an extra combined entry.
7958 if (PartialStruct.Base.isValid())
7959 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes,
7960 PartialStruct);
7961
7962 // We need to append the results of this capture to what we already have.
7963 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
7964 Pointers.append(CurPointers.begin(), CurPointers.end());
7965 Sizes.append(CurSizes.begin(), CurSizes.end());
7966 Types.append(CurTypes.begin(), CurTypes.end());
Samuel Antao86ace552016-04-27 22:40:57 +00007967 }
7968 }
7969
Alexey Bataev60705422018-10-30 15:50:12 +00007970 /// Emit capture info for lambdas for variables captured by reference.
Alexey Bataev969dbc02018-11-08 15:47:39 +00007971 void generateInfoForLambdaCaptures(
7972 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers,
7973 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes,
7974 MapFlagsArrayTy &Types,
7975 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const {
Alexey Bataev60705422018-10-30 15:50:12 +00007976 const auto *RD = VD->getType()
7977 .getCanonicalType()
7978 .getNonReferenceType()
7979 ->getAsCXXRecordDecl();
7980 if (!RD || !RD->isLambda())
7981 return;
7982 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD));
7983 LValue VDLVal = CGF.MakeAddrLValue(
7984 VDAddr, VD->getType().getCanonicalType().getNonReferenceType());
7985 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures;
7986 FieldDecl *ThisCapture = nullptr;
7987 RD->getCaptureFields(Captures, ThisCapture);
7988 if (ThisCapture) {
7989 LValue ThisLVal =
7990 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture);
Alexey Bataev969dbc02018-11-08 15:47:39 +00007991 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture);
7992 LambdaPointers.try_emplace(ThisLVal.getPointer(), VDLVal.getPointer());
7993 BasePointers.push_back(ThisLVal.getPointer());
7994 Pointers.push_back(ThisLValVal.getPointer());
Alexey Bataev60705422018-10-30 15:50:12 +00007995 Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy));
Alexey Bataev2dc07d02018-11-02 15:25:06 +00007996 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00007997 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
7998 }
7999 for (const LambdaCapture &LC : RD->captures()) {
8000 if (LC.getCaptureKind() != LCK_ByRef)
8001 continue;
8002 const VarDecl *VD = LC.getCapturedVar();
8003 auto It = Captures.find(VD);
8004 assert(It != Captures.end() && "Found lambda capture without field.");
8005 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second);
Alexey Bataev969dbc02018-11-08 15:47:39 +00008006 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second);
8007 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer());
8008 BasePointers.push_back(VarLVal.getPointer());
8009 Pointers.push_back(VarLValVal.getPointer());
Alexey Bataev60705422018-10-30 15:50:12 +00008010 Sizes.push_back(CGF.getTypeSize(
8011 VD->getType().getCanonicalType().getNonReferenceType()));
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008012 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008013 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT);
8014 }
8015 }
8016
8017 /// Set correct indices for lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008018 void adjustMemberOfForLambdaCaptures(
8019 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers,
8020 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers,
8021 MapFlagsArrayTy &Types) const {
Alexey Bataev60705422018-10-30 15:50:12 +00008022 for (unsigned I = 0, E = Types.size(); I < E; ++I) {
8023 // Set correct member_of idx for all implicit lambda captures.
Alexey Bataev2dc07d02018-11-02 15:25:06 +00008024 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL |
Alexey Bataev60705422018-10-30 15:50:12 +00008025 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT))
8026 continue;
Alexey Bataev969dbc02018-11-08 15:47:39 +00008027 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]);
8028 assert(BasePtr && "Unable to find base lambda address.");
Alexey Bataev60705422018-10-30 15:50:12 +00008029 int TgtIdx = -1;
8030 for (unsigned J = I; J > 0; --J) {
8031 unsigned Idx = J - 1;
8032 if (Pointers[Idx] != BasePtr)
8033 continue;
8034 TgtIdx = Idx;
8035 break;
8036 }
8037 assert(TgtIdx != -1 && "Unable to find parent lambda.");
8038 // All other current entries will be MEMBER_OF the combined entry
8039 // (except for PTR_AND_OBJ entries which do not have a placeholder value
8040 // 0xFFFF in the MEMBER_OF field).
8041 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx);
8042 setCorrectMemberOfFlag(Types[I], MemberOfFlag);
8043 }
8044 }
8045
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008046 /// Generate the base pointers, section pointers, sizes and map types
Samuel Antao86ace552016-04-27 22:40:57 +00008047 /// associated to a given capture.
8048 void generateInfoForCapture(const CapturedStmt::Capture *Cap,
Samuel Antao6890b092016-07-28 14:25:09 +00008049 llvm::Value *Arg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008050 MapBaseValuesArrayTy &BasePointers,
Samuel Antao86ace552016-04-27 22:40:57 +00008051 MapValuesArrayTy &Pointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008052 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types,
8053 StructRangeInfoTy &PartialStruct) const {
Samuel Antao86ace552016-04-27 22:40:57 +00008054 assert(!Cap->capturesVariableArrayType() &&
8055 "Not expecting to generate map info for a variable array type!");
8056
Samuel Antao6890b092016-07-28 14:25:09 +00008057 // We need to know when we generating information for the first component
Alexey Bataevb3638132018-07-19 16:34:13 +00008058 const ValueDecl *VD = Cap->capturesThis()
8059 ? nullptr
8060 : Cap->getCapturedVar()->getCanonicalDecl();
Samuel Antao86ace552016-04-27 22:40:57 +00008061
Samuel Antao6890b092016-07-28 14:25:09 +00008062 // If this declaration appears in a is_device_ptr clause we just have to
8063 // pass the pointer by value. If it is a reference to a declaration, we just
Alexey Bataevb3638132018-07-19 16:34:13 +00008064 // pass its value.
8065 if (DevPointersMap.count(VD)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008066 BasePointers.emplace_back(Arg, VD);
Samuel Antao6890b092016-07-28 14:25:09 +00008067 Pointers.push_back(Arg);
8068 Sizes.push_back(CGF.getTypeSize(CGF.getContext().VoidPtrTy));
George Rokos065755d2017-11-07 18:27:04 +00008069 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM);
Samuel Antao6890b092016-07-28 14:25:09 +00008070 return;
8071 }
8072
Alexey Bataeve82445f2018-09-20 13:54:02 +00008073 using MapData =
8074 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef,
Kelvin Lief579432018-12-18 22:18:41 +00008075 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008076 SmallVector<MapData, 4> DeclComponentLists;
Paul Robinson78fb1322016-08-01 22:12:46 +00008077 // FIXME: MSVC 2013 seems to require this-> to find member CurDir.
Alexey Bataeve82445f2018-09-20 13:54:02 +00008078 for (const auto *C : this->CurDir.getClausesOfKind<OMPMapClause>()) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008079 for (const auto &L : C->decl_component_lists(VD)) {
Samuel Antao86ace552016-04-27 22:40:57 +00008080 assert(L.first == VD &&
8081 "We got information for the wrong declaration??");
8082 assert(!L.second.empty() &&
8083 "Not expecting declaration with no component lists.");
Alexey Bataeve82445f2018-09-20 13:54:02 +00008084 DeclComponentLists.emplace_back(L.second, C->getMapType(),
Kelvin Lief579432018-12-18 22:18:41 +00008085 C->getMapTypeModifiers(),
Alexey Bataeve82445f2018-09-20 13:54:02 +00008086 C->isImplicit());
Samuel Antao86ace552016-04-27 22:40:57 +00008087 }
Alexey Bataeve82445f2018-09-20 13:54:02 +00008088 }
8089
8090 // Find overlapping elements (including the offset from the base element).
8091 llvm::SmallDenseMap<
8092 const MapData *,
8093 llvm::SmallVector<
8094 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>,
8095 4>
8096 OverlappedData;
8097 size_t Count = 0;
8098 for (const MapData &L : DeclComponentLists) {
8099 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8100 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008101 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008102 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008103 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008104 ++Count;
8105 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) {
8106 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1;
Kelvin Lief579432018-12-18 22:18:41 +00008107 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008108 auto CI = Components.rbegin();
8109 auto CE = Components.rend();
8110 auto SI = Components1.rbegin();
8111 auto SE = Components1.rend();
8112 for (; CI != CE && SI != SE; ++CI, ++SI) {
8113 if (CI->getAssociatedExpression()->getStmtClass() !=
8114 SI->getAssociatedExpression()->getStmtClass())
8115 break;
8116 // Are we dealing with different variables/fields?
8117 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration())
8118 break;
8119 }
8120 // Found overlapping if, at least for one component, reached the head of
8121 // the components list.
8122 if (CI == CE || SI == SE) {
8123 assert((CI != CE || SI != SE) &&
8124 "Unexpected full match of the mapping components.");
8125 const MapData &BaseData = CI == CE ? L : L1;
8126 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData =
8127 SI == SE ? Components : Components1;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008128 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData);
8129 OverlappedElements.getSecond().push_back(SubData);
8130 }
8131 }
8132 }
8133 // Sort the overlapped elements for each item.
8134 llvm::SmallVector<const FieldDecl *, 4> Layout;
8135 if (!OverlappedData.empty()) {
8136 if (const auto *CRD =
8137 VD->getType().getCanonicalType()->getAsCXXRecordDecl())
8138 getPlainLayout(CRD, Layout, /*AsBase=*/false);
8139 else {
8140 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl();
8141 Layout.append(RD->field_begin(), RD->field_end());
8142 }
8143 }
8144 for (auto &Pair : OverlappedData) {
8145 llvm::sort(
8146 Pair.getSecond(),
8147 [&Layout](
8148 OMPClauseMappableExprCommon::MappableExprComponentListRef First,
8149 OMPClauseMappableExprCommon::MappableExprComponentListRef
8150 Second) {
8151 auto CI = First.rbegin();
8152 auto CE = First.rend();
8153 auto SI = Second.rbegin();
8154 auto SE = Second.rend();
8155 for (; CI != CE && SI != SE; ++CI, ++SI) {
8156 if (CI->getAssociatedExpression()->getStmtClass() !=
8157 SI->getAssociatedExpression()->getStmtClass())
8158 break;
8159 // Are we dealing with different variables/fields?
8160 if (CI->getAssociatedDeclaration() !=
8161 SI->getAssociatedDeclaration())
8162 break;
8163 }
Richard Trieu5061e832018-09-21 21:20:33 +00008164
8165 // Lists contain the same elements.
8166 if (CI == CE && SI == SE)
8167 return false;
8168
8169 // List with less elements is less than list with more elements.
8170 if (CI == CE || SI == SE)
8171 return CI == CE;
8172
Alexey Bataeve82445f2018-09-20 13:54:02 +00008173 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration());
8174 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration());
8175 if (FD1->getParent() == FD2->getParent())
8176 return FD1->getFieldIndex() < FD2->getFieldIndex();
8177 const auto It =
8178 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) {
8179 return FD == FD1 || FD == FD2;
8180 });
8181 return *It == FD1;
8182 });
8183 }
8184
8185 // Associated with a capture, because the mapping flags depend on it.
8186 // Go through all of the elements with the overlapped elements.
8187 for (const auto &Pair : OverlappedData) {
8188 const MapData &L = *Pair.getFirst();
8189 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8190 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008191 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008192 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008193 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008194 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef>
8195 OverlappedComponents = Pair.getSecond();
8196 bool IsFirstComponentList = true;
Kelvin Lief579432018-12-18 22:18:41 +00008197 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008198 BasePointers, Pointers, Sizes, Types,
8199 PartialStruct, IsFirstComponentList,
8200 IsImplicit, OverlappedComponents);
8201 }
8202 // Go through other elements without overlapped elements.
8203 bool IsFirstComponentList = OverlappedData.empty();
8204 for (const MapData &L : DeclComponentLists) {
8205 OMPClauseMappableExprCommon::MappableExprComponentListRef Components;
8206 OpenMPMapClauseKind MapType;
Kelvin Lief579432018-12-18 22:18:41 +00008207 ArrayRef<OpenMPMapModifierKind> MapModifiers;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008208 bool IsImplicit;
Kelvin Lief579432018-12-18 22:18:41 +00008209 std::tie(Components, MapType, MapModifiers, IsImplicit) = L;
Alexey Bataeve82445f2018-09-20 13:54:02 +00008210 auto It = OverlappedData.find(&L);
8211 if (It == OverlappedData.end())
Kelvin Lief579432018-12-18 22:18:41 +00008212 generateInfoForComponentList(MapType, MapModifiers, Components,
Alexey Bataeve82445f2018-09-20 13:54:02 +00008213 BasePointers, Pointers, Sizes, Types,
8214 PartialStruct, IsFirstComponentList,
8215 IsImplicit);
8216 IsFirstComponentList = false;
8217 }
Alexey Bataevb3638132018-07-19 16:34:13 +00008218 }
Samuel Antao86ace552016-04-27 22:40:57 +00008219
Alexey Bataevb3638132018-07-19 16:34:13 +00008220 /// Generate the base pointers, section pointers, sizes and map types
8221 /// associated with the declare target link variables.
8222 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers,
8223 MapValuesArrayTy &Pointers,
8224 MapValuesArrayTy &Sizes,
8225 MapFlagsArrayTy &Types) const {
8226 // Map other list items in the map clause which are not captured variables
8227 // but "declare target link" global variables.,
8228 for (const auto *C : this->CurDir.getClausesOfKind<OMPMapClause>()) {
8229 for (const auto &L : C->component_lists()) {
8230 if (!L.first)
8231 continue;
8232 const auto *VD = dyn_cast<VarDecl>(L.first);
8233 if (!VD)
8234 continue;
8235 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00008236 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Alexey Bataevb3638132018-07-19 16:34:13 +00008237 if (!Res || *Res != OMPDeclareTargetDeclAttr::MT_Link)
8238 continue;
8239 StructRangeInfoTy PartialStruct;
8240 generateInfoForComponentList(
Kelvin Lief579432018-12-18 22:18:41 +00008241 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008242 Pointers, Sizes, Types, PartialStruct,
8243 /*IsFirstComponentList=*/true, C->isImplicit());
8244 assert(!PartialStruct.Base.isValid() &&
8245 "No partial structs for declare target link expected.");
8246 }
8247 }
Samuel Antao86ace552016-04-27 22:40:57 +00008248 }
Samuel Antaod486f842016-05-26 16:53:38 +00008249
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008250 /// Generate the default map information for a given capture \a CI,
Samuel Antaod486f842016-05-26 16:53:38 +00008251 /// record field declaration \a RI and captured value \a CV.
Samuel Antaocc10b852016-07-28 14:23:26 +00008252 void generateDefaultMapInfo(const CapturedStmt::Capture &CI,
8253 const FieldDecl &RI, llvm::Value *CV,
8254 MapBaseValuesArrayTy &CurBasePointers,
8255 MapValuesArrayTy &CurPointers,
8256 MapValuesArrayTy &CurSizes,
Alexey Bataevb3638132018-07-19 16:34:13 +00008257 MapFlagsArrayTy &CurMapTypes) const {
Samuel Antaod486f842016-05-26 16:53:38 +00008258 // Do the default mapping.
8259 if (CI.capturesThis()) {
8260 CurBasePointers.push_back(CV);
8261 CurPointers.push_back(CV);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008262 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr());
Samuel Antaod486f842016-05-26 16:53:38 +00008263 CurSizes.push_back(CGF.getTypeSize(PtrTy->getPointeeType()));
8264 // Default map type.
Samuel Antaocc10b852016-07-28 14:23:26 +00008265 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM);
Samuel Antaod486f842016-05-26 16:53:38 +00008266 } else if (CI.capturesVariableByCopy()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008267 CurBasePointers.push_back(CV);
8268 CurPointers.push_back(CV);
Samuel Antaod486f842016-05-26 16:53:38 +00008269 if (!RI.getType()->isAnyPointerType()) {
Samuel Antao6d004262016-06-16 18:39:34 +00008270 // We have to signal to the runtime captures passed by value that are
8271 // not pointers.
George Rokos065755d2017-11-07 18:27:04 +00008272 CurMapTypes.push_back(OMP_MAP_LITERAL);
Samuel Antaod486f842016-05-26 16:53:38 +00008273 CurSizes.push_back(CGF.getTypeSize(RI.getType()));
8274 } else {
8275 // Pointers are implicitly mapped with a zero size and no flags
8276 // (other than first map that is added for all implicit maps).
Alexey Bataevb3638132018-07-19 16:34:13 +00008277 CurMapTypes.push_back(OMP_MAP_NONE);
Samuel Antaod486f842016-05-26 16:53:38 +00008278 CurSizes.push_back(llvm::Constant::getNullValue(CGF.SizeTy));
8279 }
8280 } else {
8281 assert(CI.capturesVariable() && "Expected captured reference.");
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008282 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr());
Samuel Antaod486f842016-05-26 16:53:38 +00008283 QualType ElementType = PtrTy->getPointeeType();
8284 CurSizes.push_back(CGF.getTypeSize(ElementType));
8285 // The default map type for a scalar/complex type is 'to' because by
8286 // default the value doesn't have to be retrieved. For an aggregate
8287 // type, the default is 'tofrom'.
Alexey Bataevb3638132018-07-19 16:34:13 +00008288 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI));
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008289 const VarDecl *VD = CI.getCapturedVar();
8290 if (FirstPrivateDecls.count(VD) &&
8291 VD->getType().isConstant(CGF.getContext())) {
8292 llvm::Constant *Addr =
8293 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD);
8294 // Copy the value of the original variable to the new global copy.
8295 CGF.Builder.CreateMemCpy(
8296 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(),
8297 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)),
Alexey Bataevc2b831f2019-04-02 16:03:40 +00008298 CurSizes.back(), /*isVolatile=*/false);
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008299 // Use new global variable as the base pointers.
8300 CurBasePointers.push_back(Addr);
8301 CurPointers.push_back(Addr);
8302 } else {
8303 CurBasePointers.push_back(CV);
Alexey Bataevc2b831f2019-04-02 16:03:40 +00008304 if (FirstPrivateDecls.count(VD) && ElementType->isAnyPointerType()) {
8305 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue(
8306 CV, ElementType, CGF.getContext().getDeclAlign(VD),
8307 AlignmentSource::Decl));
8308 CurPointers.push_back(PtrAddr.getPointer());
8309 } else {
8310 CurPointers.push_back(CV);
8311 }
Alexey Bataev1af5bd52019-03-05 17:47:18 +00008312 }
Samuel Antaod486f842016-05-26 16:53:38 +00008313 }
George Rokos065755d2017-11-07 18:27:04 +00008314 // Every default map produces a single argument which is a target parameter.
8315 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM;
Alexey Bataevb3638132018-07-19 16:34:13 +00008316
8317 // Add flag stating this is an implicit map.
8318 CurMapTypes.back() |= OMP_MAP_IMPLICIT;
Samuel Antaod486f842016-05-26 16:53:38 +00008319 }
Samuel Antao86ace552016-04-27 22:40:57 +00008320};
Samuel Antaodf158d52016-04-27 22:58:19 +00008321
8322enum OpenMPOffloadingReservedDeviceIDs {
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008323 /// Device ID if the device was not defined, runtime should get it
Samuel Antaodf158d52016-04-27 22:58:19 +00008324 /// from environment variables in the spec.
8325 OMP_DEVICEID_UNDEF = -1,
8326};
8327} // anonymous namespace
8328
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008329/// Emit the arrays used to pass the captures and map information to the
Samuel Antaodf158d52016-04-27 22:58:19 +00008330/// offloading runtime library. If there is no map or capture information,
8331/// return nullptr by reference.
8332static void
Samuel Antaocc10b852016-07-28 14:23:26 +00008333emitOffloadingArrays(CodeGenFunction &CGF,
8334 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers,
Samuel Antaodf158d52016-04-27 22:58:19 +00008335 MappableExprsHandler::MapValuesArrayTy &Pointers,
8336 MappableExprsHandler::MapValuesArrayTy &Sizes,
Samuel Antaocc10b852016-07-28 14:23:26 +00008337 MappableExprsHandler::MapFlagsArrayTy &MapTypes,
8338 CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008339 CodeGenModule &CGM = CGF.CGM;
8340 ASTContext &Ctx = CGF.getContext();
Samuel Antaodf158d52016-04-27 22:58:19 +00008341
Samuel Antaocc10b852016-07-28 14:23:26 +00008342 // Reset the array information.
8343 Info.clearArrayInfo();
8344 Info.NumberOfPtrs = BasePointers.size();
Samuel Antaodf158d52016-04-27 22:58:19 +00008345
Samuel Antaocc10b852016-07-28 14:23:26 +00008346 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008347 // Detect if we have any capture size requiring runtime evaluation of the
8348 // size so that a constant array could be eventually used.
8349 bool hasRuntimeEvaluationCaptureSize = false;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008350 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008351 if (!isa<llvm::Constant>(S)) {
8352 hasRuntimeEvaluationCaptureSize = true;
8353 break;
8354 }
8355
Samuel Antaocc10b852016-07-28 14:23:26 +00008356 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true);
Samuel Antaodf158d52016-04-27 22:58:19 +00008357 QualType PointerArrayType =
8358 Ctx.getConstantArrayType(Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal,
8359 /*IndexTypeQuals=*/0);
8360
Samuel Antaocc10b852016-07-28 14:23:26 +00008361 Info.BasePointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008362 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer();
Samuel Antaocc10b852016-07-28 14:23:26 +00008363 Info.PointersArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008364 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer();
8365
8366 // If we don't have any VLA types or other types that require runtime
8367 // evaluation, we can use a constant array for the map sizes, otherwise we
8368 // need to fill up the arrays as we do for the pointers.
8369 if (hasRuntimeEvaluationCaptureSize) {
8370 QualType SizeArrayType = Ctx.getConstantArrayType(
8371 Ctx.getSizeType(), PointerNumAP, ArrayType::Normal,
8372 /*IndexTypeQuals=*/0);
Samuel Antaocc10b852016-07-28 14:23:26 +00008373 Info.SizesArray =
Samuel Antaodf158d52016-04-27 22:58:19 +00008374 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer();
8375 } else {
8376 // We expect all the sizes to be constant, so we collect them to create
8377 // a constant array.
8378 SmallVector<llvm::Constant *, 16> ConstSizes;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008379 for (llvm::Value *S : Sizes)
Samuel Antaodf158d52016-04-27 22:58:19 +00008380 ConstSizes.push_back(cast<llvm::Constant>(S));
8381
8382 auto *SizesArrayInit = llvm::ConstantArray::get(
8383 llvm::ArrayType::get(CGM.SizeTy, ConstSizes.size()), ConstSizes);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008384 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008385 auto *SizesArrayGbl = new llvm::GlobalVariable(
8386 CGM.getModule(), SizesArrayInit->getType(),
8387 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008388 SizesArrayInit, Name);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008389 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008390 Info.SizesArray = SizesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008391 }
8392
8393 // The map types are always constant so we don't need to generate code to
8394 // fill arrays. Instead, we create an array constant.
Alexey Bataevb3638132018-07-19 16:34:13 +00008395 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0);
8396 llvm::copy(MapTypes, Mapping.begin());
Samuel Antaodf158d52016-04-27 22:58:19 +00008397 llvm::Constant *MapTypesArrayInit =
Alexey Bataevb3638132018-07-19 16:34:13 +00008398 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping);
Alexey Bataev18fa2322018-05-02 14:20:50 +00008399 std::string MaptypesName =
8400 CGM.getOpenMPRuntime().getName({"offload_maptypes"});
Samuel Antaodf158d52016-04-27 22:58:19 +00008401 auto *MapTypesArrayGbl = new llvm::GlobalVariable(
8402 CGM.getModule(), MapTypesArrayInit->getType(),
8403 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage,
Alexey Bataev18fa2322018-05-02 14:20:50 +00008404 MapTypesArrayInit, MaptypesName);
Peter Collingbournebcf909d2016-06-14 21:02:05 +00008405 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
Samuel Antaocc10b852016-07-28 14:23:26 +00008406 Info.MapTypesArray = MapTypesArrayGbl;
Samuel Antaodf158d52016-04-27 22:58:19 +00008407
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008408 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) {
8409 llvm::Value *BPVal = *BasePointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008410 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008411 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008412 Info.BasePointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008413 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8414 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008415 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8416 CGF.Builder.CreateStore(BPVal, BPAddr);
8417
Samuel Antaocc10b852016-07-28 14:23:26 +00008418 if (Info.requiresDevicePointerInfo())
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008419 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl())
Alexey Bataev43a919f2018-04-13 17:48:43 +00008420 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr);
Samuel Antaocc10b852016-07-28 14:23:26 +00008421
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008422 llvm::Value *PVal = Pointers[I];
Samuel Antaodf158d52016-04-27 22:58:19 +00008423 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008424 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008425 Info.PointersArray, 0, I);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +00008426 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
8427 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0));
Samuel Antaodf158d52016-04-27 22:58:19 +00008428 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy));
8429 CGF.Builder.CreateStore(PVal, PAddr);
8430
8431 if (hasRuntimeEvaluationCaptureSize) {
8432 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008433 llvm::ArrayType::get(CGM.SizeTy, Info.NumberOfPtrs),
8434 Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008435 /*Idx0=*/0,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008436 /*Idx1=*/I);
Samuel Antaodf158d52016-04-27 22:58:19 +00008437 Address SAddr(S, Ctx.getTypeAlignInChars(Ctx.getSizeType()));
8438 CGF.Builder.CreateStore(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008439 CGF.Builder.CreateIntCast(Sizes[I], CGM.SizeTy, /*isSigned=*/true),
Samuel Antaodf158d52016-04-27 22:58:19 +00008440 SAddr);
8441 }
8442 }
8443 }
8444}
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00008445/// Emit the arguments to be passed to the runtime library based on the
Samuel Antaodf158d52016-04-27 22:58:19 +00008446/// arrays of pointers, sizes and map types.
8447static void emitOffloadingArraysArgument(
8448 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg,
8449 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00008450 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008451 CodeGenModule &CGM = CGF.CGM;
Samuel Antaocc10b852016-07-28 14:23:26 +00008452 if (Info.NumberOfPtrs) {
Samuel Antaodf158d52016-04-27 22:58:19 +00008453 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008454 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8455 Info.BasePointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008456 /*Idx0=*/0, /*Idx1=*/0);
8457 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008458 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs),
8459 Info.PointersArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008460 /*Idx0=*/0,
8461 /*Idx1=*/0);
8462 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
Samuel Antaocc10b852016-07-28 14:23:26 +00008463 llvm::ArrayType::get(CGM.SizeTy, Info.NumberOfPtrs), Info.SizesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008464 /*Idx0=*/0, /*Idx1=*/0);
8465 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32(
George Rokos63bc9d62017-11-21 18:25:12 +00008466 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs),
Samuel Antaocc10b852016-07-28 14:23:26 +00008467 Info.MapTypesArray,
Samuel Antaodf158d52016-04-27 22:58:19 +00008468 /*Idx0=*/0,
8469 /*Idx1=*/0);
8470 } else {
8471 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
8472 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy);
8473 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.SizeTy->getPointerTo());
8474 MapTypesArrayArg =
George Rokos63bc9d62017-11-21 18:25:12 +00008475 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo());
Samuel Antaodf158d52016-04-27 22:58:19 +00008476 }
Samuel Antao86ace552016-04-27 22:40:57 +00008477}
8478
Alexey Bataev7bb33532019-01-07 21:30:43 +00008479/// Check for inner distribute directive.
8480static const OMPExecutableDirective *
8481getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
8482 const auto *CS = D.getInnermostCapturedStmt();
8483 const auto *Body =
8484 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true);
Alexey Bataev5c427362019-04-10 19:11:33 +00008485 const Stmt *ChildStmt =
8486 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
Alexey Bataev7bb33532019-01-07 21:30:43 +00008487
Alexey Bataev5c427362019-04-10 19:11:33 +00008488 if (const auto *NestedDir =
8489 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008490 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind();
8491 switch (D.getDirectiveKind()) {
8492 case OMPD_target:
8493 if (isOpenMPDistributeDirective(DKind))
8494 return NestedDir;
8495 if (DKind == OMPD_teams) {
8496 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers(
8497 /*IgnoreCaptured=*/true);
8498 if (!Body)
8499 return nullptr;
Alexey Bataev5c427362019-04-10 19:11:33 +00008500 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body);
8501 if (const auto *NND =
8502 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) {
Alexey Bataev7bb33532019-01-07 21:30:43 +00008503 DKind = NND->getDirectiveKind();
8504 if (isOpenMPDistributeDirective(DKind))
8505 return NND;
8506 }
8507 }
8508 return nullptr;
8509 case OMPD_target_teams:
8510 if (isOpenMPDistributeDirective(DKind))
8511 return NestedDir;
8512 return nullptr;
8513 case OMPD_target_parallel:
8514 case OMPD_target_simd:
8515 case OMPD_target_parallel_for:
8516 case OMPD_target_parallel_for_simd:
8517 return nullptr;
8518 case OMPD_target_teams_distribute:
8519 case OMPD_target_teams_distribute_simd:
8520 case OMPD_target_teams_distribute_parallel_for:
8521 case OMPD_target_teams_distribute_parallel_for_simd:
8522 case OMPD_parallel:
8523 case OMPD_for:
8524 case OMPD_parallel_for:
8525 case OMPD_parallel_sections:
8526 case OMPD_for_simd:
8527 case OMPD_parallel_for_simd:
8528 case OMPD_cancel:
8529 case OMPD_cancellation_point:
8530 case OMPD_ordered:
8531 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00008532 case OMPD_allocate:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008533 case OMPD_task:
8534 case OMPD_simd:
8535 case OMPD_sections:
8536 case OMPD_section:
8537 case OMPD_single:
8538 case OMPD_master:
8539 case OMPD_critical:
8540 case OMPD_taskyield:
8541 case OMPD_barrier:
8542 case OMPD_taskwait:
8543 case OMPD_taskgroup:
8544 case OMPD_atomic:
8545 case OMPD_flush:
8546 case OMPD_teams:
8547 case OMPD_target_data:
8548 case OMPD_target_exit_data:
8549 case OMPD_target_enter_data:
8550 case OMPD_distribute:
8551 case OMPD_distribute_simd:
8552 case OMPD_distribute_parallel_for:
8553 case OMPD_distribute_parallel_for_simd:
8554 case OMPD_teams_distribute:
8555 case OMPD_teams_distribute_simd:
8556 case OMPD_teams_distribute_parallel_for:
8557 case OMPD_teams_distribute_parallel_for_simd:
8558 case OMPD_target_update:
8559 case OMPD_declare_simd:
8560 case OMPD_declare_target:
8561 case OMPD_end_declare_target:
8562 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00008563 case OMPD_declare_mapper:
Alexey Bataev7bb33532019-01-07 21:30:43 +00008564 case OMPD_taskloop:
8565 case OMPD_taskloop_simd:
8566 case OMPD_requires:
8567 case OMPD_unknown:
8568 llvm_unreachable("Unexpected directive.");
8569 }
8570 }
8571
8572 return nullptr;
8573}
8574
8575void CGOpenMPRuntime::emitTargetNumIterationsCall(
8576 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *Device,
8577 const llvm::function_ref<llvm::Value *(
8578 CodeGenFunction &CGF, const OMPLoopDirective &D)> &SizeEmitter) {
8579 OpenMPDirectiveKind Kind = D.getDirectiveKind();
8580 const OMPExecutableDirective *TD = &D;
8581 // Get nested teams distribute kind directive, if any.
8582 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind))
8583 TD = getNestedDistributeDirective(CGM.getContext(), D);
8584 if (!TD)
8585 return;
8586 const auto *LD = cast<OMPLoopDirective>(TD);
8587 auto &&CodeGen = [LD, &Device, &SizeEmitter, this](CodeGenFunction &CGF,
8588 PrePostActionTy &) {
8589 llvm::Value *NumIterations = SizeEmitter(CGF, *LD);
8590
8591 // Emit device ID if any.
8592 llvm::Value *DeviceID;
8593 if (Device)
8594 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
8595 CGF.Int64Ty, /*isSigned=*/true);
8596 else
8597 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
8598
8599 llvm::Value *Args[] = {DeviceID, NumIterations};
8600 CGF.EmitRuntimeCall(
8601 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args);
8602 };
8603 emitInlinedDirective(CGF, OMPD_unknown, CodeGen);
8604}
8605
Samuel Antaobed3c462015-10-02 16:14:20 +00008606void CGOpenMPRuntime::emitTargetCall(CodeGenFunction &CGF,
8607 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +00008608 llvm::Function *OutlinedFn,
Samuel Antaoee8fb302016-01-06 13:42:12 +00008609 llvm::Value *OutlinedFnID,
Alexey Bataev8451efa2018-01-15 19:06:12 +00008610 const Expr *IfCond, const Expr *Device) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00008611 if (!CGF.HaveInsertPoint())
8612 return;
Samuel Antaobed3c462015-10-02 16:14:20 +00008613
Samuel Antaoee8fb302016-01-06 13:42:12 +00008614 assert(OutlinedFn && "Invalid outlined function!");
8615
Alexey Bataev8451efa2018-01-15 19:06:12 +00008616 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>();
8617 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
Alexey Bataev475a7442018-01-12 19:39:11 +00008618 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target);
Alexey Bataev8451efa2018-01-15 19:06:12 +00008619 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF,
8620 PrePostActionTy &) {
8621 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
8622 };
8623 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen);
Samuel Antao86ace552016-04-27 22:40:57 +00008624
Alexey Bataev8451efa2018-01-15 19:06:12 +00008625 CodeGenFunction::OMPTargetDataInfo InputInfo;
8626 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobed3c462015-10-02 16:14:20 +00008627 // Fill up the pointer arrays and transfer execution to the device.
Alexey Bataev8451efa2018-01-15 19:06:12 +00008628 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo,
8629 &MapTypesArray, &CS, RequiresOuterTask,
8630 &CapturedVars](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobed3c462015-10-02 16:14:20 +00008631 // On top of the arrays that were filled up, the target offloading call
8632 // takes as arguments the device id as well as the host pointer. The host
8633 // pointer is used by the runtime library to identify the current target
8634 // region, so it only has to be unique and not necessarily point to
8635 // anything. It could be the pointer to the outlined function that
8636 // implements the target region, but we aren't using that so that the
8637 // compiler doesn't need to keep that, and could therefore inline the host
8638 // function if proven worthwhile during optimization.
8639
Samuel Antaoee8fb302016-01-06 13:42:12 +00008640 // From this point on, we need to have an ID of the target region defined.
8641 assert(OutlinedFnID && "Invalid outlined function ID!");
Samuel Antaobed3c462015-10-02 16:14:20 +00008642
8643 // Emit device ID if any.
8644 llvm::Value *DeviceID;
George Rokos63bc9d62017-11-21 18:25:12 +00008645 if (Device) {
Samuel Antaobed3c462015-10-02 16:14:20 +00008646 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00008647 CGF.Int64Ty, /*isSigned=*/true);
8648 } else {
8649 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
8650 }
Samuel Antaobed3c462015-10-02 16:14:20 +00008651
Samuel Antaodf158d52016-04-27 22:58:19 +00008652 // Emit the number of elements in the offloading arrays.
Alexey Bataev8451efa2018-01-15 19:06:12 +00008653 llvm::Value *PointerNum =
8654 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaodf158d52016-04-27 22:58:19 +00008655
Samuel Antaob68e2db2016-03-03 16:20:23 +00008656 // Return value of the runtime offloading call.
8657 llvm::Value *Return;
8658
Alexey Bataev5c427362019-04-10 19:11:33 +00008659 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D);
8660 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D);
Samuel Antaob68e2db2016-03-03 16:20:23 +00008661
Alexey Bataeva9f77c62017-12-13 21:04:20 +00008662 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00008663 // The target region is an outlined function launched by the runtime
8664 // via calls __tgt_target() or __tgt_target_teams().
8665 //
8666 // __tgt_target() launches a target region with one team and one thread,
8667 // executing a serial region. This master thread may in turn launch
8668 // more threads within its team upon encountering a parallel region,
8669 // however, no additional teams can be launched on the device.
8670 //
8671 // __tgt_target_teams() launches a target region with one or more teams,
8672 // each with one or more threads. This call is required for target
8673 // constructs such as:
8674 // 'target teams'
8675 // 'target' / 'teams'
8676 // 'target teams distribute parallel for'
8677 // 'target parallel'
8678 // and so on.
8679 //
8680 // Note that on the host and CPU targets, the runtime implementation of
8681 // these calls simply call the outlined function without forking threads.
8682 // The outlined functions themselves have runtime calls to
8683 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by
8684 // the compiler in emitTeamsCall() and emitParallelCall().
8685 //
8686 // In contrast, on the NVPTX target, the implementation of
8687 // __tgt_target_teams() launches a GPU kernel with the requested number
8688 // of teams and threads so no additional calls to the runtime are required.
Samuel Antaob68e2db2016-03-03 16:20:23 +00008689 if (NumTeams) {
Arpith Chacko Jacob33c849a2017-01-25 00:57:16 +00008690 // If we have NumTeams defined this means that we have an enclosed teams
8691 // region. Therefore we also expect to have NumThreads defined. These two
8692 // values should be defined in the presence of a teams directive,
8693 // regardless of having any clauses associated. If the user is using teams
8694 // but no clauses, these two values will be the default that should be
8695 // passed to the runtime library - a 32-bit integer with the value zero.
8696 assert(NumThreads && "Thread limit expression should be available along "
8697 "with number of teams.");
Alexey Bataev8451efa2018-01-15 19:06:12 +00008698 llvm::Value *OffloadingArgs[] = {DeviceID,
8699 OutlinedFnID,
8700 PointerNum,
8701 InputInfo.BasePointersArray.getPointer(),
8702 InputInfo.PointersArray.getPointer(),
8703 InputInfo.SizesArray.getPointer(),
8704 MapTypesArray,
8705 NumTeams,
8706 NumThreads};
Samuel Antaob68e2db2016-03-03 16:20:23 +00008707 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00008708 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait
8709 : OMPRTL__tgt_target_teams),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00008710 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00008711 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00008712 llvm::Value *OffloadingArgs[] = {DeviceID,
8713 OutlinedFnID,
8714 PointerNum,
8715 InputInfo.BasePointersArray.getPointer(),
8716 InputInfo.PointersArray.getPointer(),
8717 InputInfo.SizesArray.getPointer(),
8718 MapTypesArray};
Alexey Bataeva9f77c62017-12-13 21:04:20 +00008719 Return = CGF.EmitRuntimeCall(
Alexey Bataev8451efa2018-01-15 19:06:12 +00008720 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait
8721 : OMPRTL__tgt_target),
Alexey Bataeva9f77c62017-12-13 21:04:20 +00008722 OffloadingArgs);
Samuel Antaob68e2db2016-03-03 16:20:23 +00008723 }
Samuel Antaobed3c462015-10-02 16:14:20 +00008724
Alexey Bataev2a007e02017-10-02 14:20:58 +00008725 // Check the error code and execute the host version if required.
8726 llvm::BasicBlock *OffloadFailedBlock =
8727 CGF.createBasicBlock("omp_offload.failed");
8728 llvm::BasicBlock *OffloadContBlock =
8729 CGF.createBasicBlock("omp_offload.cont");
8730 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return);
8731 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock);
8732
8733 CGF.EmitBlock(OffloadFailedBlock);
Alexey Bataev8451efa2018-01-15 19:06:12 +00008734 if (RequiresOuterTask) {
8735 CapturedVars.clear();
8736 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
8737 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00008738 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev2a007e02017-10-02 14:20:58 +00008739 CGF.EmitBranch(OffloadContBlock);
8740
8741 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true);
Samuel Antaobed3c462015-10-02 16:14:20 +00008742 };
8743
Samuel Antaoee8fb302016-01-06 13:42:12 +00008744 // Notify that the host version must be executed.
Alexey Bataev8451efa2018-01-15 19:06:12 +00008745 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars,
8746 RequiresOuterTask](CodeGenFunction &CGF,
8747 PrePostActionTy &) {
8748 if (RequiresOuterTask) {
8749 CapturedVars.clear();
8750 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars);
8751 }
Stephen Kellyf2ceec42018-08-09 21:08:08 +00008752 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars);
Alexey Bataev8451efa2018-01-15 19:06:12 +00008753 };
8754
8755 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray,
8756 &CapturedVars, RequiresOuterTask,
8757 &CS](CodeGenFunction &CGF, PrePostActionTy &) {
8758 // Fill up the arrays with all the captured variables.
8759 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
8760 MappableExprsHandler::MapValuesArrayTy Pointers;
8761 MappableExprsHandler::MapValuesArrayTy Sizes;
8762 MappableExprsHandler::MapFlagsArrayTy MapTypes;
8763
Alexey Bataev8451efa2018-01-15 19:06:12 +00008764 // Get mappable expression information.
8765 MappableExprsHandler MEHandler(D, CGF);
Alexey Bataev969dbc02018-11-08 15:47:39 +00008766 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers;
Alexey Bataev8451efa2018-01-15 19:06:12 +00008767
8768 auto RI = CS.getCapturedRecordDecl()->field_begin();
8769 auto CV = CapturedVars.begin();
8770 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(),
8771 CE = CS.capture_end();
8772 CI != CE; ++CI, ++RI, ++CV) {
Alexey Bataevb3638132018-07-19 16:34:13 +00008773 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers;
8774 MappableExprsHandler::MapValuesArrayTy CurPointers;
8775 MappableExprsHandler::MapValuesArrayTy CurSizes;
8776 MappableExprsHandler::MapFlagsArrayTy CurMapTypes;
8777 MappableExprsHandler::StructRangeInfoTy PartialStruct;
Alexey Bataev8451efa2018-01-15 19:06:12 +00008778
8779 // VLA sizes are passed to the outlined region by copy and do not have map
8780 // information associated.
8781 if (CI->capturesVariableArrayType()) {
8782 CurBasePointers.push_back(*CV);
8783 CurPointers.push_back(*CV);
8784 CurSizes.push_back(CGF.getTypeSize(RI->getType()));
8785 // Copy to the device as an argument. No need to retrieve it.
8786 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL |
8787 MappableExprsHandler::OMP_MAP_TARGET_PARAM);
8788 } else {
8789 // If we have any information in the map clause, we use it, otherwise we
8790 // just do a default mapping.
8791 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers,
Alexey Bataevb3638132018-07-19 16:34:13 +00008792 CurSizes, CurMapTypes, PartialStruct);
Alexey Bataev8451efa2018-01-15 19:06:12 +00008793 if (CurBasePointers.empty())
8794 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers,
8795 CurPointers, CurSizes, CurMapTypes);
Alexey Bataev60705422018-10-30 15:50:12 +00008796 // Generate correct mapping for variables captured by reference in
8797 // lambdas.
8798 if (CI->capturesVariable())
Alexey Bataev969dbc02018-11-08 15:47:39 +00008799 MEHandler.generateInfoForLambdaCaptures(
8800 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes,
8801 CurMapTypes, LambdaPointers);
Alexey Bataev8451efa2018-01-15 19:06:12 +00008802 }
8803 // We expect to have at least an element of information for this capture.
8804 assert(!CurBasePointers.empty() &&
8805 "Non-existing map pointer for capture!");
8806 assert(CurBasePointers.size() == CurPointers.size() &&
8807 CurBasePointers.size() == CurSizes.size() &&
8808 CurBasePointers.size() == CurMapTypes.size() &&
8809 "Inconsistent map information sizes!");
8810
Alexey Bataevb3638132018-07-19 16:34:13 +00008811 // If there is an entry in PartialStruct it means we have a struct with
8812 // individual members mapped. Emit an extra combined entry.
8813 if (PartialStruct.Base.isValid())
8814 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes,
8815 CurMapTypes, PartialStruct);
8816
Alexey Bataev8451efa2018-01-15 19:06:12 +00008817 // We need to append the results of this capture to what we already have.
8818 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end());
8819 Pointers.append(CurPointers.begin(), CurPointers.end());
8820 Sizes.append(CurSizes.begin(), CurSizes.end());
8821 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end());
8822 }
Alexey Bataev60705422018-10-30 15:50:12 +00008823 // Adjust MEMBER_OF flags for the lambdas captures.
Alexey Bataev969dbc02018-11-08 15:47:39 +00008824 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers,
8825 Pointers, MapTypes);
Alexey Bataev92327c52018-03-26 16:40:55 +00008826 // Map other list items in the map clause which are not captured variables
8827 // but "declare target link" global variables.
Alexey Bataevb3638132018-07-19 16:34:13 +00008828 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes,
8829 MapTypes);
Alexey Bataev8451efa2018-01-15 19:06:12 +00008830
8831 TargetDataInfo Info;
8832 // Fill up the arrays and create the arguments.
8833 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
8834 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
8835 Info.PointersArray, Info.SizesArray,
8836 Info.MapTypesArray, Info);
8837 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
8838 InputInfo.BasePointersArray =
8839 Address(Info.BasePointersArray, CGM.getPointerAlign());
8840 InputInfo.PointersArray =
8841 Address(Info.PointersArray, CGM.getPointerAlign());
8842 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign());
8843 MapTypesArray = Info.MapTypesArray;
8844 if (RequiresOuterTask)
8845 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
8846 else
8847 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
8848 };
8849
8850 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask](
8851 CodeGenFunction &CGF, PrePostActionTy &) {
8852 if (RequiresOuterTask) {
8853 CodeGenFunction::OMPTargetDataInfo InputInfo;
8854 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo);
8855 } else {
8856 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen);
8857 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00008858 };
8859
8860 // If we have a target function ID it means that we need to support
8861 // offloading, otherwise, just execute on the host. We need to execute on host
8862 // regardless of the conditional in the if clause if, e.g., the user do not
8863 // specify target triples.
8864 if (OutlinedFnID) {
Alexey Bataev8451efa2018-01-15 19:06:12 +00008865 if (IfCond) {
8866 emitOMPIfClause(CGF, IfCond, TargetThenGen, TargetElseGen);
8867 } else {
8868 RegionCodeGenTy ThenRCG(TargetThenGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00008869 ThenRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00008870 }
8871 } else {
Alexey Bataev8451efa2018-01-15 19:06:12 +00008872 RegionCodeGenTy ElseRCG(TargetElseGen);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00008873 ElseRCG(CGF);
Alexey Bataevf539faa2016-03-28 12:58:34 +00008874 }
Samuel Antaobed3c462015-10-02 16:14:20 +00008875}
Samuel Antaoee8fb302016-01-06 13:42:12 +00008876
8877void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
8878 StringRef ParentName) {
8879 if (!S)
8880 return;
8881
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00008882 // Codegen OMP target directives that offload compute to the device.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008883 bool RequiresDeviceCodegen =
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00008884 isa<OMPExecutableDirective>(S) &&
8885 isOpenMPTargetExecutionDirective(
8886 cast<OMPExecutableDirective>(S)->getDirectiveKind());
Samuel Antaoee8fb302016-01-06 13:42:12 +00008887
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008888 if (RequiresDeviceCodegen) {
8889 const auto &E = *cast<OMPExecutableDirective>(S);
Samuel Antaoee8fb302016-01-06 13:42:12 +00008890 unsigned DeviceID;
8891 unsigned FileID;
8892 unsigned Line;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00008893 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID,
Samuel Antao2de62b02016-02-13 23:35:10 +00008894 FileID, Line);
Samuel Antaoee8fb302016-01-06 13:42:12 +00008895
8896 // Is this a target region that should not be emitted as an entry point? If
8897 // so just signal we are done with this target region.
Samuel Antao2de62b02016-02-13 23:35:10 +00008898 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID,
8899 ParentName, Line))
Samuel Antaoee8fb302016-01-06 13:42:12 +00008900 return;
8901
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008902 switch (E.getDirectiveKind()) {
8903 case OMPD_target:
8904 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName,
8905 cast<OMPTargetDirective>(E));
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00008906 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008907 case OMPD_target_parallel:
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00008908 CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008909 CGM, ParentName, cast<OMPTargetParallelDirective>(E));
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00008910 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008911 case OMPD_target_teams:
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00008912 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008913 CGM, ParentName, cast<OMPTargetTeamsDirective>(E));
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00008914 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008915 case OMPD_target_teams_distribute:
Alexey Bataevdfa430f2017-12-08 15:03:50 +00008916 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008917 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E));
Alexey Bataevdfa430f2017-12-08 15:03:50 +00008918 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008919 case OMPD_target_teams_distribute_simd:
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00008920 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008921 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E));
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00008922 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008923 case OMPD_target_parallel_for:
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00008924 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008925 CGM, ParentName, cast<OMPTargetParallelForDirective>(E));
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00008926 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008927 case OMPD_target_parallel_for_simd:
Alexey Bataev5d7edca2017-11-09 17:32:15 +00008928 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008929 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E));
Alexey Bataev5d7edca2017-11-09 17:32:15 +00008930 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008931 case OMPD_target_simd:
Alexey Bataevf8365372017-11-17 17:57:25 +00008932 CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008933 CGM, ParentName, cast<OMPTargetSimdDirective>(E));
Alexey Bataevf8365372017-11-17 17:57:25 +00008934 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008935 case OMPD_target_teams_distribute_parallel_for:
Carlo Bertolli52978c32018-01-03 21:12:44 +00008936 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
8937 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008938 cast<OMPTargetTeamsDistributeParallelForDirective>(E));
Carlo Bertolli52978c32018-01-03 21:12:44 +00008939 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008940 case OMPD_target_teams_distribute_parallel_for_simd:
Alexey Bataev647dd842018-01-15 20:59:40 +00008941 CodeGenFunction::
8942 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
8943 CGM, ParentName,
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008944 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E));
Alexey Bataev647dd842018-01-15 20:59:40 +00008945 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008946 case OMPD_parallel:
8947 case OMPD_for:
8948 case OMPD_parallel_for:
8949 case OMPD_parallel_sections:
8950 case OMPD_for_simd:
8951 case OMPD_parallel_for_simd:
8952 case OMPD_cancel:
8953 case OMPD_cancellation_point:
8954 case OMPD_ordered:
8955 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00008956 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008957 case OMPD_task:
8958 case OMPD_simd:
8959 case OMPD_sections:
8960 case OMPD_section:
8961 case OMPD_single:
8962 case OMPD_master:
8963 case OMPD_critical:
8964 case OMPD_taskyield:
8965 case OMPD_barrier:
8966 case OMPD_taskwait:
8967 case OMPD_taskgroup:
8968 case OMPD_atomic:
8969 case OMPD_flush:
8970 case OMPD_teams:
8971 case OMPD_target_data:
8972 case OMPD_target_exit_data:
8973 case OMPD_target_enter_data:
8974 case OMPD_distribute:
8975 case OMPD_distribute_simd:
8976 case OMPD_distribute_parallel_for:
8977 case OMPD_distribute_parallel_for_simd:
8978 case OMPD_teams_distribute:
8979 case OMPD_teams_distribute_simd:
8980 case OMPD_teams_distribute_parallel_for:
8981 case OMPD_teams_distribute_parallel_for_simd:
8982 case OMPD_target_update:
8983 case OMPD_declare_simd:
8984 case OMPD_declare_target:
8985 case OMPD_end_declare_target:
8986 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00008987 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008988 case OMPD_taskloop:
8989 case OMPD_taskloop_simd:
Kelvin Li1408f912018-09-26 04:28:39 +00008990 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008991 case OMPD_unknown:
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00008992 llvm_unreachable("Unknown target directive for OpenMP device codegen.");
8993 }
Samuel Antaoee8fb302016-01-06 13:42:12 +00008994 return;
8995 }
8996
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00008997 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) {
Alexey Bataev475a7442018-01-12 19:39:11 +00008998 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt())
Samuel Antaoee8fb302016-01-06 13:42:12 +00008999 return;
9000
9001 scanForTargetRegionsFunctions(
Alexey Bataev475a7442018-01-12 19:39:11 +00009002 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009003 return;
9004 }
9005
9006 // If this is a lambda function, look into its body.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009007 if (const auto *L = dyn_cast<LambdaExpr>(S))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009008 S = L->getBody();
9009
9010 // Keep looking for target regions recursively.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009011 for (const Stmt *II : S->children())
Samuel Antaoee8fb302016-01-06 13:42:12 +00009012 scanForTargetRegionsFunctions(II, ParentName);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009013}
9014
9015bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009016 // If emitting code for the host, we do not process FD here. Instead we do
9017 // the normal code generation.
9018 if (!CGM.getLangOpts().OpenMPIsDevice)
9019 return false;
9020
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009021 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl());
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009022 StringRef Name = CGM.getMangledName(GD);
9023 // Try to detect target regions in the function.
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009024 if (const auto *FD = dyn_cast<FunctionDecl>(VD))
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009025 scanForTargetRegionsFunctions(FD->getBody(), Name);
Samuel Antaoee8fb302016-01-06 13:42:12 +00009026
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009027 // Do not to emit function if it is not marked as declare target.
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009028 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) &&
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009029 AlreadyEmittedTargetFunctions.count(Name) == 0;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009030}
9031
9032bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
9033 if (!CGM.getLangOpts().OpenMPIsDevice)
9034 return false;
9035
9036 // Check if there are Ctors/Dtors in this declaration and look for target
9037 // regions in it. We use the complete variant to produce the kernel name
9038 // mangling.
9039 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009040 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) {
9041 for (const CXXConstructorDecl *Ctor : RD->ctors()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009042 StringRef ParentName =
9043 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete));
9044 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName);
9045 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009046 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) {
Samuel Antaoee8fb302016-01-06 13:42:12 +00009047 StringRef ParentName =
9048 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete));
9049 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName);
9050 }
9051 }
9052
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009053 // Do not to emit variable if it is not marked as declare target.
Alexey Bataev92327c52018-03-26 16:40:55 +00009054 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009055 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(
9056 cast<VarDecl>(GD.getDecl()));
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009057 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link) {
Alexey Bataevd01b7492018-08-15 19:45:12 +00009058 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009059 return true;
9060 }
9061 return false;
Samuel Antaoee8fb302016-01-06 13:42:12 +00009062}
9063
Alexey Bataev1af5bd52019-03-05 17:47:18 +00009064llvm::Constant *
9065CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF,
9066 const VarDecl *VD) {
9067 assert(VD->getType().isConstant(CGM.getContext()) &&
9068 "Expected constant variable.");
9069 StringRef VarName;
9070 llvm::Constant *Addr;
9071 llvm::GlobalValue::LinkageTypes Linkage;
9072 QualType Ty = VD->getType();
9073 SmallString<128> Buffer;
9074 {
9075 unsigned DeviceID;
9076 unsigned FileID;
9077 unsigned Line;
9078 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID,
9079 FileID, Line);
9080 llvm::raw_svector_ostream OS(Buffer);
9081 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID)
9082 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line;
9083 VarName = OS.str();
9084 }
9085 Linkage = llvm::GlobalValue::InternalLinkage;
9086 Addr =
9087 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName,
9088 getDefaultFirstprivateAddressSpace());
9089 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage);
9090 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty);
9091 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr));
9092 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9093 VarName, Addr, VarSize,
9094 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage);
9095 return Addr;
9096}
9097
Alexey Bataev03f270c2018-03-30 18:31:07 +00009098void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD,
9099 llvm::Constant *Addr) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009100 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
9101 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
9102 if (!Res) {
9103 if (CGM.getLangOpts().OpenMPIsDevice) {
9104 // Register non-target variables being emitted in device code (debug info
9105 // may cause this).
9106 StringRef VarName = CGM.getMangledName(VD);
9107 EmittedNonTargetVariables.try_emplace(VarName, Addr);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009108 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009109 return;
Alexey Bataev03f270c2018-03-30 18:31:07 +00009110 }
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009111 // Register declare target variables.
9112 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags;
9113 StringRef VarName;
9114 CharUnits VarSize;
9115 llvm::GlobalValue::LinkageTypes Linkage;
9116 switch (*Res) {
9117 case OMPDeclareTargetDeclAttr::MT_To:
9118 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo;
9119 VarName = CGM.getMangledName(VD);
9120 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) {
9121 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType());
9122 assert(!VarSize.isZero() && "Expected non-zero size of the variable");
9123 } else {
9124 VarSize = CharUnits::Zero();
9125 }
9126 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false);
9127 // Temp solution to prevent optimizations of the internal variables.
9128 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) {
9129 std::string RefName = getName({VarName, "ref"});
9130 if (!CGM.GetGlobalValue(RefName)) {
9131 llvm::Constant *AddrRef =
9132 getOrCreateInternalVariable(Addr->getType(), RefName);
9133 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef);
9134 GVAddrRef->setConstant(/*Val=*/true);
9135 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage);
9136 GVAddrRef->setInitializer(Addr);
9137 CGM.addCompilerUsedGlobal(GVAddrRef);
9138 }
9139 }
9140 break;
9141 case OMPDeclareTargetDeclAttr::MT_Link:
9142 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink;
9143 if (CGM.getLangOpts().OpenMPIsDevice) {
9144 VarName = Addr->getName();
9145 Addr = nullptr;
9146 } else {
9147 VarName = getAddrOfDeclareTargetLink(VD).getName();
9148 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetLink(VD).getPointer());
9149 }
9150 VarSize = CGM.getPointerSize();
9151 Linkage = llvm::GlobalValue::WeakAnyLinkage;
9152 break;
9153 }
9154 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo(
9155 VarName, Addr, VarSize, Flags, Linkage);
Alexey Bataev03f270c2018-03-30 18:31:07 +00009156}
9157
Samuel Antaoee8fb302016-01-06 13:42:12 +00009158bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) {
Alexey Bataeve6aa4692018-09-13 16:54:05 +00009159 if (isa<FunctionDecl>(GD.getDecl()) ||
9160 isa<OMPDeclareReductionDecl>(GD.getDecl()))
Samuel Antaoee8fb302016-01-06 13:42:12 +00009161 return emitTargetFunctions(GD);
9162
9163 return emitTargetGlobalVariable(GD);
9164}
9165
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009166void CGOpenMPRuntime::emitDeferredTargetDecls() const {
9167 for (const VarDecl *VD : DeferredGlobalVariables) {
9168 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
Alexey Bataev97b72212018-08-14 18:31:20 +00009169 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009170 if (!Res)
9171 continue;
9172 if (*Res == OMPDeclareTargetDeclAttr::MT_To) {
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009173 CGM.EmitGlobal(VD);
Alexey Bataevd01b7492018-08-15 19:45:12 +00009174 } else {
9175 assert(*Res == OMPDeclareTargetDeclAttr::MT_Link &&
9176 "Expected to or link clauses.");
9177 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetLink(VD);
Alexey Bataevbf8fe712018-08-07 16:14:36 +00009178 }
9179 }
9180}
9181
Alexey Bataev60705422018-10-30 15:50:12 +00009182void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas(
9183 CodeGenFunction &CGF, const OMPExecutableDirective &D) const {
9184 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) &&
9185 " Expected target-based directive.");
9186}
9187
Alexey Bataevc5687252019-03-21 19:35:27 +00009188bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD,
9189 LangAS &AS) {
9190 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())
9191 return false;
9192 const auto *A = VD->getAttr<OMPAllocateDeclAttr>();
9193 switch(A->getAllocatorType()) {
9194 case OMPAllocateDeclAttr::OMPDefaultMemAlloc:
9195 // Not supported, fallback to the default mem space.
9196 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc:
9197 case OMPAllocateDeclAttr::OMPCGroupMemAlloc:
9198 case OMPAllocateDeclAttr::OMPHighBWMemAlloc:
9199 case OMPAllocateDeclAttr::OMPLowLatMemAlloc:
9200 case OMPAllocateDeclAttr::OMPThreadMemAlloc:
9201 case OMPAllocateDeclAttr::OMPConstMemAlloc:
9202 case OMPAllocateDeclAttr::OMPPTeamMemAlloc:
9203 AS = LangAS::Default;
9204 return true;
9205 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc:
9206 llvm_unreachable("Expected predefined allocator for the variables with the "
9207 "static storage.");
9208 }
9209 return false;
9210}
9211
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009212CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII(
9213 CodeGenModule &CGM)
9214 : CGM(CGM) {
9215 if (CGM.getLangOpts().OpenMPIsDevice) {
9216 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal;
9217 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false;
9218 }
9219}
9220
9221CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() {
9222 if (CGM.getLangOpts().OpenMPIsDevice)
9223 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal;
9224}
9225
Alexey Bataev6d944102018-05-02 15:45:28 +00009226bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) {
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009227 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal)
9228 return true;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009229
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009230 StringRef Name = CGM.getMangledName(GD);
Alexey Bataev6d944102018-05-02 15:45:28 +00009231 const auto *D = cast<FunctionDecl>(GD.getDecl());
Alexey Bataev34f8a702018-03-28 14:28:54 +00009232 // Do not to emit function if it is marked as declare target as it was already
9233 // emitted.
Alexey Bataev97b72212018-08-14 18:31:20 +00009234 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) {
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009235 if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) {
9236 if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name)))
Alexey Bataev34f8a702018-03-28 14:28:54 +00009237 return !F->isDeclaration();
9238 return false;
9239 }
9240 return true;
9241 }
9242
Alexey Bataev2a6f3f52018-11-07 19:11:14 +00009243 return !AlreadyEmittedTargetFunctions.insert(Name).second;
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00009244}
9245
Samuel Antaoee8fb302016-01-06 13:42:12 +00009246llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() {
9247 // If we have offloading in the current module, we need to emit the entries
9248 // now and register the offloading descriptor.
9249 createOffloadEntriesAndInfoMetadata();
9250
9251 // Create and register the offloading binary descriptors. This is the main
9252 // entity that captures all the information about offloading in the current
9253 // compilation unit.
9254 return createOffloadingBinaryDescriptorRegistration();
9255}
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009256
9257void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF,
9258 const OMPExecutableDirective &D,
9259 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +00009260 llvm::Function *OutlinedFn,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009261 ArrayRef<llvm::Value *> CapturedVars) {
9262 if (!CGF.HaveInsertPoint())
9263 return;
9264
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009265 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009266 CodeGenFunction::RunCleanupsScope Scope(CGF);
9267
9268 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn);
9269 llvm::Value *Args[] = {
9270 RTLoc,
9271 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars
9272 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())};
9273 llvm::SmallVector<llvm::Value *, 16> RealArgs;
9274 RealArgs.append(std::begin(Args), std::end(Args));
9275 RealArgs.append(CapturedVars.begin(), CapturedVars.end());
9276
James Y Knight9871db02019-02-05 16:42:33 +00009277 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009278 CGF.EmitRuntimeCall(RTLFn, RealArgs);
9279}
9280
9281void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
Carlo Bertollic6872252016-04-04 15:55:02 +00009282 const Expr *NumTeams,
9283 const Expr *ThreadLimit,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009284 SourceLocation Loc) {
9285 if (!CGF.HaveInsertPoint())
9286 return;
9287
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009288 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009289
Carlo Bertollic6872252016-04-04 15:55:02 +00009290 llvm::Value *NumTeamsVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009291 NumTeams
Carlo Bertollic6872252016-04-04 15:55:02 +00009292 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams),
9293 CGF.CGM.Int32Ty, /* isSigned = */ true)
9294 : CGF.Builder.getInt32(0);
9295
9296 llvm::Value *ThreadLimitVal =
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009297 ThreadLimit
Carlo Bertollic6872252016-04-04 15:55:02 +00009298 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit),
9299 CGF.CGM.Int32Ty, /* isSigned = */ true)
9300 : CGF.Builder.getInt32(0);
9301
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009302 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit)
Carlo Bertollic6872252016-04-04 15:55:02 +00009303 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal,
9304 ThreadLimitVal};
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00009305 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams),
9306 PushNumTeamsArgs);
9307}
Samuel Antaodf158d52016-04-27 22:58:19 +00009308
Samuel Antaocc10b852016-07-28 14:23:26 +00009309void CGOpenMPRuntime::emitTargetDataCalls(
9310 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
9311 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009312 if (!CGF.HaveInsertPoint())
9313 return;
9314
Samuel Antaocc10b852016-07-28 14:23:26 +00009315 // Action used to replace the default codegen action and turn privatization
9316 // off.
9317 PrePostActionTy NoPrivAction;
Samuel Antaodf158d52016-04-27 22:58:19 +00009318
9319 // Generate the code for the opening of the data environment. Capture all the
9320 // arguments of the runtime call by reference because they are used in the
9321 // closing of the region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009322 auto &&BeginThenGen = [this, &D, Device, &Info,
9323 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009324 // Fill up the arrays with all the mapped variables.
Samuel Antaocc10b852016-07-28 14:23:26 +00009325 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
Samuel Antaodf158d52016-04-27 22:58:19 +00009326 MappableExprsHandler::MapValuesArrayTy Pointers;
9327 MappableExprsHandler::MapValuesArrayTy Sizes;
9328 MappableExprsHandler::MapFlagsArrayTy MapTypes;
9329
9330 // Get map clause information.
9331 MappableExprsHandler MCHandler(D, CGF);
9332 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
Samuel Antaodf158d52016-04-27 22:58:19 +00009333
9334 // Fill up the arrays and create the arguments.
Samuel Antaocc10b852016-07-28 14:23:26 +00009335 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +00009336
9337 llvm::Value *BasePointersArrayArg = nullptr;
9338 llvm::Value *PointersArrayArg = nullptr;
9339 llvm::Value *SizesArrayArg = nullptr;
9340 llvm::Value *MapTypesArrayArg = nullptr;
9341 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00009342 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +00009343
9344 // Emit device ID if any.
9345 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +00009346 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009347 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009348 CGF.Int64Ty, /*isSigned=*/true);
9349 } else {
9350 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9351 }
Samuel Antaodf158d52016-04-27 22:58:19 +00009352
9353 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009354 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +00009355
9356 llvm::Value *OffloadingArgs[] = {
9357 DeviceID, PointerNum, BasePointersArrayArg,
9358 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009359 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin),
Samuel Antaodf158d52016-04-27 22:58:19 +00009360 OffloadingArgs);
Samuel Antaocc10b852016-07-28 14:23:26 +00009361
9362 // If device pointer privatization is required, emit the body of the region
9363 // here. It will have to be duplicated: with and without privatization.
9364 if (!Info.CaptureDeviceAddrMap.empty())
9365 CodeGen(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +00009366 };
9367
9368 // Generate code for the closing of the data region.
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009369 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF,
9370 PrePostActionTy &) {
Samuel Antaocc10b852016-07-28 14:23:26 +00009371 assert(Info.isValid() && "Invalid data environment closing arguments.");
Samuel Antaodf158d52016-04-27 22:58:19 +00009372
9373 llvm::Value *BasePointersArrayArg = nullptr;
9374 llvm::Value *PointersArrayArg = nullptr;
9375 llvm::Value *SizesArrayArg = nullptr;
9376 llvm::Value *MapTypesArrayArg = nullptr;
9377 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg,
Samuel Antaocc10b852016-07-28 14:23:26 +00009378 SizesArrayArg, MapTypesArrayArg, Info);
Samuel Antaodf158d52016-04-27 22:58:19 +00009379
9380 // Emit device ID if any.
9381 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +00009382 if (Device) {
Samuel Antaodf158d52016-04-27 22:58:19 +00009383 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009384 CGF.Int64Ty, /*isSigned=*/true);
9385 } else {
9386 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9387 }
Samuel Antaodf158d52016-04-27 22:58:19 +00009388
9389 // Emit the number of elements in the offloading arrays.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009390 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs);
Samuel Antaodf158d52016-04-27 22:58:19 +00009391
9392 llvm::Value *OffloadingArgs[] = {
9393 DeviceID, PointerNum, BasePointersArrayArg,
9394 PointersArrayArg, SizesArrayArg, MapTypesArrayArg};
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009395 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end),
Samuel Antaodf158d52016-04-27 22:58:19 +00009396 OffloadingArgs);
9397 };
9398
Samuel Antaocc10b852016-07-28 14:23:26 +00009399 // If we need device pointer privatization, we need to emit the body of the
9400 // region with no privatization in the 'else' branch of the conditional.
9401 // Otherwise, we don't have to do anything.
9402 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF,
9403 PrePostActionTy &) {
9404 if (!Info.CaptureDeviceAddrMap.empty()) {
9405 CodeGen.setAction(NoPrivAction);
9406 CodeGen(CGF);
9407 }
9408 };
9409
9410 // We don't have to do anything to close the region if the if clause evaluates
9411 // to false.
9412 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {};
Samuel Antaodf158d52016-04-27 22:58:19 +00009413
9414 if (IfCond) {
Samuel Antaocc10b852016-07-28 14:23:26 +00009415 emitOMPIfClause(CGF, IfCond, BeginThenGen, BeginElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +00009416 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +00009417 RegionCodeGenTy RCG(BeginThenGen);
9418 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +00009419 }
9420
Samuel Antaocc10b852016-07-28 14:23:26 +00009421 // If we don't require privatization of device pointers, we emit the body in
9422 // between the runtime calls. This avoids duplicating the body code.
9423 if (Info.CaptureDeviceAddrMap.empty()) {
9424 CodeGen.setAction(NoPrivAction);
9425 CodeGen(CGF);
9426 }
Samuel Antaodf158d52016-04-27 22:58:19 +00009427
9428 if (IfCond) {
Samuel Antaocc10b852016-07-28 14:23:26 +00009429 emitOMPIfClause(CGF, IfCond, EndThenGen, EndElseGen);
Samuel Antaodf158d52016-04-27 22:58:19 +00009430 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +00009431 RegionCodeGenTy RCG(EndThenGen);
9432 RCG(CGF);
Samuel Antaodf158d52016-04-27 22:58:19 +00009433 }
9434}
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009435
Samuel Antao8d2d7302016-05-26 18:30:22 +00009436void CGOpenMPRuntime::emitTargetDataStandAloneCall(
Samuel Antao8dd66282016-04-27 23:14:30 +00009437 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
9438 const Expr *Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009439 if (!CGF.HaveInsertPoint())
9440 return;
9441
Samuel Antao8dd66282016-04-27 23:14:30 +00009442 assert((isa<OMPTargetEnterDataDirective>(D) ||
Samuel Antao8d2d7302016-05-26 18:30:22 +00009443 isa<OMPTargetExitDataDirective>(D) ||
9444 isa<OMPTargetUpdateDirective>(D)) &&
9445 "Expecting either target enter, exit data, or update directives.");
Samuel Antao8dd66282016-04-27 23:14:30 +00009446
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009447 CodeGenFunction::OMPTargetDataInfo InputInfo;
9448 llvm::Value *MapTypesArray = nullptr;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009449 // Generate the code for the opening of the data environment.
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009450 auto &&ThenGen = [this, &D, Device, &InputInfo,
9451 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009452 // Emit device ID if any.
9453 llvm::Value *DeviceID = nullptr;
George Rokos63bc9d62017-11-21 18:25:12 +00009454 if (Device) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009455 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device),
George Rokos63bc9d62017-11-21 18:25:12 +00009456 CGF.Int64Ty, /*isSigned=*/true);
9457 } else {
9458 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF);
9459 }
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009460
9461 // Emit the number of elements in the offloading arrays.
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009462 llvm::Constant *PointerNum =
9463 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009464
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009465 llvm::Value *OffloadingArgs[] = {DeviceID,
9466 PointerNum,
9467 InputInfo.BasePointersArray.getPointer(),
9468 InputInfo.PointersArray.getPointer(),
9469 InputInfo.SizesArray.getPointer(),
9470 MapTypesArray};
Samuel Antao8d2d7302016-05-26 18:30:22 +00009471
Samuel Antao8d2d7302016-05-26 18:30:22 +00009472 // Select the right runtime function call for each expected standalone
9473 // directive.
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00009474 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>();
Samuel Antao8d2d7302016-05-26 18:30:22 +00009475 OpenMPRTLFunction RTLFn;
9476 switch (D.getDirectiveKind()) {
Samuel Antao8d2d7302016-05-26 18:30:22 +00009477 case OMPD_target_enter_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00009478 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait
9479 : OMPRTL__tgt_target_data_begin;
Samuel Antao8d2d7302016-05-26 18:30:22 +00009480 break;
9481 case OMPD_target_exit_data:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00009482 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait
9483 : OMPRTL__tgt_target_data_end;
Samuel Antao8d2d7302016-05-26 18:30:22 +00009484 break;
9485 case OMPD_target_update:
Alexey Bataev0cc6b8e2017-12-14 17:00:17 +00009486 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait
9487 : OMPRTL__tgt_target_data_update;
Samuel Antao8d2d7302016-05-26 18:30:22 +00009488 break;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009489 case OMPD_parallel:
9490 case OMPD_for:
9491 case OMPD_parallel_for:
9492 case OMPD_parallel_sections:
9493 case OMPD_for_simd:
9494 case OMPD_parallel_for_simd:
9495 case OMPD_cancel:
9496 case OMPD_cancellation_point:
9497 case OMPD_ordered:
9498 case OMPD_threadprivate:
Alexey Bataev25ed0c02019-03-07 17:54:44 +00009499 case OMPD_allocate:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009500 case OMPD_task:
9501 case OMPD_simd:
9502 case OMPD_sections:
9503 case OMPD_section:
9504 case OMPD_single:
9505 case OMPD_master:
9506 case OMPD_critical:
9507 case OMPD_taskyield:
9508 case OMPD_barrier:
9509 case OMPD_taskwait:
9510 case OMPD_taskgroup:
9511 case OMPD_atomic:
9512 case OMPD_flush:
9513 case OMPD_teams:
9514 case OMPD_target_data:
9515 case OMPD_distribute:
9516 case OMPD_distribute_simd:
9517 case OMPD_distribute_parallel_for:
9518 case OMPD_distribute_parallel_for_simd:
9519 case OMPD_teams_distribute:
9520 case OMPD_teams_distribute_simd:
9521 case OMPD_teams_distribute_parallel_for:
9522 case OMPD_teams_distribute_parallel_for_simd:
9523 case OMPD_declare_simd:
9524 case OMPD_declare_target:
9525 case OMPD_end_declare_target:
9526 case OMPD_declare_reduction:
Michael Kruse251e1482019-02-01 20:25:04 +00009527 case OMPD_declare_mapper:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009528 case OMPD_taskloop:
9529 case OMPD_taskloop_simd:
9530 case OMPD_target:
9531 case OMPD_target_simd:
9532 case OMPD_target_teams_distribute:
9533 case OMPD_target_teams_distribute_simd:
9534 case OMPD_target_teams_distribute_parallel_for:
9535 case OMPD_target_teams_distribute_parallel_for_simd:
9536 case OMPD_target_teams:
9537 case OMPD_target_parallel:
9538 case OMPD_target_parallel_for:
9539 case OMPD_target_parallel_for_simd:
Kelvin Li1408f912018-09-26 04:28:39 +00009540 case OMPD_requires:
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009541 case OMPD_unknown:
9542 llvm_unreachable("Unexpected standalone target data directive.");
9543 break;
Samuel Antao8d2d7302016-05-26 18:30:22 +00009544 }
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009545 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009546 };
9547
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009548 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray](
9549 CodeGenFunction &CGF, PrePostActionTy &) {
9550 // Fill up the arrays with all the mapped variables.
9551 MappableExprsHandler::MapBaseValuesArrayTy BasePointers;
9552 MappableExprsHandler::MapValuesArrayTy Pointers;
9553 MappableExprsHandler::MapValuesArrayTy Sizes;
9554 MappableExprsHandler::MapFlagsArrayTy MapTypes;
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009555
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009556 // Get map clause information.
9557 MappableExprsHandler MEHandler(D, CGF);
9558 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes);
9559
9560 TargetDataInfo Info;
9561 // Fill up the arrays and create the arguments.
9562 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info);
9563 emitOffloadingArraysArgument(CGF, Info.BasePointersArray,
9564 Info.PointersArray, Info.SizesArray,
9565 Info.MapTypesArray, Info);
9566 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs;
9567 InputInfo.BasePointersArray =
9568 Address(Info.BasePointersArray, CGM.getPointerAlign());
9569 InputInfo.PointersArray =
9570 Address(Info.PointersArray, CGM.getPointerAlign());
9571 InputInfo.SizesArray =
9572 Address(Info.SizesArray, CGM.getPointerAlign());
9573 MapTypesArray = Info.MapTypesArray;
9574 if (D.hasClausesOfKind<OMPDependClause>())
9575 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo);
9576 else
Alexey Bataev768f1f22018-01-09 19:59:25 +00009577 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009578 };
9579
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009580 if (IfCond) {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009581 emitOMPIfClause(CGF, IfCond, TargetThenGen,
9582 [](CodeGenFunction &CGF, PrePostActionTy &) {});
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009583 } else {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00009584 RegionCodeGenTy ThenRCG(TargetThenGen);
9585 ThenRCG(CGF);
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00009586 }
9587}
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009588
9589namespace {
9590 /// Kind of parameter in a function with 'declare simd' directive.
9591 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector };
9592 /// Attribute set of the parameter.
9593 struct ParamAttrTy {
9594 ParamKindTy Kind = Vector;
9595 llvm::APSInt StrideOrArg;
9596 llvm::APSInt Alignment;
9597 };
9598} // namespace
9599
9600static unsigned evaluateCDTSize(const FunctionDecl *FD,
9601 ArrayRef<ParamAttrTy> ParamAttrs) {
9602 // Every vector variant of a SIMD-enabled function has a vector length (VLEN).
9603 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument
9604 // of that clause. The VLEN value must be power of 2.
9605 // In other case the notion of the function`s "characteristic data type" (CDT)
9606 // is used to compute the vector length.
9607 // CDT is defined in the following order:
9608 // a) For non-void function, the CDT is the return type.
9609 // b) If the function has any non-uniform, non-linear parameters, then the
9610 // CDT is the type of the first such parameter.
9611 // c) If the CDT determined by a) or b) above is struct, union, or class
9612 // type which is pass-by-value (except for the type that maps to the
9613 // built-in complex data type), the characteristic data type is int.
9614 // d) If none of the above three cases is applicable, the CDT is int.
9615 // The VLEN is then determined based on the CDT and the size of vector
9616 // register of that ISA for which current vector version is generated. The
9617 // VLEN is computed using the formula below:
9618 // VLEN = sizeof(vector_register) / sizeof(CDT),
9619 // where vector register size specified in section 3.2.1 Registers and the
9620 // Stack Frame of original AMD64 ABI document.
9621 QualType RetType = FD->getReturnType();
9622 if (RetType.isNull())
9623 return 0;
9624 ASTContext &C = FD->getASTContext();
9625 QualType CDT;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009626 if (!RetType.isNull() && !RetType->isVoidType()) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009627 CDT = RetType;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009628 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009629 unsigned Offset = 0;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009630 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009631 if (ParamAttrs[Offset].Kind == Vector)
9632 CDT = C.getPointerType(C.getRecordType(MD->getParent()));
9633 ++Offset;
9634 }
9635 if (CDT.isNull()) {
9636 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
9637 if (ParamAttrs[I + Offset].Kind == Vector) {
9638 CDT = FD->getParamDecl(I)->getType();
9639 break;
9640 }
9641 }
9642 }
9643 }
9644 if (CDT.isNull())
9645 CDT = C.IntTy;
9646 CDT = CDT->getCanonicalTypeUnqualified();
9647 if (CDT->isRecordType() || CDT->isUnionType())
9648 CDT = C.IntTy;
9649 return C.getTypeSize(CDT);
9650}
9651
9652static void
9653emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
Benjamin Kramer81cb4b72016-11-24 16:01:20 +00009654 const llvm::APSInt &VLENVal,
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009655 ArrayRef<ParamAttrTy> ParamAttrs,
9656 OMPDeclareSimdDeclAttr::BranchStateTy State) {
9657 struct ISADataTy {
9658 char ISA;
9659 unsigned VecRegSize;
9660 };
9661 ISADataTy ISAData[] = {
9662 {
9663 'b', 128
9664 }, // SSE
9665 {
9666 'c', 256
9667 }, // AVX
9668 {
9669 'd', 256
9670 }, // AVX2
9671 {
9672 'e', 512
9673 }, // AVX512
9674 };
9675 llvm::SmallVector<char, 2> Masked;
9676 switch (State) {
9677 case OMPDeclareSimdDeclAttr::BS_Undefined:
9678 Masked.push_back('N');
9679 Masked.push_back('M');
9680 break;
9681 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
9682 Masked.push_back('N');
9683 break;
9684 case OMPDeclareSimdDeclAttr::BS_Inbranch:
9685 Masked.push_back('M');
9686 break;
9687 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009688 for (char Mask : Masked) {
9689 for (const ISADataTy &Data : ISAData) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009690 SmallString<256> Buffer;
9691 llvm::raw_svector_ostream Out(Buffer);
9692 Out << "_ZGV" << Data.ISA << Mask;
9693 if (!VLENVal) {
9694 Out << llvm::APSInt::getUnsigned(Data.VecRegSize /
9695 evaluateCDTSize(FD, ParamAttrs));
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009696 } else {
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009697 Out << VLENVal;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +00009698 }
9699 for (const ParamAttrTy &ParamAttr : ParamAttrs) {
Alexey Bataevc7a82b42016-05-06 09:40:08 +00009700 switch (ParamAttr.Kind){
9701 case LinearWithVarStride:
9702 Out << 's' << ParamAttr.StrideOrArg;
9703 break;
9704 case Linear:
9705 Out << 'l';
9706 if (!!ParamAttr.StrideOrArg)
9707 Out << ParamAttr.StrideOrArg;
9708 break;
9709 case Uniform:
9710 Out << 'u';
9711 break;
9712 case Vector:
9713 Out << 'v';
9714 break;
9715 }
9716 if (!!ParamAttr.Alignment)
9717 Out << 'a' << ParamAttr.Alignment;
9718 }
9719 Out << '_' << Fn->getName();
9720 Fn->addFnAttr(Out.str());
9721 }
9722 }
9723}
9724
Alexey Bataeva0a22642019-04-16 13:56:21 +00009725// This are the Functions that are needed to mangle the name of the
9726// vector functions generated by the compiler, according to the rules
9727// defined in the "Vector Function ABI specifications for AArch64",
9728// available at
9729// https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi.
9730
9731/// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI.
9732///
9733/// TODO: Need to implement the behavior for reference marked with a
9734/// var or no linear modifiers (1.b in the section). For this, we
9735/// need to extend ParamKindTy to support the linear modifiers.
9736static bool getAArch64MTV(QualType QT, ParamKindTy Kind) {
9737 QT = QT.getCanonicalType();
9738
9739 if (QT->isVoidType())
9740 return false;
9741
9742 if (Kind == ParamKindTy::Uniform)
9743 return false;
9744
9745 if (Kind == ParamKindTy::Linear)
9746 return false;
9747
9748 // TODO: Handle linear references with modifiers
9749
9750 if (Kind == ParamKindTy::LinearWithVarStride)
9751 return false;
9752
9753 return true;
9754}
9755
9756/// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI.
9757static bool getAArch64PBV(QualType QT, ASTContext &C) {
9758 QT = QT.getCanonicalType();
9759 unsigned Size = C.getTypeSize(QT);
9760
9761 // Only scalars and complex within 16 bytes wide set PVB to true.
9762 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128)
9763 return false;
9764
9765 if (QT->isFloatingType())
9766 return true;
9767
9768 if (QT->isIntegerType())
9769 return true;
9770
9771 if (QT->isPointerType())
9772 return true;
9773
9774 // TODO: Add support for complex types (section 3.1.2, item 2).
9775
9776 return false;
9777}
9778
9779/// Computes the lane size (LS) of a return type or of an input parameter,
9780/// as defined by `LS(P)` in 3.2.1 of the AAVFABI.
9781/// TODO: Add support for references, section 3.2.1, item 1.
9782static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) {
9783 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) {
9784 QualType PTy = QT.getCanonicalType()->getPointeeType();
9785 if (getAArch64PBV(PTy, C))
9786 return C.getTypeSize(PTy);
9787 }
9788 if (getAArch64PBV(QT, C))
9789 return C.getTypeSize(QT);
9790
9791 return C.getTypeSize(C.getUIntPtrType());
9792}
9793
9794// Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the
9795// signature of the scalar function, as defined in 3.2.2 of the
9796// AAVFABI.
9797static std::tuple<unsigned, unsigned, bool>
9798getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) {
9799 QualType RetType = FD->getReturnType().getCanonicalType();
9800
9801 ASTContext &C = FD->getASTContext();
9802
9803 bool OutputBecomesInput = false;
9804
9805 llvm::SmallVector<unsigned, 8> Sizes;
9806 if (!RetType->isVoidType()) {
9807 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C));
9808 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {}))
9809 OutputBecomesInput = true;
9810 }
9811 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) {
9812 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType();
9813 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C));
9814 }
9815
9816 assert(!Sizes.empty() && "Unable to determine NDS and WDS.");
9817 // The LS of a function parameter / return value can only be a power
9818 // of 2, starting from 8 bits, up to 128.
9819 assert(std::all_of(Sizes.begin(), Sizes.end(),
9820 [](unsigned Size) {
9821 return Size == 8 || Size == 16 || Size == 32 ||
9822 Size == 64 || Size == 128;
9823 }) &&
9824 "Invalid size");
9825
9826 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)),
9827 *std::max_element(std::begin(Sizes), std::end(Sizes)),
9828 OutputBecomesInput);
9829}
9830
9831/// Mangle the parameter part of the vector function name according to
9832/// their OpenMP classification. The mangling function is defined in
9833/// section 3.5 of the AAVFABI.
9834static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) {
9835 SmallString<256> Buffer;
9836 llvm::raw_svector_ostream Out(Buffer);
9837 for (const auto &ParamAttr : ParamAttrs) {
9838 switch (ParamAttr.Kind) {
9839 case LinearWithVarStride:
9840 Out << "ls" << ParamAttr.StrideOrArg;
9841 break;
9842 case Linear:
9843 Out << 'l';
9844 // Don't print the step value if it is not present or if it is
9845 // equal to 1.
9846 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1)
9847 Out << ParamAttr.StrideOrArg;
9848 break;
9849 case Uniform:
9850 Out << 'u';
9851 break;
9852 case Vector:
9853 Out << 'v';
9854 break;
9855 }
9856
9857 if (!!ParamAttr.Alignment)
9858 Out << 'a' << ParamAttr.Alignment;
9859 }
9860
9861 return Out.str();
9862}
9863
9864// Function used to add the attribute. The parameter `VLEN` is
9865// templated to allow the use of "x" when targeting scalable functions
9866// for SVE.
9867template <typename T>
9868static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix,
9869 char ISA, StringRef ParSeq,
9870 StringRef MangledName, bool OutputBecomesInput,
9871 llvm::Function *Fn) {
9872 SmallString<256> Buffer;
9873 llvm::raw_svector_ostream Out(Buffer);
9874 Out << Prefix << ISA << LMask << VLEN;
9875 if (OutputBecomesInput)
9876 Out << "v";
9877 Out << ParSeq << "_" << MangledName;
9878 Fn->addFnAttr(Out.str());
9879}
9880
9881// Helper function to generate the Advanced SIMD names depending on
9882// the value of the NDS when simdlen is not present.
9883static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask,
9884 StringRef Prefix, char ISA,
9885 StringRef ParSeq, StringRef MangledName,
9886 bool OutputBecomesInput,
9887 llvm::Function *Fn) {
9888 switch (NDS) {
9889 case 8:
9890 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
9891 OutputBecomesInput, Fn);
9892 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName,
9893 OutputBecomesInput, Fn);
9894 break;
9895 case 16:
9896 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
9897 OutputBecomesInput, Fn);
9898 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName,
9899 OutputBecomesInput, Fn);
9900 break;
9901 case 32:
9902 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
9903 OutputBecomesInput, Fn);
9904 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName,
9905 OutputBecomesInput, Fn);
9906 break;
9907 case 64:
9908 case 128:
9909 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName,
9910 OutputBecomesInput, Fn);
9911 break;
9912 default:
9913 llvm_unreachable("Scalar type is too wide.");
9914 }
9915}
9916
9917/// Emit vector function attributes for AArch64, as defined in the AAVFABI.
9918static void emitAArch64DeclareSimdFunction(
9919 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN,
9920 ArrayRef<ParamAttrTy> ParamAttrs,
9921 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName,
9922 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) {
9923
9924 // Get basic data for building the vector signature.
9925 const auto Data = getNDSWDS(FD, ParamAttrs);
9926 const unsigned NDS = std::get<0>(Data);
9927 const unsigned WDS = std::get<1>(Data);
9928 const bool OutputBecomesInput = std::get<2>(Data);
9929
9930 // Check the values provided via `simdlen` by the user.
9931 // 1. A `simdlen(1)` doesn't produce vector signatures,
9932 if (UserVLEN == 1) {
9933 unsigned DiagID = CGM.getDiags().getCustomDiagID(
9934 DiagnosticsEngine::Warning,
9935 "The clause simdlen(1) has no effect when targeting aarch64.");
9936 CGM.getDiags().Report(SLoc, DiagID);
9937 return;
9938 }
9939
9940 // 2. Section 3.3.1, item 1: user input must be a power of 2 for
9941 // Advanced SIMD output.
9942 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) {
9943 unsigned DiagID = CGM.getDiags().getCustomDiagID(
9944 DiagnosticsEngine::Warning, "The value specified in simdlen must be a "
9945 "power of 2 when targeting Advanced SIMD.");
9946 CGM.getDiags().Report(SLoc, DiagID);
9947 return;
9948 }
9949
9950 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural
9951 // limits.
9952 if (ISA == 's' && UserVLEN != 0) {
9953 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) {
9954 unsigned DiagID = CGM.getDiags().getCustomDiagID(
9955 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit "
9956 "lanes in the architectural constraints "
9957 "for SVE (min is 128-bit, max is "
9958 "2048-bit, by steps of 128-bit)");
9959 CGM.getDiags().Report(SLoc, DiagID) << WDS;
9960 return;
9961 }
9962 }
9963
9964 // Sort out parameter sequence.
9965 const std::string ParSeq = mangleVectorParameters(ParamAttrs);
9966 StringRef Prefix = "_ZGV";
9967 // Generate simdlen from user input (if any).
9968 if (UserVLEN) {
9969 if (ISA == 's') {
9970 // SVE generates only a masked function.
9971 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
9972 OutputBecomesInput, Fn);
9973 } else {
9974 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
9975 // Advanced SIMD generates one or two functions, depending on
9976 // the `[not]inbranch` clause.
9977 switch (State) {
9978 case OMPDeclareSimdDeclAttr::BS_Undefined:
9979 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
9980 OutputBecomesInput, Fn);
9981 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
9982 OutputBecomesInput, Fn);
9983 break;
9984 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
9985 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName,
9986 OutputBecomesInput, Fn);
9987 break;
9988 case OMPDeclareSimdDeclAttr::BS_Inbranch:
9989 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName,
9990 OutputBecomesInput, Fn);
9991 break;
9992 }
9993 }
9994 } else {
9995 // If no user simdlen is provided, follow the AAVFABI rules for
9996 // generating the vector length.
9997 if (ISA == 's') {
9998 // SVE, section 3.4.1, item 1.
9999 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName,
10000 OutputBecomesInput, Fn);
10001 } else {
10002 assert(ISA == 'n' && "Expected ISA either 's' or 'n'.");
10003 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or
10004 // two vector names depending on the use of the clause
10005 // `[not]inbranch`.
10006 switch (State) {
10007 case OMPDeclareSimdDeclAttr::BS_Undefined:
10008 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10009 OutputBecomesInput, Fn);
10010 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10011 OutputBecomesInput, Fn);
10012 break;
10013 case OMPDeclareSimdDeclAttr::BS_Notinbranch:
10014 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName,
10015 OutputBecomesInput, Fn);
10016 break;
10017 case OMPDeclareSimdDeclAttr::BS_Inbranch:
10018 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName,
10019 OutputBecomesInput, Fn);
10020 break;
10021 }
10022 }
10023 }
10024}
10025
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010026void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
10027 llvm::Function *Fn) {
10028 ASTContext &C = CGM.getContext();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010029 FD = FD->getMostRecentDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010030 // Map params to their positions in function decl.
10031 llvm::DenseMap<const Decl *, unsigned> ParamPositions;
10032 if (isa<CXXMethodDecl>(FD))
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010033 ParamPositions.try_emplace(FD, 0);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010034 unsigned ParamPos = ParamPositions.size();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010035 for (const ParmVarDecl *P : FD->parameters()) {
10036 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos);
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010037 ++ParamPos;
10038 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010039 while (FD) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010040 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010041 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
10042 // Mark uniform parameters.
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010043 for (const Expr *E : Attr->uniforms()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010044 E = E->IgnoreParenImpCasts();
10045 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010046 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010047 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010048 } else {
10049 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10050 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010051 Pos = ParamPositions[PVD];
10052 }
10053 ParamAttrs[Pos].Kind = Uniform;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010054 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010055 // Get alignment info.
10056 auto NI = Attr->alignments_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010057 for (const Expr *E : Attr->aligneds()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010058 E = E->IgnoreParenImpCasts();
10059 unsigned Pos;
10060 QualType ParmTy;
10061 if (isa<CXXThisExpr>(E)) {
10062 Pos = ParamPositions[FD];
10063 ParmTy = E->getType();
10064 } else {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010065 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10066 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010067 Pos = ParamPositions[PVD];
10068 ParmTy = PVD->getType();
10069 }
10070 ParamAttrs[Pos].Alignment =
10071 (*NI)
10072 ? (*NI)->EvaluateKnownConstInt(C)
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010073 : llvm::APSInt::getUnsigned(
10074 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy))
10075 .getQuantity());
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010076 ++NI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010077 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010078 // Mark linear parameters.
10079 auto SI = Attr->steps_begin();
10080 auto MI = Attr->modifiers_begin();
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010081 for (const Expr *E : Attr->linears()) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010082 E = E->IgnoreParenImpCasts();
10083 unsigned Pos;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010084 if (isa<CXXThisExpr>(E)) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010085 Pos = ParamPositions[FD];
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010086 } else {
10087 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl())
10088 ->getCanonicalDecl();
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010089 Pos = ParamPositions[PVD];
10090 }
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010091 ParamAttrTy &ParamAttr = ParamAttrs[Pos];
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010092 ParamAttr.Kind = Linear;
10093 if (*SI) {
Fangrui Song407659a2018-11-30 23:41:18 +000010094 Expr::EvalResult Result;
10095 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) {
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010096 if (const auto *DRE =
10097 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) {
10098 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010099 ParamAttr.Kind = LinearWithVarStride;
10100 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(
10101 ParamPositions[StridePVD->getCanonicalDecl()]);
10102 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010103 }
Fangrui Song407659a2018-11-30 23:41:18 +000010104 } else {
10105 ParamAttr.StrideOrArg = Result.Val.getInt();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010106 }
10107 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010108 ++SI;
10109 ++MI;
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010110 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010111 llvm::APSInt VLENVal;
Alexey Bataeva0a22642019-04-16 13:56:21 +000010112 SourceLocation ExprLoc;
10113 const Expr *VLENExpr = Attr->getSimdlen();
10114 if (VLENExpr) {
10115 VLENVal = VLENExpr->EvaluateKnownConstInt(C);
10116 ExprLoc = VLENExpr->getExprLoc();
10117 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010118 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
10119 if (CGM.getTriple().getArch() == llvm::Triple::x86 ||
Alexey Bataeva0a22642019-04-16 13:56:21 +000010120 CGM.getTriple().getArch() == llvm::Triple::x86_64) {
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010121 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
Alexey Bataeva0a22642019-04-16 13:56:21 +000010122 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) {
10123 unsigned VLEN = VLENVal.getExtValue();
10124 StringRef MangledName = Fn->getName();
10125 if (CGM.getTarget().hasFeature("sve"))
10126 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10127 MangledName, 's', 128, Fn, ExprLoc);
10128 if (CGM.getTarget().hasFeature("neon"))
10129 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State,
10130 MangledName, 'n', 128, Fn, ExprLoc);
10131 }
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010132 }
Alexey Bataev20cf67c2018-03-02 18:07:00 +000010133 FD = FD->getPreviousDecl();
Alexey Bataevc7a82b42016-05-06 09:40:08 +000010134 }
10135}
Alexey Bataev8b427062016-05-25 12:36:08 +000010136
10137namespace {
10138/// Cleanup action for doacross support.
10139class DoacrossCleanupTy final : public EHScopeStack::Cleanup {
10140public:
10141 static const int DoacrossFinArgs = 2;
10142
10143private:
James Y Knight9871db02019-02-05 16:42:33 +000010144 llvm::FunctionCallee RTLFn;
Alexey Bataev8b427062016-05-25 12:36:08 +000010145 llvm::Value *Args[DoacrossFinArgs];
10146
10147public:
James Y Knight9871db02019-02-05 16:42:33 +000010148 DoacrossCleanupTy(llvm::FunctionCallee RTLFn,
10149 ArrayRef<llvm::Value *> CallArgs)
Alexey Bataev8b427062016-05-25 12:36:08 +000010150 : RTLFn(RTLFn) {
10151 assert(CallArgs.size() == DoacrossFinArgs);
10152 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10153 }
10154 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10155 if (!CGF.HaveInsertPoint())
10156 return;
10157 CGF.EmitRuntimeCall(RTLFn, Args);
10158 }
10159};
10160} // namespace
10161
10162void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000010163 const OMPLoopDirective &D,
10164 ArrayRef<Expr *> NumIterations) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010165 if (!CGF.HaveInsertPoint())
10166 return;
10167
10168 ASTContext &C = CGM.getContext();
10169 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true);
10170 RecordDecl *RD;
10171 if (KmpDimTy.isNull()) {
10172 // Build struct kmp_dim { // loop bounds info casted to kmp_int64
10173 // kmp_int64 lo; // lower
10174 // kmp_int64 up; // upper
10175 // kmp_int64 st; // stride
10176 // };
10177 RD = C.buildImplicitRecord("kmp_dim");
10178 RD->startDefinition();
10179 addFieldToRecordDecl(C, RD, Int64Ty);
10180 addFieldToRecordDecl(C, RD, Int64Ty);
10181 addFieldToRecordDecl(C, RD, Int64Ty);
10182 RD->completeDefinition();
10183 KmpDimTy = C.getRecordType(RD);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010184 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010185 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl());
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010186 }
Alexey Bataevf138fda2018-08-13 19:04:24 +000010187 llvm::APInt Size(/*numBits=*/32, NumIterations.size());
10188 QualType ArrayTy =
10189 C.getConstantArrayType(KmpDimTy, Size, ArrayType::Normal, 0);
Alexey Bataev8b427062016-05-25 12:36:08 +000010190
Alexey Bataevf138fda2018-08-13 19:04:24 +000010191 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims");
10192 CGF.EmitNullInitialization(DimsAddr, ArrayTy);
Alexey Bataev8b427062016-05-25 12:36:08 +000010193 enum { LowerFD = 0, UpperFD, StrideFD };
10194 // Fill dims with data.
Alexey Bataevf138fda2018-08-13 19:04:24 +000010195 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) {
James Y Knight751fe282019-02-09 22:22:28 +000010196 LValue DimsLVal = CGF.MakeAddrLValue(
10197 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010198 // dims.upper = num_iterations;
10199 LValue UpperLVal = CGF.EmitLValueForField(
10200 DimsLVal, *std::next(RD->field_begin(), UpperFD));
10201 llvm::Value *NumIterVal =
10202 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]),
10203 D.getNumIterations()->getType(), Int64Ty,
10204 D.getNumIterations()->getExprLoc());
10205 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal);
10206 // dims.stride = 1;
10207 LValue StrideLVal = CGF.EmitLValueForField(
10208 DimsLVal, *std::next(RD->field_begin(), StrideFD));
10209 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1),
10210 StrideLVal);
10211 }
Alexey Bataev8b427062016-05-25 12:36:08 +000010212
10213 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid,
10214 // kmp_int32 num_dims, struct kmp_dim * dims);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010215 llvm::Value *Args[] = {
10216 emitUpdateLocation(CGF, D.getBeginLoc()),
10217 getThreadID(CGF, D.getBeginLoc()),
10218 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()),
10219 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
James Y Knight751fe282019-02-09 22:22:28 +000010220 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(),
Alexey Bataevf138fda2018-08-13 19:04:24 +000010221 CGM.VoidPtrTy)};
Alexey Bataev8b427062016-05-25 12:36:08 +000010222
James Y Knight9871db02019-02-05 16:42:33 +000010223 llvm::FunctionCallee RTLFn =
10224 createRuntimeFunction(OMPRTL__kmpc_doacross_init);
Alexey Bataev8b427062016-05-25 12:36:08 +000010225 CGF.EmitRuntimeCall(RTLFn, Args);
10226 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = {
Stephen Kelly1c301dc2018-08-09 21:09:38 +000010227 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())};
James Y Knight9871db02019-02-05 16:42:33 +000010228 llvm::FunctionCallee FiniRTLFn =
10229 createRuntimeFunction(OMPRTL__kmpc_doacross_fini);
Alexey Bataev8b427062016-05-25 12:36:08 +000010230 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
10231 llvm::makeArrayRef(FiniArgs));
10232}
10233
10234void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
10235 const OMPDependClause *C) {
10236 QualType Int64Ty =
10237 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010238 llvm::APInt Size(/*numBits=*/32, C->getNumLoops());
10239 QualType ArrayTy = CGM.getContext().getConstantArrayType(
10240 Int64Ty, Size, ArrayType::Normal, 0);
10241 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr");
10242 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) {
10243 const Expr *CounterVal = C->getLoopData(I);
10244 assert(CounterVal);
10245 llvm::Value *CntVal = CGF.EmitScalarConversion(
10246 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty,
10247 CounterVal->getExprLoc());
James Y Knight751fe282019-02-09 22:22:28 +000010248 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I),
10249 /*Volatile=*/false, Int64Ty);
Alexey Bataevf138fda2018-08-13 19:04:24 +000010250 }
10251 llvm::Value *Args[] = {
10252 emitUpdateLocation(CGF, C->getBeginLoc()),
10253 getThreadID(CGF, C->getBeginLoc()),
James Y Knight751fe282019-02-09 22:22:28 +000010254 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()};
James Y Knight9871db02019-02-05 16:42:33 +000010255 llvm::FunctionCallee RTLFn;
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010256 if (C->getDependencyKind() == OMPC_DEPEND_source) {
Alexey Bataev8b427062016-05-25 12:36:08 +000010257 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post);
Alexey Bataeva4fa0b82018-04-16 17:59:34 +000010258 } else {
Alexey Bataev8b427062016-05-25 12:36:08 +000010259 assert(C->getDependencyKind() == OMPC_DEPEND_sink);
10260 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait);
10261 }
10262 CGF.EmitRuntimeCall(RTLFn, Args);
10263}
10264
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010265void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000010266 llvm::FunctionCallee Callee,
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010267 ArrayRef<llvm::Value *> Args) const {
10268 assert(Loc.isValid() && "Outlined function call location must be valid.");
Alexey Bataev3c595a62017-08-14 15:01:03 +000010269 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc);
10270
James Y Knight9871db02019-02-05 16:42:33 +000010271 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) {
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010272 if (Fn->doesNotThrow()) {
Alexey Bataev3c595a62017-08-14 15:01:03 +000010273 CGF.EmitNounwindRuntimeCall(Fn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010274 return;
10275 }
10276 }
Alexey Bataev3c595a62017-08-14 15:01:03 +000010277 CGF.EmitRuntimeCall(Callee, Args);
10278}
10279
10280void CGOpenMPRuntime::emitOutlinedFunctionCall(
James Y Knight9871db02019-02-05 16:42:33 +000010281 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn,
Alexey Bataev3c595a62017-08-14 15:01:03 +000010282 ArrayRef<llvm::Value *> Args) const {
Alexey Bataev7ef47a62018-02-22 18:33:31 +000010283 emitCall(CGF, Loc, OutlinedFn, Args);
Alexey Bataev2c7eee52017-08-04 19:10:54 +000010284}
Alexey Bataev3b8d5582017-08-08 18:04:06 +000010285
10286Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF,
10287 const VarDecl *NativeParam,
10288 const VarDecl *TargetParam) const {
10289 return CGF.GetAddrOfLocalVar(NativeParam);
10290}
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010291
Alexey Bataev4f680db2019-03-19 16:41:16 +000010292namespace {
10293/// Cleanup action for allocate support.
10294class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup {
10295public:
10296 static const int CleanupArgs = 3;
10297
10298private:
10299 llvm::FunctionCallee RTLFn;
10300 llvm::Value *Args[CleanupArgs];
10301
10302public:
10303 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn,
10304 ArrayRef<llvm::Value *> CallArgs)
10305 : RTLFn(RTLFn) {
10306 assert(CallArgs.size() == CleanupArgs &&
10307 "Size of arguments does not match.");
10308 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args));
10309 }
10310 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override {
10311 if (!CGF.HaveInsertPoint())
10312 return;
10313 CGF.EmitRuntimeCall(RTLFn, Args);
10314 }
10315};
10316} // namespace
10317
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000010318Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF,
10319 const VarDecl *VD) {
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010320 if (!VD)
10321 return Address::invalid();
Alexey Bataev4f680db2019-03-19 16:41:16 +000010322 const VarDecl *CVD = VD->getCanonicalDecl();
10323 if (!CVD->hasAttr<OMPAllocateDeclAttr>())
10324 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010325 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>();
10326 // Use the default allocation.
Alexey Bataev0fd3c682019-04-02 19:44:46 +000010327 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc &&
10328 !AA->getAllocator())
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010329 return Address::invalid();
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010330 llvm::Value *Size;
10331 CharUnits Align = CGM.getContext().getDeclAlign(CVD);
10332 if (CVD->getType()->isVariablyModifiedType()) {
10333 Size = CGF.getTypeSize(CVD->getType());
Alexey Bataev9c397812019-04-03 17:57:06 +000010334 // Align the size: ((size + align - 1) / align) * align
10335 Size = CGF.Builder.CreateNUWAdd(
10336 Size, CGM.getSize(Align - CharUnits::fromQuantity(1)));
10337 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align));
10338 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align));
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010339 } else {
10340 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType());
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010341 Size = CGM.getSize(Sz.alignTo(Align));
Alexey Bataev4f680db2019-03-19 16:41:16 +000010342 }
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010343 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc());
10344 assert(AA->getAllocator() &&
10345 "Expected allocator expression for non-default allocator.");
10346 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator());
Alexey Bataev6cf7b712019-04-08 19:06:42 +000010347 // According to the standard, the original allocator type is a enum (integer).
10348 // Convert to pointer type, if required.
10349 if (Allocator->getType()->isIntegerTy())
10350 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy);
10351 else if (Allocator->getType()->isPointerTy())
10352 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator,
10353 CGM.VoidPtrTy);
Alexey Bataev084b0c2f02019-03-21 20:36:16 +000010354 llvm::Value *Args[] = {ThreadID, Size, Allocator};
10355
10356 llvm::Value *Addr =
10357 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args,
10358 CVD->getName() + ".void.addr");
10359 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr,
10360 Allocator};
10361 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free);
10362
10363 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn,
10364 llvm::makeArrayRef(FiniArgs));
10365 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
10366 Addr,
10367 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())),
10368 CVD->getName() + ".addr");
10369 return Address(Addr, Align);
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +000010370}
10371
James Y Knight9871db02019-02-05 16:42:33 +000010372llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010373 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
10374 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
10375 llvm_unreachable("Not supported in SIMD-only mode");
10376}
10377
James Y Knight9871db02019-02-05 16:42:33 +000010378llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010379 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
10380 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) {
10381 llvm_unreachable("Not supported in SIMD-only mode");
10382}
10383
James Y Knight9871db02019-02-05 16:42:33 +000010384llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction(
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010385 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar,
10386 const VarDecl *PartIDVar, const VarDecl *TaskTVar,
10387 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
10388 bool Tied, unsigned &NumberOfParts) {
10389 llvm_unreachable("Not supported in SIMD-only mode");
10390}
10391
10392void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF,
10393 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000010394 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010395 ArrayRef<llvm::Value *> CapturedVars,
10396 const Expr *IfCond) {
10397 llvm_unreachable("Not supported in SIMD-only mode");
10398}
10399
10400void CGOpenMPSIMDRuntime::emitCriticalRegion(
10401 CodeGenFunction &CGF, StringRef CriticalName,
10402 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc,
10403 const Expr *Hint) {
10404 llvm_unreachable("Not supported in SIMD-only mode");
10405}
10406
10407void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF,
10408 const RegionCodeGenTy &MasterOpGen,
10409 SourceLocation Loc) {
10410 llvm_unreachable("Not supported in SIMD-only mode");
10411}
10412
10413void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF,
10414 SourceLocation Loc) {
10415 llvm_unreachable("Not supported in SIMD-only mode");
10416}
10417
10418void CGOpenMPSIMDRuntime::emitTaskgroupRegion(
10419 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen,
10420 SourceLocation Loc) {
10421 llvm_unreachable("Not supported in SIMD-only mode");
10422}
10423
10424void CGOpenMPSIMDRuntime::emitSingleRegion(
10425 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen,
10426 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars,
10427 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs,
10428 ArrayRef<const Expr *> AssignmentOps) {
10429 llvm_unreachable("Not supported in SIMD-only mode");
10430}
10431
10432void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF,
10433 const RegionCodeGenTy &OrderedOpGen,
10434 SourceLocation Loc,
10435 bool IsThreads) {
10436 llvm_unreachable("Not supported in SIMD-only mode");
10437}
10438
10439void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF,
10440 SourceLocation Loc,
10441 OpenMPDirectiveKind Kind,
10442 bool EmitChecks,
10443 bool ForceSimpleCall) {
10444 llvm_unreachable("Not supported in SIMD-only mode");
10445}
10446
10447void CGOpenMPSIMDRuntime::emitForDispatchInit(
10448 CodeGenFunction &CGF, SourceLocation Loc,
10449 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned,
10450 bool Ordered, const DispatchRTInput &DispatchValues) {
10451 llvm_unreachable("Not supported in SIMD-only mode");
10452}
10453
10454void CGOpenMPSIMDRuntime::emitForStaticInit(
10455 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind,
10456 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) {
10457 llvm_unreachable("Not supported in SIMD-only mode");
10458}
10459
10460void CGOpenMPSIMDRuntime::emitDistributeStaticInit(
10461 CodeGenFunction &CGF, SourceLocation Loc,
10462 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) {
10463 llvm_unreachable("Not supported in SIMD-only mode");
10464}
10465
10466void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF,
10467 SourceLocation Loc,
10468 unsigned IVSize,
10469 bool IVSigned) {
10470 llvm_unreachable("Not supported in SIMD-only mode");
10471}
10472
10473void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF,
10474 SourceLocation Loc,
10475 OpenMPDirectiveKind DKind) {
10476 llvm_unreachable("Not supported in SIMD-only mode");
10477}
10478
10479llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF,
10480 SourceLocation Loc,
10481 unsigned IVSize, bool IVSigned,
10482 Address IL, Address LB,
10483 Address UB, Address ST) {
10484 llvm_unreachable("Not supported in SIMD-only mode");
10485}
10486
10487void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF,
10488 llvm::Value *NumThreads,
10489 SourceLocation Loc) {
10490 llvm_unreachable("Not supported in SIMD-only mode");
10491}
10492
10493void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF,
10494 OpenMPProcBindClauseKind ProcBind,
10495 SourceLocation Loc) {
10496 llvm_unreachable("Not supported in SIMD-only mode");
10497}
10498
10499Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF,
10500 const VarDecl *VD,
10501 Address VDAddr,
10502 SourceLocation Loc) {
10503 llvm_unreachable("Not supported in SIMD-only mode");
10504}
10505
10506llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition(
10507 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit,
10508 CodeGenFunction *CGF) {
10509 llvm_unreachable("Not supported in SIMD-only mode");
10510}
10511
10512Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate(
10513 CodeGenFunction &CGF, QualType VarType, StringRef Name) {
10514 llvm_unreachable("Not supported in SIMD-only mode");
10515}
10516
10517void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF,
10518 ArrayRef<const Expr *> Vars,
10519 SourceLocation Loc) {
10520 llvm_unreachable("Not supported in SIMD-only mode");
10521}
10522
10523void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc,
10524 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000010525 llvm::Function *TaskFunction,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010526 QualType SharedsTy, Address Shareds,
10527 const Expr *IfCond,
10528 const OMPTaskDataTy &Data) {
10529 llvm_unreachable("Not supported in SIMD-only mode");
10530}
10531
10532void CGOpenMPSIMDRuntime::emitTaskLoopCall(
10533 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000010534 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010535 const Expr *IfCond, const OMPTaskDataTy &Data) {
10536 llvm_unreachable("Not supported in SIMD-only mode");
10537}
10538
10539void CGOpenMPSIMDRuntime::emitReduction(
10540 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates,
10541 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs,
10542 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) {
10543 assert(Options.SimpleReduction && "Only simple reduction is expected.");
10544 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs,
10545 ReductionOps, Options);
10546}
10547
10548llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit(
10549 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs,
10550 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) {
10551 llvm_unreachable("Not supported in SIMD-only mode");
10552}
10553
10554void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF,
10555 SourceLocation Loc,
10556 ReductionCodeGen &RCG,
10557 unsigned N) {
10558 llvm_unreachable("Not supported in SIMD-only mode");
10559}
10560
10561Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
10562 SourceLocation Loc,
10563 llvm::Value *ReductionsPtr,
10564 LValue SharedLVal) {
10565 llvm_unreachable("Not supported in SIMD-only mode");
10566}
10567
10568void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
10569 SourceLocation Loc) {
10570 llvm_unreachable("Not supported in SIMD-only mode");
10571}
10572
10573void CGOpenMPSIMDRuntime::emitCancellationPointCall(
10574 CodeGenFunction &CGF, SourceLocation Loc,
10575 OpenMPDirectiveKind CancelRegion) {
10576 llvm_unreachable("Not supported in SIMD-only mode");
10577}
10578
10579void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF,
10580 SourceLocation Loc, const Expr *IfCond,
10581 OpenMPDirectiveKind CancelRegion) {
10582 llvm_unreachable("Not supported in SIMD-only mode");
10583}
10584
10585void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction(
10586 const OMPExecutableDirective &D, StringRef ParentName,
10587 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID,
10588 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) {
10589 llvm_unreachable("Not supported in SIMD-only mode");
10590}
10591
10592void CGOpenMPSIMDRuntime::emitTargetCall(CodeGenFunction &CGF,
10593 const OMPExecutableDirective &D,
James Y Knight9871db02019-02-05 16:42:33 +000010594 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010595 llvm::Value *OutlinedFnID,
James Y Knight9871db02019-02-05 16:42:33 +000010596 const Expr *IfCond,
10597 const Expr *Device) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010598 llvm_unreachable("Not supported in SIMD-only mode");
10599}
10600
10601bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) {
10602 llvm_unreachable("Not supported in SIMD-only mode");
10603}
10604
10605bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
10606 llvm_unreachable("Not supported in SIMD-only mode");
10607}
10608
10609bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) {
10610 return false;
10611}
10612
10613llvm::Function *CGOpenMPSIMDRuntime::emitRegistrationFunction() {
10614 return nullptr;
10615}
10616
10617void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF,
10618 const OMPExecutableDirective &D,
10619 SourceLocation Loc,
James Y Knight9871db02019-02-05 16:42:33 +000010620 llvm::Function *OutlinedFn,
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010621 ArrayRef<llvm::Value *> CapturedVars) {
10622 llvm_unreachable("Not supported in SIMD-only mode");
10623}
10624
10625void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF,
10626 const Expr *NumTeams,
10627 const Expr *ThreadLimit,
10628 SourceLocation Loc) {
10629 llvm_unreachable("Not supported in SIMD-only mode");
10630}
10631
10632void CGOpenMPSIMDRuntime::emitTargetDataCalls(
10633 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10634 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) {
10635 llvm_unreachable("Not supported in SIMD-only mode");
10636}
10637
10638void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall(
10639 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond,
10640 const Expr *Device) {
10641 llvm_unreachable("Not supported in SIMD-only mode");
10642}
10643
10644void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF,
Alexey Bataevf138fda2018-08-13 19:04:24 +000010645 const OMPLoopDirective &D,
10646 ArrayRef<Expr *> NumIterations) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +000010647 llvm_unreachable("Not supported in SIMD-only mode");
10648}
10649
10650void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF,
10651 const OMPDependClause *C) {
10652 llvm_unreachable("Not supported in SIMD-only mode");
10653}
10654
10655const VarDecl *
10656CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD,
10657 const VarDecl *NativeParam) const {
10658 llvm_unreachable("Not supported in SIMD-only mode");
10659}
10660
10661Address
10662CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF,
10663 const VarDecl *NativeParam,
10664 const VarDecl *TargetParam) const {
10665 llvm_unreachable("Not supported in SIMD-only mode");
10666}