blob: bef36bf4693b2c9a26da5285fbcc3c2637222c5e [file] [log] [blame]
Alexey Bataev9959db52014-05-06 10:08:46 +00001//===--- CGStmtOpenMP.cpp - Emit LLVM Code from Statements ----------------===//
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 contains code to emit OpenMP nodes as LLVM code.
10//
11//===----------------------------------------------------------------------===//
12
Alexey Bataev3392d762016-02-16 11:18:12 +000013#include "CGCleanup.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000014#include "CGOpenMPRuntime.h"
15#include "CodeGenFunction.h"
16#include "CodeGenModule.h"
Chandler Carruth0d9593d2015-01-14 11:29:14 +000017#include "TargetInfo.h"
Alexey Bataev61205822019-12-04 09:50:21 -050018#include "clang/AST/ASTContext.h"
Reid Kleckner98031782019-12-09 16:11:56 -080019#include "clang/AST/Attr.h"
20#include "clang/AST/DeclOpenMP.h"
Alexey Bataeve6d25832020-01-27 14:10:17 -050021#include "clang/AST/OpenMPClause.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000022#include "clang/AST/Stmt.h"
23#include "clang/AST/StmtOpenMP.h"
Alexey Bataevea9166b2020-02-06 16:30:23 -050024#include "clang/Basic/OpenMPKinds.h"
Alexey Bataev8bbf2e32019-11-04 09:59:11 -050025#include "clang/Basic/PrettyStackTrace.h"
Johannes Doerfert10fedd92019-12-26 11:23:38 -060026#include "llvm/Frontend/OpenMP/OMPIRBuilder.h"
Alexey Bataeve8e05de2020-02-07 12:22:23 -050027#include "llvm/IR/Instructions.h"
Alexey Bataev2d4f80f2020-02-11 15:15:21 -050028#include "llvm/Support/AtomicOrdering.h"
Alexey Bataev9959db52014-05-06 10:08:46 +000029using namespace clang;
30using namespace CodeGen;
Johannes Doerferteb3e81f2019-11-04 22:00:49 -060031using namespace llvm::omp;
Alexey Bataev9959db52014-05-06 10:08:46 +000032
Alexey Bataev3392d762016-02-16 11:18:12 +000033namespace {
34/// Lexical scope for OpenMP executable constructs, that handles correct codegen
35/// for captured expressions.
Arpith Chacko Jacobfe4890a2017-01-18 20:40:48 +000036class OMPLexicalScope : public CodeGenFunction::LexicalScope {
Alexey Bataev3392d762016-02-16 11:18:12 +000037 void emitPreInitStmt(CodeGenFunction &CGF, const OMPExecutableDirective &S) {
38 for (const auto *C : S.clauses()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +000039 if (const auto *CPI = OMPClauseWithPreInit::get(C)) {
40 if (const auto *PreInit =
41 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
Alexey Bataev2bbf7212016-03-03 03:52:24 +000042 for (const auto *I : PreInit->decls()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +000043 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
Alexey Bataev2bbf7212016-03-03 03:52:24 +000044 CGF.EmitVarDecl(cast<VarDecl>(*I));
Alexey Bataevddf3db92018-04-13 17:31:06 +000045 } else {
Alexey Bataev2bbf7212016-03-03 03:52:24 +000046 CodeGenFunction::AutoVarEmission Emission =
47 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
48 CGF.EmitAutoVarCleanups(Emission);
49 }
50 }
Alexey Bataev3392d762016-02-16 11:18:12 +000051 }
52 }
53 }
54 }
Alexey Bataev4ba78a42016-04-27 07:56:03 +000055 CodeGenFunction::OMPPrivateScope InlinedShareds;
56
57 static bool isCapturedVar(CodeGenFunction &CGF, const VarDecl *VD) {
58 return CGF.LambdaCaptureFields.lookup(VD) ||
59 (CGF.CapturedStmtInfo && CGF.CapturedStmtInfo->lookup(VD)) ||
Alexey Bataev172f1462020-03-12 12:52:02 -040060 (CGF.CurCodeDecl && isa<BlockDecl>(CGF.CurCodeDecl) &&
61 cast<BlockDecl>(CGF.CurCodeDecl)->capturesVariable(VD));
Alexey Bataev4ba78a42016-04-27 07:56:03 +000062 }
Alexey Bataev3392d762016-02-16 11:18:12 +000063
Alexey Bataev3392d762016-02-16 11:18:12 +000064public:
Alexey Bataev475a7442018-01-12 19:39:11 +000065 OMPLexicalScope(
66 CodeGenFunction &CGF, const OMPExecutableDirective &S,
67 const llvm::Optional<OpenMPDirectiveKind> CapturedRegion = llvm::None,
68 const bool EmitPreInitStmt = true)
Alexey Bataev4ba78a42016-04-27 07:56:03 +000069 : CodeGenFunction::LexicalScope(CGF, S.getSourceRange()),
70 InlinedShareds(CGF) {
Arpith Chacko Jacobfe4890a2017-01-18 20:40:48 +000071 if (EmitPreInitStmt)
72 emitPreInitStmt(CGF, S);
Alexey Bataev475a7442018-01-12 19:39:11 +000073 if (!CapturedRegion.hasValue())
74 return;
75 assert(S.hasAssociatedStmt() &&
76 "Expected associated statement for inlined directive.");
77 const CapturedStmt *CS = S.getCapturedStmt(*CapturedRegion);
Alexey Bataevddf3db92018-04-13 17:31:06 +000078 for (const auto &C : CS->captures()) {
Alexey Bataev475a7442018-01-12 19:39:11 +000079 if (C.capturesVariable() || C.capturesVariableByCopy()) {
80 auto *VD = C.getCapturedVar();
81 assert(VD == VD->getCanonicalDecl() &&
82 "Canonical decl must be captured.");
83 DeclRefExpr DRE(
Bruno Ricci5fc4db72018-12-21 14:10:18 +000084 CGF.getContext(), const_cast<VarDecl *>(VD),
Alexey Bataev475a7442018-01-12 19:39:11 +000085 isCapturedVar(CGF, VD) || (CGF.CapturedStmtInfo &&
86 InlinedShareds.isGlobalVarCaptured(VD)),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +000087 VD->getType().getNonReferenceType(), VK_LValue, C.getLocation());
Alexey Bataev475a7442018-01-12 19:39:11 +000088 InlinedShareds.addPrivate(VD, [&CGF, &DRE]() -> Address {
Akira Hatanakaf139ae32019-12-03 15:17:01 -080089 return CGF.EmitLValue(&DRE).getAddress(CGF);
Alexey Bataev475a7442018-01-12 19:39:11 +000090 });
Alexey Bataev4ba78a42016-04-27 07:56:03 +000091 }
92 }
Alexey Bataev475a7442018-01-12 19:39:11 +000093 (void)InlinedShareds.Privatize();
Alexey Bataev3392d762016-02-16 11:18:12 +000094 }
95};
Alexey Bataev14fa1c62016-03-29 05:34:15 +000096
Arpith Chacko Jacobfe4890a2017-01-18 20:40:48 +000097/// Lexical scope for OpenMP parallel construct, that handles correct codegen
98/// for captured expressions.
99class OMPParallelScope final : public OMPLexicalScope {
100 bool EmitPreInitStmt(const OMPExecutableDirective &S) {
101 OpenMPDirectiveKind Kind = S.getDirectiveKind();
Carlo Bertollib0ff0a62017-04-25 17:52:12 +0000102 return !(isOpenMPTargetExecutionDirective(Kind) ||
103 isOpenMPLoopBoundSharingDirective(Kind)) &&
Arpith Chacko Jacobfe4890a2017-01-18 20:40:48 +0000104 isOpenMPParallelDirective(Kind);
105 }
106
107public:
108 OMPParallelScope(CodeGenFunction &CGF, const OMPExecutableDirective &S)
Alexey Bataev475a7442018-01-12 19:39:11 +0000109 : OMPLexicalScope(CGF, S, /*CapturedRegion=*/llvm::None,
110 EmitPreInitStmt(S)) {}
Arpith Chacko Jacobfe4890a2017-01-18 20:40:48 +0000111};
112
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +0000113/// Lexical scope for OpenMP teams construct, that handles correct codegen
114/// for captured expressions.
115class OMPTeamsScope final : public OMPLexicalScope {
116 bool EmitPreInitStmt(const OMPExecutableDirective &S) {
117 OpenMPDirectiveKind Kind = S.getDirectiveKind();
118 return !isOpenMPTargetExecutionDirective(Kind) &&
119 isOpenMPTeamsDirective(Kind);
120 }
121
122public:
123 OMPTeamsScope(CodeGenFunction &CGF, const OMPExecutableDirective &S)
Alexey Bataev475a7442018-01-12 19:39:11 +0000124 : OMPLexicalScope(CGF, S, /*CapturedRegion=*/llvm::None,
125 EmitPreInitStmt(S)) {}
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +0000126};
127
Alexey Bataev5a3af132016-03-29 08:58:54 +0000128/// Private scope for OpenMP loop-based directives, that supports capturing
129/// of used expression from loop statement.
130class OMPLoopScope : public CodeGenFunction::RunCleanupsScope {
131 void emitPreInitStmt(CodeGenFunction &CGF, const OMPLoopDirective &S) {
Alexey Bataevab4ea222018-03-07 18:17:06 +0000132 CodeGenFunction::OMPMapVars PreCondVars;
Alexey Bataevf71939c2019-09-18 19:24:07 +0000133 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
Alexey Bataevddf3db92018-04-13 17:31:06 +0000134 for (const auto *E : S.counters()) {
Alexey Bataeve83b3e82017-12-08 20:18:58 +0000135 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataevf71939c2019-09-18 19:24:07 +0000136 EmittedAsPrivate.insert(VD->getCanonicalDecl());
Alexey Bataevab4ea222018-03-07 18:17:06 +0000137 (void)PreCondVars.setVarAddr(
138 CGF, VD, CGF.CreateMemTemp(VD->getType().getNonReferenceType()));
Alexey Bataeve83b3e82017-12-08 20:18:58 +0000139 }
Alexey Bataevf71939c2019-09-18 19:24:07 +0000140 // Mark private vars as undefs.
141 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) {
142 for (const Expr *IRef : C->varlists()) {
143 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(IRef)->getDecl());
144 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
145 (void)PreCondVars.setVarAddr(
146 CGF, OrigVD,
147 Address(llvm::UndefValue::get(
148 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(
149 OrigVD->getType().getNonReferenceType()))),
150 CGF.getContext().getDeclAlign(OrigVD)));
151 }
152 }
153 }
Alexey Bataevab4ea222018-03-07 18:17:06 +0000154 (void)PreCondVars.apply(CGF);
Alexey Bataevbef93a92019-10-07 18:54:57 +0000155 // Emit init, __range and __end variables for C++ range loops.
156 const Stmt *Body =
157 S.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
158 for (unsigned Cnt = 0; Cnt < S.getCollapsedNumber(); ++Cnt) {
Alexey Bataev8bbf2e32019-11-04 09:59:11 -0500159 Body = OMPLoopDirective::tryToFindNextInnerLoop(
160 Body, /*TryImperfectlyNestedLoops=*/true);
Alexey Bataevbef93a92019-10-07 18:54:57 +0000161 if (auto *For = dyn_cast<ForStmt>(Body)) {
162 Body = For->getBody();
163 } else {
164 assert(isa<CXXForRangeStmt>(Body) &&
Alexey Bataevd457f7e2019-10-07 19:57:40 +0000165 "Expected canonical for loop or range-based for loop.");
Alexey Bataevbef93a92019-10-07 18:54:57 +0000166 auto *CXXFor = cast<CXXForRangeStmt>(Body);
167 if (const Stmt *Init = CXXFor->getInit())
168 CGF.EmitStmt(Init);
169 CGF.EmitStmt(CXXFor->getRangeStmt());
170 CGF.EmitStmt(CXXFor->getEndStmt());
171 Body = CXXFor->getBody();
172 }
173 }
Alexey Bataevddf3db92018-04-13 17:31:06 +0000174 if (const auto *PreInits = cast_or_null<DeclStmt>(S.getPreInits())) {
George Burgess IV00f70bd2018-03-01 05:43:23 +0000175 for (const auto *I : PreInits->decls())
176 CGF.EmitVarDecl(cast<VarDecl>(*I));
Alexey Bataev5a3af132016-03-29 08:58:54 +0000177 }
Alexey Bataevab4ea222018-03-07 18:17:06 +0000178 PreCondVars.restore(CGF);
Alexey Bataev5a3af132016-03-29 08:58:54 +0000179 }
180
181public:
182 OMPLoopScope(CodeGenFunction &CGF, const OMPLoopDirective &S)
183 : CodeGenFunction::RunCleanupsScope(CGF) {
184 emitPreInitStmt(CGF, S);
185 }
186};
187
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000188class OMPSimdLexicalScope : public CodeGenFunction::LexicalScope {
189 CodeGenFunction::OMPPrivateScope InlinedShareds;
190
191 static bool isCapturedVar(CodeGenFunction &CGF, const VarDecl *VD) {
192 return CGF.LambdaCaptureFields.lookup(VD) ||
193 (CGF.CapturedStmtInfo && CGF.CapturedStmtInfo->lookup(VD)) ||
194 (CGF.CurCodeDecl && isa<BlockDecl>(CGF.CurCodeDecl) &&
195 cast<BlockDecl>(CGF.CurCodeDecl)->capturesVariable(VD));
196 }
197
198public:
199 OMPSimdLexicalScope(CodeGenFunction &CGF, const OMPExecutableDirective &S)
200 : CodeGenFunction::LexicalScope(CGF, S.getSourceRange()),
201 InlinedShareds(CGF) {
202 for (const auto *C : S.clauses()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000203 if (const auto *CPI = OMPClauseWithPreInit::get(C)) {
204 if (const auto *PreInit =
205 cast_or_null<DeclStmt>(CPI->getPreInitStmt())) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000206 for (const auto *I : PreInit->decls()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000207 if (!I->hasAttr<OMPCaptureNoInitAttr>()) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000208 CGF.EmitVarDecl(cast<VarDecl>(*I));
Alexey Bataevddf3db92018-04-13 17:31:06 +0000209 } else {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000210 CodeGenFunction::AutoVarEmission Emission =
211 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I));
212 CGF.EmitAutoVarCleanups(Emission);
213 }
214 }
215 }
216 } else if (const auto *UDP = dyn_cast<OMPUseDevicePtrClause>(C)) {
217 for (const Expr *E : UDP->varlists()) {
218 const Decl *D = cast<DeclRefExpr>(E)->getDecl();
219 if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(D))
220 CGF.EmitVarDecl(*OED);
221 }
222 }
223 }
224 if (!isOpenMPSimdDirective(S.getDirectiveKind()))
225 CGF.EmitOMPPrivateClause(S, InlinedShareds);
226 if (const auto *TG = dyn_cast<OMPTaskgroupDirective>(&S)) {
227 if (const Expr *E = TG->getReductionRef())
228 CGF.EmitVarDecl(*cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()));
229 }
230 const auto *CS = cast_or_null<CapturedStmt>(S.getAssociatedStmt());
231 while (CS) {
232 for (auto &C : CS->captures()) {
233 if (C.capturesVariable() || C.capturesVariableByCopy()) {
234 auto *VD = C.getCapturedVar();
235 assert(VD == VD->getCanonicalDecl() &&
236 "Canonical decl must be captured.");
Bruno Ricci5fc4db72018-12-21 14:10:18 +0000237 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD),
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000238 isCapturedVar(CGF, VD) ||
239 (CGF.CapturedStmtInfo &&
240 InlinedShareds.isGlobalVarCaptured(VD)),
241 VD->getType().getNonReferenceType(), VK_LValue,
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000242 C.getLocation());
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000243 InlinedShareds.addPrivate(VD, [&CGF, &DRE]() -> Address {
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800244 return CGF.EmitLValue(&DRE).getAddress(CGF);
Alexey Bataeva8a9153a2017-12-29 18:07:07 +0000245 });
246 }
247 }
248 CS = dyn_cast<CapturedStmt>(CS->getCapturedStmt());
249 }
250 (void)InlinedShareds.Privatize();
251 }
252};
253
Alexey Bataev3392d762016-02-16 11:18:12 +0000254} // namespace
255
Alexey Bataevf8365372017-11-17 17:57:25 +0000256static void emitCommonOMPTargetDirective(CodeGenFunction &CGF,
257 const OMPExecutableDirective &S,
258 const RegionCodeGenTy &CodeGen);
259
Alexey Bataevf47c4b42017-09-26 13:47:31 +0000260LValue CodeGenFunction::EmitOMPSharedLValue(const Expr *E) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000261 if (const auto *OrigDRE = dyn_cast<DeclRefExpr>(E)) {
262 if (const auto *OrigVD = dyn_cast<VarDecl>(OrigDRE->getDecl())) {
Alexey Bataevf47c4b42017-09-26 13:47:31 +0000263 OrigVD = OrigVD->getCanonicalDecl();
264 bool IsCaptured =
265 LambdaCaptureFields.lookup(OrigVD) ||
266 (CapturedStmtInfo && CapturedStmtInfo->lookup(OrigVD)) ||
267 (CurCodeDecl && isa<BlockDecl>(CurCodeDecl));
Bruno Ricci5fc4db72018-12-21 14:10:18 +0000268 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD), IsCaptured,
Alexey Bataevf47c4b42017-09-26 13:47:31 +0000269 OrigDRE->getType(), VK_LValue, OrigDRE->getExprLoc());
270 return EmitLValue(&DRE);
271 }
272 }
273 return EmitLValue(E);
274}
275
Alexey Bataev1189bd02016-01-26 12:20:39 +0000276llvm::Value *CodeGenFunction::getTypeSize(QualType Ty) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000277 ASTContext &C = getContext();
Alexey Bataev1189bd02016-01-26 12:20:39 +0000278 llvm::Value *Size = nullptr;
279 auto SizeInChars = C.getTypeSizeInChars(Ty);
280 if (SizeInChars.isZero()) {
281 // getTypeSizeInChars() returns 0 for a VLA.
Alexey Bataevddf3db92018-04-13 17:31:06 +0000282 while (const VariableArrayType *VAT = C.getAsVariableArrayType(Ty)) {
283 VlaSizePair VlaSize = getVLASize(VAT);
Sander de Smalen891af03a2018-02-03 13:55:59 +0000284 Ty = VlaSize.Type;
285 Size = Size ? Builder.CreateNUWMul(Size, VlaSize.NumElts)
286 : VlaSize.NumElts;
Alexey Bataev1189bd02016-01-26 12:20:39 +0000287 }
288 SizeInChars = C.getTypeSizeInChars(Ty);
289 if (SizeInChars.isZero())
290 return llvm::ConstantInt::get(SizeTy, /*V=*/0);
Alexey Bataevddf3db92018-04-13 17:31:06 +0000291 return Builder.CreateNUWMul(Size, CGM.getSize(SizeInChars));
292 }
293 return CGM.getSize(SizeInChars);
Alexey Bataev1189bd02016-01-26 12:20:39 +0000294}
295
Alexey Bataev2377fe92015-09-10 08:12:02 +0000296void CodeGenFunction::GenerateOpenMPCapturedVars(
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000297 const CapturedStmt &S, SmallVectorImpl<llvm::Value *> &CapturedVars) {
Alexey Bataev2377fe92015-09-10 08:12:02 +0000298 const RecordDecl *RD = S.getCapturedRecordDecl();
299 auto CurField = RD->field_begin();
300 auto CurCap = S.captures().begin();
301 for (CapturedStmt::const_capture_init_iterator I = S.capture_init_begin(),
302 E = S.capture_init_end();
303 I != E; ++I, ++CurField, ++CurCap) {
304 if (CurField->hasCapturedVLAType()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000305 const VariableArrayType *VAT = CurField->getCapturedVLAType();
306 llvm::Value *Val = VLASizeMap[VAT->getSizeExpr()];
Samuel Antaobed3c462015-10-02 16:14:20 +0000307 CapturedVars.push_back(Val);
Alexey Bataevddf3db92018-04-13 17:31:06 +0000308 } else if (CurCap->capturesThis()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +0000309 CapturedVars.push_back(CXXThisValue);
Alexey Bataevddf3db92018-04-13 17:31:06 +0000310 } else if (CurCap->capturesVariableByCopy()) {
Alexey Bataev1e491372018-01-23 18:44:14 +0000311 llvm::Value *CV = EmitLoadOfScalar(EmitLValue(*I), CurCap->getLocation());
Samuel Antao6d004262016-06-16 18:39:34 +0000312
313 // If the field is not a pointer, we need to save the actual value
314 // and load it as a void pointer.
315 if (!CurField->getType()->isAnyPointerType()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000316 ASTContext &Ctx = getContext();
317 Address DstAddr = CreateMemTemp(
Samuel Antao6d004262016-06-16 18:39:34 +0000318 Ctx.getUIntPtrType(),
Alexey Bataevddf3db92018-04-13 17:31:06 +0000319 Twine(CurCap->getCapturedVar()->getName(), ".casted"));
Samuel Antao6d004262016-06-16 18:39:34 +0000320 LValue DstLV = MakeAddrLValue(DstAddr, Ctx.getUIntPtrType());
321
Alexey Bataevddf3db92018-04-13 17:31:06 +0000322 llvm::Value *SrcAddrVal = EmitScalarConversion(
Samuel Antao6d004262016-06-16 18:39:34 +0000323 DstAddr.getPointer(), Ctx.getPointerType(Ctx.getUIntPtrType()),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000324 Ctx.getPointerType(CurField->getType()), CurCap->getLocation());
Samuel Antao6d004262016-06-16 18:39:34 +0000325 LValue SrcLV =
326 MakeNaturalAlignAddrLValue(SrcAddrVal, CurField->getType());
327
328 // Store the value using the source type pointer.
329 EmitStoreThroughLValue(RValue::get(CV), SrcLV);
330
331 // Load the value using the destination type pointer.
Alexey Bataev1e491372018-01-23 18:44:14 +0000332 CV = EmitLoadOfScalar(DstLV, CurCap->getLocation());
Samuel Antao6d004262016-06-16 18:39:34 +0000333 }
334 CapturedVars.push_back(CV);
335 } else {
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000336 assert(CurCap->capturesVariable() && "Expected capture by reference.");
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800337 CapturedVars.push_back(EmitLValue(*I).getAddress(*this).getPointer());
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000338 }
Alexey Bataev2377fe92015-09-10 08:12:02 +0000339 }
340}
341
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000342static Address castValueFromUintptr(CodeGenFunction &CGF, SourceLocation Loc,
343 QualType DstType, StringRef Name,
Alexey Bataev06e80f62019-05-23 18:19:54 +0000344 LValue AddrLV) {
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000345 ASTContext &Ctx = CGF.getContext();
346
Alexey Bataevddf3db92018-04-13 17:31:06 +0000347 llvm::Value *CastedPtr = CGF.EmitScalarConversion(
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800348 AddrLV.getAddress(CGF).getPointer(), Ctx.getUIntPtrType(),
Alexey Bataevddf3db92018-04-13 17:31:06 +0000349 Ctx.getPointerType(DstType), Loc);
350 Address TmpAddr =
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000351 CGF.MakeNaturalAlignAddrLValue(CastedPtr, Ctx.getPointerType(DstType))
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800352 .getAddress(CGF);
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000353 return TmpAddr;
354}
355
Alexey Bataevf7ce1662017-04-10 19:16:45 +0000356static QualType getCanonicalParamType(ASTContext &C, QualType T) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000357 if (T->isLValueReferenceType())
Alexey Bataevf7ce1662017-04-10 19:16:45 +0000358 return C.getLValueReferenceType(
359 getCanonicalParamType(C, T.getNonReferenceType()),
360 /*SpelledAsLValue=*/false);
Alexey Bataevf7ce1662017-04-10 19:16:45 +0000361 if (T->isPointerType())
362 return C.getPointerType(getCanonicalParamType(C, T->getPointeeType()));
Alexey Bataevddf3db92018-04-13 17:31:06 +0000363 if (const ArrayType *A = T->getAsArrayTypeUnsafe()) {
364 if (const auto *VLA = dyn_cast<VariableArrayType>(A))
Alexey Bataev1b48c5e2017-10-24 19:52:31 +0000365 return getCanonicalParamType(C, VLA->getElementType());
Alexey Bataevddf3db92018-04-13 17:31:06 +0000366 if (!A->isVariablyModifiedType())
Alexey Bataev1b48c5e2017-10-24 19:52:31 +0000367 return C.getCanonicalType(T);
368 }
Alexey Bataevf7ce1662017-04-10 19:16:45 +0000369 return C.getCanonicalParamType(T);
370}
371
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000372namespace {
Alexey Bataevc33ba8c2020-01-17 14:05:40 -0500373/// Contains required data for proper outlined function codegen.
374struct FunctionOptions {
375 /// Captured statement for which the function is generated.
376 const CapturedStmt *S = nullptr;
377 /// true if cast to/from UIntPtr is required for variables captured by
378 /// value.
379 const bool UIntPtrCastRequired = true;
380 /// true if only casted arguments must be registered as local args or VLA
381 /// sizes.
382 const bool RegisterCastedArgsOnly = false;
383 /// Name of the generated function.
384 const StringRef FunctionName;
385 /// Location of the non-debug version of the outlined function.
386 SourceLocation Loc;
387 explicit FunctionOptions(const CapturedStmt *S, bool UIntPtrCastRequired,
388 bool RegisterCastedArgsOnly, StringRef FunctionName,
389 SourceLocation Loc)
390 : S(S), UIntPtrCastRequired(UIntPtrCastRequired),
391 RegisterCastedArgsOnly(UIntPtrCastRequired && RegisterCastedArgsOnly),
392 FunctionName(FunctionName), Loc(Loc) {}
393};
394} // namespace
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000395
Alexey Bataeve754b182017-08-09 19:38:53 +0000396static llvm::Function *emitOutlinedFunctionPrologue(
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000397 CodeGenFunction &CGF, FunctionArgList &Args,
Alexey Bataev3b8d5582017-08-08 18:04:06 +0000398 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>>
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000399 &LocalAddrs,
400 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>>
401 &VLASizes,
402 llvm::Value *&CXXThisValue, const FunctionOptions &FO) {
403 const CapturedDecl *CD = FO.S->getCapturedDecl();
404 const RecordDecl *RD = FO.S->getCapturedRecordDecl();
Alexey Bataev2377fe92015-09-10 08:12:02 +0000405 assert(CD->hasBody() && "missing CapturedDecl body");
406
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000407 CXXThisValue = nullptr;
Alexey Bataev2377fe92015-09-10 08:12:02 +0000408 // Build the argument list.
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000409 CodeGenModule &CGM = CGF.CGM;
Alexey Bataev2377fe92015-09-10 08:12:02 +0000410 ASTContext &Ctx = CGM.getContext();
Alexey Bataev3b8d5582017-08-08 18:04:06 +0000411 FunctionArgList TargetArgs;
Alexey Bataev2377fe92015-09-10 08:12:02 +0000412 Args.append(CD->param_begin(),
413 std::next(CD->param_begin(), CD->getContextParamPosition()));
Alexey Bataev3b8d5582017-08-08 18:04:06 +0000414 TargetArgs.append(
415 CD->param_begin(),
416 std::next(CD->param_begin(), CD->getContextParamPosition()));
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000417 auto I = FO.S->captures().begin();
Alexey Bataevb45d43c2017-11-22 16:02:03 +0000418 FunctionDecl *DebugFunctionDecl = nullptr;
419 if (!FO.UIntPtrCastRequired) {
420 FunctionProtoType::ExtProtoInfo EPI;
Jonas Devlieghere64a26302018-11-11 00:56:15 +0000421 QualType FunctionTy = Ctx.getFunctionType(Ctx.VoidTy, llvm::None, EPI);
Alexey Bataevb45d43c2017-11-22 16:02:03 +0000422 DebugFunctionDecl = FunctionDecl::Create(
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000423 Ctx, Ctx.getTranslationUnitDecl(), FO.S->getBeginLoc(),
Jonas Devlieghere64a26302018-11-11 00:56:15 +0000424 SourceLocation(), DeclarationName(), FunctionTy,
425 Ctx.getTrivialTypeSourceInfo(FunctionTy), SC_Static,
426 /*isInlineSpecified=*/false, /*hasWrittenPrototype=*/false);
Alexey Bataevb45d43c2017-11-22 16:02:03 +0000427 }
Alexey Bataevddf3db92018-04-13 17:31:06 +0000428 for (const FieldDecl *FD : RD->fields()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +0000429 QualType ArgType = FD->getType();
430 IdentifierInfo *II = nullptr;
431 VarDecl *CapVar = nullptr;
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000432
433 // If this is a capture by copy and the type is not a pointer, the outlined
434 // function argument type should be uintptr and the value properly casted to
435 // uintptr. This is necessary given that the runtime library is only able to
436 // deal with pointers. We can pass in the same way the VLA type sizes to the
437 // outlined function.
Alexey Bataevddf3db92018-04-13 17:31:06 +0000438 if (FO.UIntPtrCastRequired &&
439 ((I->capturesVariableByCopy() && !ArgType->isAnyPointerType()) ||
440 I->capturesVariableArrayType()))
441 ArgType = Ctx.getUIntPtrType();
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000442
443 if (I->capturesVariable() || I->capturesVariableByCopy()) {
Alexey Bataev2377fe92015-09-10 08:12:02 +0000444 CapVar = I->getCapturedVar();
445 II = CapVar->getIdentifier();
Alexey Bataevddf3db92018-04-13 17:31:06 +0000446 } else if (I->capturesThis()) {
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000447 II = &Ctx.Idents.get("this");
Alexey Bataevddf3db92018-04-13 17:31:06 +0000448 } else {
Alexey Bataev2377fe92015-09-10 08:12:02 +0000449 assert(I->capturesVariableArrayType());
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000450 II = &Ctx.Idents.get("vla");
Alexey Bataev2377fe92015-09-10 08:12:02 +0000451 }
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000452 if (ArgType->isVariablyModifiedType())
Alexey Bataev1b48c5e2017-10-24 19:52:31 +0000453 ArgType = getCanonicalParamType(Ctx, ArgType);
Alexey Bataevb45d43c2017-11-22 16:02:03 +0000454 VarDecl *Arg;
455 if (DebugFunctionDecl && (CapVar || I->capturesThis())) {
456 Arg = ParmVarDecl::Create(
457 Ctx, DebugFunctionDecl,
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000458 CapVar ? CapVar->getBeginLoc() : FD->getBeginLoc(),
Alexey Bataevb45d43c2017-11-22 16:02:03 +0000459 CapVar ? CapVar->getLocation() : FD->getLocation(), II, ArgType,
460 /*TInfo=*/nullptr, SC_None, /*DefArg=*/nullptr);
461 } else {
462 Arg = ImplicitParamDecl::Create(Ctx, /*DC=*/nullptr, FD->getLocation(),
463 II, ArgType, ImplicitParamDecl::Other);
464 }
Alexey Bataev3b8d5582017-08-08 18:04:06 +0000465 Args.emplace_back(Arg);
466 // Do not cast arguments if we emit function with non-original types.
467 TargetArgs.emplace_back(
468 FO.UIntPtrCastRequired
469 ? Arg
470 : CGM.getOpenMPRuntime().translateParameter(FD, Arg));
Alexey Bataev2377fe92015-09-10 08:12:02 +0000471 ++I;
472 }
473 Args.append(
474 std::next(CD->param_begin(), CD->getContextParamPosition() + 1),
475 CD->param_end());
Alexey Bataev3b8d5582017-08-08 18:04:06 +0000476 TargetArgs.append(
477 std::next(CD->param_begin(), CD->getContextParamPosition() + 1),
478 CD->param_end());
Alexey Bataev2377fe92015-09-10 08:12:02 +0000479
480 // Create the function declaration.
Alexey Bataev2377fe92015-09-10 08:12:02 +0000481 const CGFunctionInfo &FuncInfo =
Alexey Bataev3b8d5582017-08-08 18:04:06 +0000482 CGM.getTypes().arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, TargetArgs);
Alexey Bataev2377fe92015-09-10 08:12:02 +0000483 llvm::FunctionType *FuncLLVMTy = CGM.getTypes().GetFunctionType(FuncInfo);
484
Alexey Bataevddf3db92018-04-13 17:31:06 +0000485 auto *F =
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000486 llvm::Function::Create(FuncLLVMTy, llvm::GlobalValue::InternalLinkage,
487 FO.FunctionName, &CGM.getModule());
Alexey Bataev2377fe92015-09-10 08:12:02 +0000488 CGM.SetInternalFunctionAttributes(CD, F, FuncInfo);
489 if (CD->isNothrow())
Alexey Bataev2c7eee52017-08-04 19:10:54 +0000490 F->setDoesNotThrow();
Alexey Bataevc0f879b2018-04-10 20:10:53 +0000491 F->setDoesNotRecurse();
Alexey Bataev2377fe92015-09-10 08:12:02 +0000492
493 // Generate the function.
Alexey Bataev6e01dc12017-08-14 16:03:47 +0000494 CGF.StartFunction(CD, Ctx.VoidTy, F, FuncInfo, TargetArgs,
Alexey Bataevc33ba8c2020-01-17 14:05:40 -0500495 FO.UIntPtrCastRequired ? FO.Loc : FO.S->getBeginLoc(),
496 FO.UIntPtrCastRequired ? FO.Loc
497 : CD->getBody()->getBeginLoc());
Alexey Bataev2377fe92015-09-10 08:12:02 +0000498 unsigned Cnt = CD->getContextParamPosition();
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000499 I = FO.S->captures().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +0000500 for (const FieldDecl *FD : RD->fields()) {
Alexey Bataev3b8d5582017-08-08 18:04:06 +0000501 // Do not map arguments if we emit function with non-original types.
502 Address LocalAddr(Address::invalid());
503 if (!FO.UIntPtrCastRequired && Args[Cnt] != TargetArgs[Cnt]) {
504 LocalAddr = CGM.getOpenMPRuntime().getParameterAddress(CGF, Args[Cnt],
505 TargetArgs[Cnt]);
506 } else {
507 LocalAddr = CGF.GetAddrOfLocalVar(Args[Cnt]);
508 }
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000509 // If we are capturing a pointer by copy we don't need to do anything, just
510 // use the value that we get from the arguments.
511 if (I->capturesVariableByCopy() && FD->getType()->isAnyPointerType()) {
Samuel Antao403ffd42016-07-27 22:49:49 +0000512 const VarDecl *CurVD = I->getCapturedVar();
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000513 if (!FO.RegisterCastedArgsOnly)
514 LocalAddrs.insert({Args[Cnt], {CurVD, LocalAddr}});
Richard Trieucc3949d2016-02-18 22:34:54 +0000515 ++Cnt;
516 ++I;
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000517 continue;
518 }
519
Ivan A. Kosarev5f8c0ca2017-10-10 09:39:32 +0000520 LValue ArgLVal = CGF.MakeAddrLValue(LocalAddr, Args[Cnt]->getType(),
521 AlignmentSource::Decl);
Alexey Bataev2377fe92015-09-10 08:12:02 +0000522 if (FD->hasCapturedVLAType()) {
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000523 if (FO.UIntPtrCastRequired) {
Alexey Bataeva9b9cc02018-01-23 18:12:38 +0000524 ArgLVal = CGF.MakeAddrLValue(
525 castValueFromUintptr(CGF, I->getLocation(), FD->getType(),
526 Args[Cnt]->getName(), ArgLVal),
527 FD->getType(), AlignmentSource::Decl);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000528 }
Alexey Bataevddf3db92018-04-13 17:31:06 +0000529 llvm::Value *ExprArg = CGF.EmitLoadOfScalar(ArgLVal, I->getLocation());
530 const VariableArrayType *VAT = FD->getCapturedVLAType();
531 VLASizes.try_emplace(Args[Cnt], VAT->getSizeExpr(), ExprArg);
Alexey Bataev2377fe92015-09-10 08:12:02 +0000532 } else if (I->capturesVariable()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000533 const VarDecl *Var = I->getCapturedVar();
Alexey Bataev2377fe92015-09-10 08:12:02 +0000534 QualType VarTy = Var->getType();
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800535 Address ArgAddr = ArgLVal.getAddress(CGF);
Alexey Bataev06e80f62019-05-23 18:19:54 +0000536 if (ArgLVal.getType()->isLValueReferenceType()) {
537 ArgAddr = CGF.EmitLoadOfReference(ArgLVal);
538 } else if (!VarTy->isVariablyModifiedType() || !VarTy->isPointerType()) {
539 assert(ArgLVal.getType()->isPointerType());
540 ArgAddr = CGF.EmitLoadOfPointer(
541 ArgAddr, ArgLVal.getType()->castAs<PointerType>());
Alexey Bataev2377fe92015-09-10 08:12:02 +0000542 }
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000543 if (!FO.RegisterCastedArgsOnly) {
544 LocalAddrs.insert(
545 {Args[Cnt],
546 {Var, Address(ArgAddr.getPointer(), Ctx.getDeclAlign(Var))}});
547 }
Samuel Antao4af1b7b2015-12-02 17:44:43 +0000548 } else if (I->capturesVariableByCopy()) {
549 assert(!FD->getType()->isAnyPointerType() &&
550 "Not expecting a captured pointer.");
Alexey Bataevddf3db92018-04-13 17:31:06 +0000551 const VarDecl *Var = I->getCapturedVar();
Alexey Bataev06e80f62019-05-23 18:19:54 +0000552 LocalAddrs.insert({Args[Cnt],
553 {Var, FO.UIntPtrCastRequired
554 ? castValueFromUintptr(
555 CGF, I->getLocation(), FD->getType(),
556 Args[Cnt]->getName(), ArgLVal)
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800557 : ArgLVal.getAddress(CGF)}});
Alexey Bataev2377fe92015-09-10 08:12:02 +0000558 } else {
559 // If 'this' is captured, load it into CXXThisValue.
560 assert(I->capturesThis());
Alexey Bataev1e491372018-01-23 18:44:14 +0000561 CXXThisValue = CGF.EmitLoadOfScalar(ArgLVal, I->getLocation());
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800562 LocalAddrs.insert({Args[Cnt], {nullptr, ArgLVal.getAddress(CGF)}});
Alexey Bataev2377fe92015-09-10 08:12:02 +0000563 }
Richard Trieucc3949d2016-02-18 22:34:54 +0000564 ++Cnt;
565 ++I;
Alexey Bataev2377fe92015-09-10 08:12:02 +0000566 }
567
Alexey Bataeve754b182017-08-09 19:38:53 +0000568 return F;
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000569}
570
571llvm::Function *
Alexey Bataevc33ba8c2020-01-17 14:05:40 -0500572CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S,
573 SourceLocation Loc) {
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000574 assert(
575 CapturedStmtInfo &&
576 "CapturedStmtInfo should be set when generating the captured function");
577 const CapturedDecl *CD = S.getCapturedDecl();
578 // Build the argument list.
579 bool NeedWrapperFunction =
Amy Huang53539bb2020-01-13 15:54:54 -0800580 getDebugInfo() && CGM.getCodeGenOpts().hasReducedDebugInfo();
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000581 FunctionArgList Args;
Alexey Bataev3b8d5582017-08-08 18:04:06 +0000582 llvm::MapVector<const Decl *, std::pair<const VarDecl *, Address>> LocalAddrs;
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000583 llvm::DenseMap<const Decl *, std::pair<const Expr *, llvm::Value *>> VLASizes;
Alexey Bataeve754b182017-08-09 19:38:53 +0000584 SmallString<256> Buffer;
585 llvm::raw_svector_ostream Out(Buffer);
586 Out << CapturedStmtInfo->getHelperName();
587 if (NeedWrapperFunction)
588 Out << "_debug__";
Alexey Bataev4aa19052017-08-08 16:45:36 +0000589 FunctionOptions FO(&S, !NeedWrapperFunction, /*RegisterCastedArgsOnly=*/false,
Alexey Bataevc33ba8c2020-01-17 14:05:40 -0500590 Out.str(), Loc);
Alexey Bataeve754b182017-08-09 19:38:53 +0000591 llvm::Function *F = emitOutlinedFunctionPrologue(*this, Args, LocalAddrs,
592 VLASizes, CXXThisValue, FO);
Alexey Bataev06e80f62019-05-23 18:19:54 +0000593 CodeGenFunction::OMPPrivateScope LocalScope(*this);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000594 for (const auto &LocalAddrPair : LocalAddrs) {
595 if (LocalAddrPair.second.first) {
Alexey Bataev06e80f62019-05-23 18:19:54 +0000596 LocalScope.addPrivate(LocalAddrPair.second.first, [&LocalAddrPair]() {
597 return LocalAddrPair.second.second;
598 });
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000599 }
600 }
Alexey Bataev06e80f62019-05-23 18:19:54 +0000601 (void)LocalScope.Privatize();
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000602 for (const auto &VLASizePair : VLASizes)
603 VLASizeMap[VLASizePair.second.first] = VLASizePair.second.second;
Serge Pavlov3a561452015-12-06 14:32:39 +0000604 PGO.assignRegionCounters(GlobalDecl(CD), F);
Alexey Bataev2377fe92015-09-10 08:12:02 +0000605 CapturedStmtInfo->EmitBody(*this, CD->getBody());
Alexey Bataev06e80f62019-05-23 18:19:54 +0000606 (void)LocalScope.ForceCleanup();
Alexey Bataev2377fe92015-09-10 08:12:02 +0000607 FinishFunction(CD->getBodyRBrace());
Alexey Bataeve754b182017-08-09 19:38:53 +0000608 if (!NeedWrapperFunction)
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000609 return F;
Alexey Bataev2377fe92015-09-10 08:12:02 +0000610
Alexey Bataevefd884d2017-08-04 21:26:25 +0000611 FunctionOptions WrapperFO(&S, /*UIntPtrCastRequired=*/true,
Alexey Bataeve754b182017-08-09 19:38:53 +0000612 /*RegisterCastedArgsOnly=*/true,
Alexey Bataevc33ba8c2020-01-17 14:05:40 -0500613 CapturedStmtInfo->getHelperName(), Loc);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000614 CodeGenFunction WrapperCGF(CGM, /*suppressNewContext=*/true);
Gheorghe-Teodor Bercead3dcf2f2018-03-14 14:17:45 +0000615 WrapperCGF.CapturedStmtInfo = CapturedStmtInfo;
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000616 Args.clear();
617 LocalAddrs.clear();
618 VLASizes.clear();
619 llvm::Function *WrapperF =
620 emitOutlinedFunctionPrologue(WrapperCGF, Args, LocalAddrs, VLASizes,
Alexey Bataeve754b182017-08-09 19:38:53 +0000621 WrapperCGF.CXXThisValue, WrapperFO);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000622 llvm::SmallVector<llvm::Value *, 4> CallArgs;
623 for (const auto *Arg : Args) {
624 llvm::Value *CallArg;
625 auto I = LocalAddrs.find(Arg);
626 if (I != LocalAddrs.end()) {
Alexey Bataev7ba57af2017-10-17 16:47:34 +0000627 LValue LV = WrapperCGF.MakeAddrLValue(
628 I->second.second,
629 I->second.first ? I->second.first->getType() : Arg->getType(),
630 AlignmentSource::Decl);
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000631 CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.getBeginLoc());
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000632 } else {
633 auto EI = VLASizes.find(Arg);
Alexey Bataevddf3db92018-04-13 17:31:06 +0000634 if (EI != VLASizes.end()) {
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000635 CallArg = EI->second.second;
Alexey Bataevddf3db92018-04-13 17:31:06 +0000636 } else {
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000637 LValue LV = WrapperCGF.MakeAddrLValue(WrapperCGF.GetAddrOfLocalVar(Arg),
Ivan A. Kosarev5f8c0ca2017-10-10 09:39:32 +0000638 Arg->getType(),
639 AlignmentSource::Decl);
Stephen Kellyf2ceec42018-08-09 21:08:08 +0000640 CallArg = WrapperCGF.EmitLoadOfScalar(LV, S.getBeginLoc());
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000641 }
642 }
Alexey Bataev7ba57af2017-10-17 16:47:34 +0000643 CallArgs.emplace_back(WrapperCGF.EmitFromMemory(CallArg, Arg->getType()));
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000644 }
Alexey Bataevc33ba8c2020-01-17 14:05:40 -0500645 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(WrapperCGF, Loc, F, CallArgs);
Alexey Bataev1fdfdf72017-06-29 16:43:05 +0000646 WrapperCGF.FinishFunction();
647 return WrapperF;
Alexey Bataev2377fe92015-09-10 08:12:02 +0000648}
649
Alexey Bataev9959db52014-05-06 10:08:46 +0000650//===----------------------------------------------------------------------===//
651// OpenMP Directive Emission
652//===----------------------------------------------------------------------===//
Alexey Bataev420d45b2015-04-14 05:11:24 +0000653void CodeGenFunction::EmitOMPAggregateAssign(
John McCall7f416cc2015-09-08 08:05:57 +0000654 Address DestAddr, Address SrcAddr, QualType OriginalType,
Alexey Bataevddf3db92018-04-13 17:31:06 +0000655 const llvm::function_ref<void(Address, Address)> CopyGen) {
Alexey Bataev420d45b2015-04-14 05:11:24 +0000656 // Perform element-by-element initialization.
657 QualType ElementTy;
John McCall7f416cc2015-09-08 08:05:57 +0000658
659 // Drill down to the base element type on both arrays.
Alexey Bataevddf3db92018-04-13 17:31:06 +0000660 const ArrayType *ArrayTy = OriginalType->getAsArrayTypeUnsafe();
661 llvm::Value *NumElements = emitArrayLength(ArrayTy, ElementTy, DestAddr);
John McCall7f416cc2015-09-08 08:05:57 +0000662 SrcAddr = Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType());
663
Alexey Bataevddf3db92018-04-13 17:31:06 +0000664 llvm::Value *SrcBegin = SrcAddr.getPointer();
665 llvm::Value *DestBegin = DestAddr.getPointer();
Alexey Bataev420d45b2015-04-14 05:11:24 +0000666 // Cast from pointer to array type to pointer to single element.
Alexey Bataevddf3db92018-04-13 17:31:06 +0000667 llvm::Value *DestEnd = Builder.CreateGEP(DestBegin, NumElements);
Alexey Bataev420d45b2015-04-14 05:11:24 +0000668 // The basic structure here is a while-do loop.
Alexey Bataevddf3db92018-04-13 17:31:06 +0000669 llvm::BasicBlock *BodyBB = createBasicBlock("omp.arraycpy.body");
670 llvm::BasicBlock *DoneBB = createBasicBlock("omp.arraycpy.done");
671 llvm::Value *IsEmpty =
Alexey Bataev420d45b2015-04-14 05:11:24 +0000672 Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arraycpy.isempty");
673 Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB);
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000674
Alexey Bataev420d45b2015-04-14 05:11:24 +0000675 // Enter the loop body, making that address the current address.
Alexey Bataevddf3db92018-04-13 17:31:06 +0000676 llvm::BasicBlock *EntryBB = Builder.GetInsertBlock();
Alexey Bataev420d45b2015-04-14 05:11:24 +0000677 EmitBlock(BodyBB);
John McCall7f416cc2015-09-08 08:05:57 +0000678
679 CharUnits ElementSize = getContext().getTypeSizeInChars(ElementTy);
680
681 llvm::PHINode *SrcElementPHI =
682 Builder.CreatePHI(SrcBegin->getType(), 2, "omp.arraycpy.srcElementPast");
683 SrcElementPHI->addIncoming(SrcBegin, EntryBB);
684 Address SrcElementCurrent =
685 Address(SrcElementPHI,
686 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize));
687
688 llvm::PHINode *DestElementPHI =
689 Builder.CreatePHI(DestBegin->getType(), 2, "omp.arraycpy.destElementPast");
690 DestElementPHI->addIncoming(DestBegin, EntryBB);
691 Address DestElementCurrent =
692 Address(DestElementPHI,
693 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize));
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000694
Alexey Bataev420d45b2015-04-14 05:11:24 +0000695 // Emit copy.
696 CopyGen(DestElementCurrent, SrcElementCurrent);
697
698 // Shift the address forward by one element.
Alexey Bataevddf3db92018-04-13 17:31:06 +0000699 llvm::Value *DestElementNext = Builder.CreateConstGEP1_32(
John McCall7f416cc2015-09-08 08:05:57 +0000700 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element");
Alexey Bataevddf3db92018-04-13 17:31:06 +0000701 llvm::Value *SrcElementNext = Builder.CreateConstGEP1_32(
John McCall7f416cc2015-09-08 08:05:57 +0000702 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element");
Alexey Bataev420d45b2015-04-14 05:11:24 +0000703 // Check whether we've reached the end.
Alexey Bataevddf3db92018-04-13 17:31:06 +0000704 llvm::Value *Done =
Alexey Bataev420d45b2015-04-14 05:11:24 +0000705 Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done");
706 Builder.CreateCondBr(Done, DoneBB, BodyBB);
John McCall7f416cc2015-09-08 08:05:57 +0000707 DestElementPHI->addIncoming(DestElementNext, Builder.GetInsertBlock());
708 SrcElementPHI->addIncoming(SrcElementNext, Builder.GetInsertBlock());
Alexey Bataev420d45b2015-04-14 05:11:24 +0000709
710 // Done.
711 EmitBlock(DoneBB, /*IsFinished=*/true);
712}
713
John McCall7f416cc2015-09-08 08:05:57 +0000714void CodeGenFunction::EmitOMPCopy(QualType OriginalType, Address DestAddr,
715 Address SrcAddr, const VarDecl *DestVD,
Alexey Bataev420d45b2015-04-14 05:11:24 +0000716 const VarDecl *SrcVD, const Expr *Copy) {
717 if (OriginalType->isArrayType()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000718 const auto *BO = dyn_cast<BinaryOperator>(Copy);
Alexey Bataev420d45b2015-04-14 05:11:24 +0000719 if (BO && BO->getOpcode() == BO_Assign) {
720 // Perform simple memcpy for simple copying.
Ivan A. Kosarev1860b522018-01-25 14:21:55 +0000721 LValue Dest = MakeAddrLValue(DestAddr, OriginalType);
722 LValue Src = MakeAddrLValue(SrcAddr, OriginalType);
723 EmitAggregateAssign(Dest, Src, OriginalType);
Alexey Bataev420d45b2015-04-14 05:11:24 +0000724 } else {
725 // For arrays with complex element types perform element by element
726 // copying.
John McCall7f416cc2015-09-08 08:05:57 +0000727 EmitOMPAggregateAssign(
Alexey Bataev420d45b2015-04-14 05:11:24 +0000728 DestAddr, SrcAddr, OriginalType,
John McCall7f416cc2015-09-08 08:05:57 +0000729 [this, Copy, SrcVD, DestVD](Address DestElement, Address SrcElement) {
Alexey Bataev420d45b2015-04-14 05:11:24 +0000730 // Working with the single array element, so have to remap
731 // destination and source variables to corresponding array
732 // elements.
John McCall7f416cc2015-09-08 08:05:57 +0000733 CodeGenFunction::OMPPrivateScope Remap(*this);
Alexey Bataevddf3db92018-04-13 17:31:06 +0000734 Remap.addPrivate(DestVD, [DestElement]() { return DestElement; });
735 Remap.addPrivate(SrcVD, [SrcElement]() { return SrcElement; });
Alexey Bataev420d45b2015-04-14 05:11:24 +0000736 (void)Remap.Privatize();
John McCall7f416cc2015-09-08 08:05:57 +0000737 EmitIgnoredExpr(Copy);
Alexey Bataev420d45b2015-04-14 05:11:24 +0000738 });
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000739 }
Alexey Bataev420d45b2015-04-14 05:11:24 +0000740 } else {
741 // Remap pseudo source variable to private copy.
John McCall7f416cc2015-09-08 08:05:57 +0000742 CodeGenFunction::OMPPrivateScope Remap(*this);
Alexey Bataevddf3db92018-04-13 17:31:06 +0000743 Remap.addPrivate(SrcVD, [SrcAddr]() { return SrcAddr; });
744 Remap.addPrivate(DestVD, [DestAddr]() { return DestAddr; });
Alexey Bataev420d45b2015-04-14 05:11:24 +0000745 (void)Remap.Privatize();
746 // Emit copying of the whole variable.
John McCall7f416cc2015-09-08 08:05:57 +0000747 EmitIgnoredExpr(Copy);
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000748 }
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000749}
750
Alexey Bataev69c62a92015-04-15 04:52:20 +0000751bool CodeGenFunction::EmitOMPFirstprivateClause(const OMPExecutableDirective &D,
752 OMPPrivateScope &PrivateScope) {
Alexey Bataev8ef31412015-12-18 07:58:25 +0000753 if (!HaveInsertPoint())
754 return false;
Alexey Bataev1af5bd52019-03-05 17:47:18 +0000755 bool DeviceConstTarget =
756 getLangOpts().OpenMPIsDevice &&
757 isOpenMPTargetExecutionDirective(D.getDirectiveKind());
Alexey Bataevcd8b6a22016-02-15 08:07:17 +0000758 bool FirstprivateIsLastprivate = false;
Alexey Bataev46978742020-01-30 10:46:11 -0500759 llvm::DenseMap<const VarDecl *, OpenMPLastprivateModifier> Lastprivates;
Alexey Bataevcd8b6a22016-02-15 08:07:17 +0000760 for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {
761 for (const auto *D : C->varlists())
Alexey Bataev46978742020-01-30 10:46:11 -0500762 Lastprivates.try_emplace(
763 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl())->getCanonicalDecl(),
764 C->getKind());
Alexey Bataevcd8b6a22016-02-15 08:07:17 +0000765 }
Alexey Bataev69c62a92015-04-15 04:52:20 +0000766 llvm::DenseSet<const VarDecl *> EmittedAsFirstprivate;
Alexey Bataev475a7442018-01-12 19:39:11 +0000767 llvm::SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
768 getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind());
769 // Force emission of the firstprivate copy if the directive does not emit
770 // outlined function, like omp for, omp simd, omp distribute etc.
771 bool MustEmitFirstprivateCopy =
772 CaptureRegions.size() == 1 && CaptureRegions.back() == OMPD_unknown;
Benjamin Kramerfc600dc2015-08-30 15:12:28 +0000773 for (const auto *C : D.getClausesOfKind<OMPFirstprivateClause>()) {
Alexey Bataev46978742020-01-30 10:46:11 -0500774 const auto *IRef = C->varlist_begin();
775 const auto *InitsRef = C->inits().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +0000776 for (const Expr *IInit : C->private_copies()) {
777 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
Alexey Bataev7ace49d2016-05-17 08:55:33 +0000778 bool ThisFirstprivateIsLastprivate =
779 Lastprivates.count(OrigVD->getCanonicalDecl()) > 0;
Alexey Bataevddf3db92018-04-13 17:31:06 +0000780 const FieldDecl *FD = CapturedStmtInfo->lookup(OrigVD);
Alexey Bataev9c397812019-04-03 17:57:06 +0000781 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
Alexey Bataev475a7442018-01-12 19:39:11 +0000782 if (!MustEmitFirstprivateCopy && !ThisFirstprivateIsLastprivate && FD &&
Alexey Bataev9c397812019-04-03 17:57:06 +0000783 !FD->getType()->isReferenceType() &&
784 (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())) {
Alexey Bataev7ace49d2016-05-17 08:55:33 +0000785 EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl());
786 ++IRef;
787 ++InitsRef;
788 continue;
789 }
Alexey Bataev1af5bd52019-03-05 17:47:18 +0000790 // Do not emit copy for firstprivate constant variables in target regions,
791 // captured by reference.
792 if (DeviceConstTarget && OrigVD->getType().isConstant(getContext()) &&
Alexey Bataev9c397812019-04-03 17:57:06 +0000793 FD && FD->getType()->isReferenceType() &&
794 (!VD || !VD->hasAttr<OMPAllocateDeclAttr>())) {
Alexey Bataev1af5bd52019-03-05 17:47:18 +0000795 (void)CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(*this,
796 OrigVD);
797 ++IRef;
798 ++InitsRef;
799 continue;
800 }
Alexey Bataevcd8b6a22016-02-15 08:07:17 +0000801 FirstprivateIsLastprivate =
Alexey Bataev7ace49d2016-05-17 08:55:33 +0000802 FirstprivateIsLastprivate || ThisFirstprivateIsLastprivate;
Alexey Bataevcd8b6a22016-02-15 08:07:17 +0000803 if (EmittedAsFirstprivate.insert(OrigVD->getCanonicalDecl()).second) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000804 const auto *VDInit =
805 cast<VarDecl>(cast<DeclRefExpr>(*InitsRef)->getDecl());
Alexey Bataev69c62a92015-04-15 04:52:20 +0000806 bool IsRegistered;
Bruno Ricci5fc4db72018-12-21 14:10:18 +0000807 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
Alexey Bataev7ace49d2016-05-17 08:55:33 +0000808 /*RefersToEnclosingVariableOrCapture=*/FD != nullptr,
809 (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
Alexey Bataeve0ef04f2019-05-23 22:30:43 +0000810 LValue OriginalLVal;
811 if (!FD) {
812 // Check if the firstprivate variable is just a constant value.
813 ConstantEmission CE = tryEmitAsConstant(&DRE);
814 if (CE && !CE.isReference()) {
815 // Constant value, no need to create a copy.
816 ++IRef;
817 ++InitsRef;
818 continue;
819 }
820 if (CE && CE.isReference()) {
821 OriginalLVal = CE.getReferenceLValue(*this, &DRE);
822 } else {
823 assert(!CE && "Expected non-constant firstprivate.");
824 OriginalLVal = EmitLValue(&DRE);
825 }
826 } else {
827 OriginalLVal = EmitLValue(&DRE);
828 }
Alexey Bataevfeddd642016-04-22 09:05:03 +0000829 QualType Type = VD->getType();
Alexey Bataev1d9c15c2015-05-19 12:31:28 +0000830 if (Type->isArrayType()) {
Alexey Bataev69c62a92015-04-15 04:52:20 +0000831 // Emit VarDecl with copy init for arrays.
832 // Get the address of the original variable captured in current
833 // captured region.
Alexey Bataevddf3db92018-04-13 17:31:06 +0000834 IsRegistered = PrivateScope.addPrivate(
835 OrigVD, [this, VD, Type, OriginalLVal, VDInit]() {
836 AutoVarEmission Emission = EmitAutoVarAlloca(*VD);
837 const Expr *Init = VD->getInit();
838 if (!isa<CXXConstructExpr>(Init) ||
839 isTrivialInitializer(Init)) {
840 // Perform simple memcpy.
841 LValue Dest =
842 MakeAddrLValue(Emission.getAllocatedAddress(), Type);
843 EmitAggregateAssign(Dest, OriginalLVal, Type);
844 } else {
845 EmitOMPAggregateAssign(
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800846 Emission.getAllocatedAddress(),
847 OriginalLVal.getAddress(*this), Type,
Alexey Bataevddf3db92018-04-13 17:31:06 +0000848 [this, VDInit, Init](Address DestElement,
849 Address SrcElement) {
850 // Clean up any temporaries needed by the
851 // initialization.
852 RunCleanupsScope InitScope(*this);
853 // Emit initialization for single element.
854 setAddrOfLocalVar(VDInit, SrcElement);
855 EmitAnyExprToMem(Init, DestElement,
856 Init->getType().getQualifiers(),
857 /*IsInitializer*/ false);
858 LocalDeclMap.erase(VDInit);
859 });
860 }
861 EmitAutoVarCleanups(Emission);
862 return Emission.getAllocatedAddress();
863 });
Alexey Bataev69c62a92015-04-15 04:52:20 +0000864 } else {
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800865 Address OriginalAddr = OriginalLVal.getAddress(*this);
Alexey Bataev46978742020-01-30 10:46:11 -0500866 IsRegistered =
867 PrivateScope.addPrivate(OrigVD, [this, VDInit, OriginalAddr, VD,
868 ThisFirstprivateIsLastprivate,
869 OrigVD, &Lastprivates, IRef]() {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000870 // Emit private VarDecl with copy init.
871 // Remap temp VDInit variable to the address of the original
872 // variable (for proper handling of captured global variables).
873 setAddrOfLocalVar(VDInit, OriginalAddr);
874 EmitDecl(*VD);
875 LocalDeclMap.erase(VDInit);
Alexey Bataev46978742020-01-30 10:46:11 -0500876 if (ThisFirstprivateIsLastprivate &&
877 Lastprivates[OrigVD->getCanonicalDecl()] ==
878 OMPC_LASTPRIVATE_conditional) {
879 // Create/init special variable for lastprivate conditionals.
880 Address VDAddr =
881 CGM.getOpenMPRuntime().emitLastprivateConditionalInit(
882 *this, OrigVD);
883 llvm::Value *V = EmitLoadOfScalar(
884 MakeAddrLValue(GetAddrOfLocalVar(VD), (*IRef)->getType(),
885 AlignmentSource::Decl),
886 (*IRef)->getExprLoc());
887 EmitStoreOfScalar(V,
888 MakeAddrLValue(VDAddr, (*IRef)->getType(),
889 AlignmentSource::Decl));
890 LocalDeclMap.erase(VD);
891 setAddrOfLocalVar(VD, VDAddr);
892 return VDAddr;
893 }
Alexey Bataevddf3db92018-04-13 17:31:06 +0000894 return GetAddrOfLocalVar(VD);
895 });
Alexey Bataev69c62a92015-04-15 04:52:20 +0000896 }
897 assert(IsRegistered &&
898 "firstprivate var already registered as private");
899 // Silence the warning about unused variable.
900 (void)IsRegistered;
901 }
Richard Trieucc3949d2016-02-18 22:34:54 +0000902 ++IRef;
903 ++InitsRef;
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000904 }
905 }
Alexey Bataevcd8b6a22016-02-15 08:07:17 +0000906 return FirstprivateIsLastprivate && !EmittedAsFirstprivate.empty();
Alexey Bataev4a5bb772014-10-08 14:01:46 +0000907}
908
Alexey Bataev03b340a2014-10-21 03:16:40 +0000909void CodeGenFunction::EmitOMPPrivateClause(
910 const OMPExecutableDirective &D,
911 CodeGenFunction::OMPPrivateScope &PrivateScope) {
Alexey Bataev8ef31412015-12-18 07:58:25 +0000912 if (!HaveInsertPoint())
913 return;
Alexey Bataev50a64582015-04-22 12:24:45 +0000914 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
Benjamin Kramerfc600dc2015-08-30 15:12:28 +0000915 for (const auto *C : D.getClausesOfKind<OMPPrivateClause>()) {
Alexey Bataev03b340a2014-10-21 03:16:40 +0000916 auto IRef = C->varlist_begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +0000917 for (const Expr *IInit : C->private_copies()) {
918 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
Alexey Bataev50a64582015-04-22 12:24:45 +0000919 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
Alexey Bataevddf3db92018-04-13 17:31:06 +0000920 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
921 bool IsRegistered = PrivateScope.addPrivate(OrigVD, [this, VD]() {
922 // Emit private VarDecl with copy init.
923 EmitDecl(*VD);
924 return GetAddrOfLocalVar(VD);
925 });
Alexey Bataev50a64582015-04-22 12:24:45 +0000926 assert(IsRegistered && "private var already registered as private");
927 // Silence the warning about unused variable.
928 (void)IsRegistered;
929 }
Alexey Bataev03b340a2014-10-21 03:16:40 +0000930 ++IRef;
931 }
932 }
933}
934
Alexey Bataevf56f98c2015-04-16 05:39:01 +0000935bool CodeGenFunction::EmitOMPCopyinClause(const OMPExecutableDirective &D) {
Alexey Bataev8ef31412015-12-18 07:58:25 +0000936 if (!HaveInsertPoint())
937 return false;
Alexey Bataevf56f98c2015-04-16 05:39:01 +0000938 // threadprivate_var1 = master_threadprivate_var1;
939 // operator=(threadprivate_var2, master_threadprivate_var2);
940 // ...
941 // __kmpc_barrier(&loc, global_tid);
Alexey Bataevf56f98c2015-04-16 05:39:01 +0000942 llvm::DenseSet<const VarDecl *> CopiedVars;
943 llvm::BasicBlock *CopyBegin = nullptr, *CopyEnd = nullptr;
Benjamin Kramerfc600dc2015-08-30 15:12:28 +0000944 for (const auto *C : D.getClausesOfKind<OMPCopyinClause>()) {
Alexey Bataevf56f98c2015-04-16 05:39:01 +0000945 auto IRef = C->varlist_begin();
946 auto ISrcRef = C->source_exprs().begin();
947 auto IDestRef = C->destination_exprs().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +0000948 for (const Expr *AssignOp : C->assignment_ops()) {
949 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
Alexey Bataev1d9c15c2015-05-19 12:31:28 +0000950 QualType Type = VD->getType();
Alexey Bataevf56f98c2015-04-16 05:39:01 +0000951 if (CopiedVars.insert(VD->getCanonicalDecl()).second) {
Samuel Antao9c75cfe2015-07-27 16:38:06 +0000952 // Get the address of the master variable. If we are emitting code with
953 // TLS support, the address is passed from the master as field in the
954 // captured declaration.
John McCall7f416cc2015-09-08 08:05:57 +0000955 Address MasterAddr = Address::invalid();
Samuel Antao9c75cfe2015-07-27 16:38:06 +0000956 if (getLangOpts().OpenMPUseTLS &&
957 getContext().getTargetInfo().isTLSSupported()) {
958 assert(CapturedStmtInfo->lookup(VD) &&
959 "Copyin threadprivates should have been captured!");
Bruno Ricci5fc4db72018-12-21 14:10:18 +0000960 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(VD), true,
961 (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800962 MasterAddr = EmitLValue(&DRE).getAddress(*this);
Alexey Bataev2377fe92015-09-10 08:12:02 +0000963 LocalDeclMap.erase(VD);
Samuel Antao9c75cfe2015-07-27 16:38:06 +0000964 } else {
John McCall7f416cc2015-09-08 08:05:57 +0000965 MasterAddr =
966 Address(VD->isStaticLocal() ? CGM.getStaticLocalDeclAddress(VD)
967 : CGM.GetAddrOfGlobal(VD),
968 getContext().getDeclAlign(VD));
Samuel Antao9c75cfe2015-07-27 16:38:06 +0000969 }
Alexey Bataevf56f98c2015-04-16 05:39:01 +0000970 // Get the address of the threadprivate variable.
Akira Hatanakaf139ae32019-12-03 15:17:01 -0800971 Address PrivateAddr = EmitLValue(*IRef).getAddress(*this);
Alexey Bataevf56f98c2015-04-16 05:39:01 +0000972 if (CopiedVars.size() == 1) {
973 // At first check if current thread is a master thread. If it is, no
974 // need to copy data.
975 CopyBegin = createBasicBlock("copyin.not.master");
976 CopyEnd = createBasicBlock("copyin.not.master.end");
977 Builder.CreateCondBr(
978 Builder.CreateICmpNE(
John McCall7f416cc2015-09-08 08:05:57 +0000979 Builder.CreatePtrToInt(MasterAddr.getPointer(), CGM.IntPtrTy),
Alexey Bataevddf3db92018-04-13 17:31:06 +0000980 Builder.CreatePtrToInt(PrivateAddr.getPointer(),
981 CGM.IntPtrTy)),
Alexey Bataevf56f98c2015-04-16 05:39:01 +0000982 CopyBegin, CopyEnd);
983 EmitBlock(CopyBegin);
984 }
Alexey Bataevddf3db92018-04-13 17:31:06 +0000985 const auto *SrcVD =
986 cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
987 const auto *DestVD =
988 cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
John McCall7f416cc2015-09-08 08:05:57 +0000989 EmitOMPCopy(Type, PrivateAddr, MasterAddr, DestVD, SrcVD, AssignOp);
Alexey Bataevf56f98c2015-04-16 05:39:01 +0000990 }
991 ++IRef;
992 ++ISrcRef;
993 ++IDestRef;
994 }
995 }
996 if (CopyEnd) {
997 // Exit out of copying procedure for non-master thread.
998 EmitBlock(CopyEnd, /*IsFinished=*/true);
999 return true;
1000 }
1001 return false;
1002}
1003
Alexey Bataev38e89532015-04-16 04:54:05 +00001004bool CodeGenFunction::EmitOMPLastprivateClauseInit(
1005 const OMPExecutableDirective &D, OMPPrivateScope &PrivateScope) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001006 if (!HaveInsertPoint())
1007 return false;
Alexey Bataev38e89532015-04-16 04:54:05 +00001008 bool HasAtLeastOneLastprivate = false;
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001009 llvm::DenseSet<const VarDecl *> SIMDLCVs;
1010 if (isOpenMPSimdDirective(D.getDirectiveKind())) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001011 const auto *LoopDirective = cast<OMPLoopDirective>(&D);
1012 for (const Expr *C : LoopDirective->counters()) {
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001013 SIMDLCVs.insert(
1014 cast<VarDecl>(cast<DeclRefExpr>(C)->getDecl())->getCanonicalDecl());
1015 }
1016 }
Alexey Bataev38e89532015-04-16 04:54:05 +00001017 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001018 for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {
Alexey Bataevd130fd12015-05-13 10:23:02 +00001019 HasAtLeastOneLastprivate = true;
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00001020 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) &&
1021 !getLangOpts().OpenMPSimd)
Alexey Bataevf93095a2016-05-05 08:46:22 +00001022 break;
Alexey Bataev46978742020-01-30 10:46:11 -05001023 const auto *IRef = C->varlist_begin();
1024 const auto *IDestRef = C->destination_exprs().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001025 for (const Expr *IInit : C->private_copies()) {
Alexey Bataev38e89532015-04-16 04:54:05 +00001026 // Keep the address of the original variable for future update at the end
1027 // of the loop.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001028 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
Alexey Bataevf93095a2016-05-05 08:46:22 +00001029 // Taskloops do not require additional initialization, it is done in
1030 // runtime support library.
Alexey Bataev38e89532015-04-16 04:54:05 +00001031 if (AlreadyEmittedVars.insert(OrigVD->getCanonicalDecl()).second) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001032 const auto *DestVD =
1033 cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
1034 PrivateScope.addPrivate(DestVD, [this, OrigVD, IRef]() {
Bruno Ricci5fc4db72018-12-21 14:10:18 +00001035 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
1036 /*RefersToEnclosingVariableOrCapture=*/
1037 CapturedStmtInfo->lookup(OrigVD) != nullptr,
1038 (*IRef)->getType(), VK_LValue, (*IRef)->getExprLoc());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001039 return EmitLValue(&DRE).getAddress(*this);
Alexey Bataev38e89532015-04-16 04:54:05 +00001040 });
1041 // Check if the variable is also a firstprivate: in this case IInit is
1042 // not generated. Initialization of this variable will happen in codegen
1043 // for 'firstprivate' clause.
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001044 if (IInit && !SIMDLCVs.count(OrigVD->getCanonicalDecl())) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001045 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(IInit)->getDecl());
Alexey Bataev46978742020-01-30 10:46:11 -05001046 bool IsRegistered = PrivateScope.addPrivate(OrigVD, [this, VD, C,
1047 OrigVD]() {
1048 if (C->getKind() == OMPC_LASTPRIVATE_conditional) {
1049 Address VDAddr =
1050 CGM.getOpenMPRuntime().emitLastprivateConditionalInit(*this,
1051 OrigVD);
1052 setAddrOfLocalVar(VD, VDAddr);
1053 return VDAddr;
1054 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00001055 // Emit private VarDecl with copy init.
1056 EmitDecl(*VD);
1057 return GetAddrOfLocalVar(VD);
1058 });
Alexey Bataevd130fd12015-05-13 10:23:02 +00001059 assert(IsRegistered &&
1060 "lastprivate var already registered as private");
1061 (void)IsRegistered;
1062 }
Alexey Bataev38e89532015-04-16 04:54:05 +00001063 }
Richard Trieucc3949d2016-02-18 22:34:54 +00001064 ++IRef;
1065 ++IDestRef;
Alexey Bataev38e89532015-04-16 04:54:05 +00001066 }
1067 }
1068 return HasAtLeastOneLastprivate;
1069}
1070
1071void CodeGenFunction::EmitOMPLastprivateClauseFinal(
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001072 const OMPExecutableDirective &D, bool NoFinals,
1073 llvm::Value *IsLastIterCond) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001074 if (!HaveInsertPoint())
1075 return;
Alexey Bataev38e89532015-04-16 04:54:05 +00001076 // Emit following code:
1077 // if (<IsLastIterCond>) {
1078 // orig_var1 = private_orig_var1;
1079 // ...
1080 // orig_varn = private_orig_varn;
1081 // }
Alexey Bataevfc087ec2015-06-16 13:14:42 +00001082 llvm::BasicBlock *ThenBB = nullptr;
1083 llvm::BasicBlock *DoneBB = nullptr;
1084 if (IsLastIterCond) {
Alexey Bataeva58da1a2019-12-27 09:44:43 -05001085 // Emit implicit barrier if at least one lastprivate conditional is found
1086 // and this is not a simd mode.
1087 if (!getLangOpts().OpenMPSimd &&
1088 llvm::any_of(D.getClausesOfKind<OMPLastprivateClause>(),
1089 [](const OMPLastprivateClause *C) {
1090 return C->getKind() == OMPC_LASTPRIVATE_conditional;
1091 })) {
1092 CGM.getOpenMPRuntime().emitBarrierCall(*this, D.getBeginLoc(),
1093 OMPD_unknown,
1094 /*EmitChecks=*/false,
1095 /*ForceSimpleCall=*/true);
1096 }
Alexey Bataevfc087ec2015-06-16 13:14:42 +00001097 ThenBB = createBasicBlock(".omp.lastprivate.then");
1098 DoneBB = createBasicBlock(".omp.lastprivate.done");
1099 Builder.CreateCondBr(IsLastIterCond, ThenBB, DoneBB);
1100 EmitBlock(ThenBB);
1101 }
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001102 llvm::DenseSet<const VarDecl *> AlreadyEmittedVars;
1103 llvm::DenseMap<const VarDecl *, const Expr *> LoopCountersAndUpdates;
Alexey Bataevddf3db92018-04-13 17:31:06 +00001104 if (const auto *LoopDirective = dyn_cast<OMPLoopDirective>(&D)) {
Alexey Bataev8ffcc942016-02-18 13:48:15 +00001105 auto IC = LoopDirective->counters().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001106 for (const Expr *F : LoopDirective->finals()) {
1107 const auto *D =
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001108 cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl())->getCanonicalDecl();
1109 if (NoFinals)
1110 AlreadyEmittedVars.insert(D);
1111 else
1112 LoopCountersAndUpdates[D] = F;
Alexey Bataev8ffcc942016-02-18 13:48:15 +00001113 ++IC;
Alexey Bataev7a228ff2015-05-21 07:59:51 +00001114 }
1115 }
Alexey Bataev8ffcc942016-02-18 13:48:15 +00001116 for (const auto *C : D.getClausesOfKind<OMPLastprivateClause>()) {
1117 auto IRef = C->varlist_begin();
1118 auto ISrcRef = C->source_exprs().begin();
1119 auto IDestRef = C->destination_exprs().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001120 for (const Expr *AssignOp : C->assignment_ops()) {
1121 const auto *PrivateVD =
1122 cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
Alexey Bataev8ffcc942016-02-18 13:48:15 +00001123 QualType Type = PrivateVD->getType();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001124 const auto *CanonicalVD = PrivateVD->getCanonicalDecl();
Alexey Bataev8ffcc942016-02-18 13:48:15 +00001125 if (AlreadyEmittedVars.insert(CanonicalVD).second) {
1126 // If lastprivate variable is a loop control variable for loop-based
1127 // directive, update its value before copyin back to original
1128 // variable.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001129 if (const Expr *FinalExpr = LoopCountersAndUpdates.lookup(CanonicalVD))
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001130 EmitIgnoredExpr(FinalExpr);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001131 const auto *SrcVD =
1132 cast<VarDecl>(cast<DeclRefExpr>(*ISrcRef)->getDecl());
1133 const auto *DestVD =
1134 cast<VarDecl>(cast<DeclRefExpr>(*IDestRef)->getDecl());
Alexey Bataev8ffcc942016-02-18 13:48:15 +00001135 // Get the address of the private variable.
1136 Address PrivateAddr = GetAddrOfLocalVar(PrivateVD);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001137 if (const auto *RefTy = PrivateVD->getType()->getAs<ReferenceType>())
Alexey Bataev8ffcc942016-02-18 13:48:15 +00001138 PrivateAddr =
John McCall7f416cc2015-09-08 08:05:57 +00001139 Address(Builder.CreateLoad(PrivateAddr),
1140 getNaturalTypeAlignment(RefTy->getPointeeType()));
Alexey Bataeva58da1a2019-12-27 09:44:43 -05001141 // Store the last value to the private copy in the last iteration.
1142 if (C->getKind() == OMPC_LASTPRIVATE_conditional)
1143 CGM.getOpenMPRuntime().emitLastprivateConditionalFinalUpdate(
1144 *this, MakeAddrLValue(PrivateAddr, (*IRef)->getType()), PrivateVD,
1145 (*IRef)->getExprLoc());
1146 // Get the address of the original variable.
1147 Address OriginalAddr = GetAddrOfLocalVar(DestVD);
Alexey Bataev8ffcc942016-02-18 13:48:15 +00001148 EmitOMPCopy(Type, OriginalAddr, PrivateAddr, DestVD, SrcVD, AssignOp);
Alexey Bataev38e89532015-04-16 04:54:05 +00001149 }
Alexey Bataev8ffcc942016-02-18 13:48:15 +00001150 ++IRef;
1151 ++ISrcRef;
1152 ++IDestRef;
Alexey Bataev38e89532015-04-16 04:54:05 +00001153 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00001154 if (const Expr *PostUpdate = C->getPostUpdateExpr())
Alexey Bataev005248a2016-02-25 05:25:57 +00001155 EmitIgnoredExpr(PostUpdate);
Alexey Bataev38e89532015-04-16 04:54:05 +00001156 }
Alexey Bataev8ffcc942016-02-18 13:48:15 +00001157 if (IsLastIterCond)
Alexey Bataevfc087ec2015-06-16 13:14:42 +00001158 EmitBlock(DoneBB, /*IsFinished=*/true);
Alexey Bataev38e89532015-04-16 04:54:05 +00001159}
1160
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001161void CodeGenFunction::EmitOMPReductionClauseInit(
1162 const OMPExecutableDirective &D,
1163 CodeGenFunction::OMPPrivateScope &PrivateScope) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001164 if (!HaveInsertPoint())
1165 return;
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001166 SmallVector<const Expr *, 4> Shareds;
1167 SmallVector<const Expr *, 4> Privates;
1168 SmallVector<const Expr *, 4> ReductionOps;
1169 SmallVector<const Expr *, 4> LHSs;
1170 SmallVector<const Expr *, 4> RHSs;
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001171 for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) {
Alexey Bataevf24e7b12015-10-08 09:10:53 +00001172 auto IPriv = C->privates().begin();
Alexey Bataeva839ddd2016-03-17 10:19:46 +00001173 auto IRed = C->reduction_ops().begin();
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001174 auto ILHS = C->lhs_exprs().begin();
1175 auto IRHS = C->rhs_exprs().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001176 for (const Expr *Ref : C->varlists()) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001177 Shareds.emplace_back(Ref);
1178 Privates.emplace_back(*IPriv);
1179 ReductionOps.emplace_back(*IRed);
1180 LHSs.emplace_back(*ILHS);
1181 RHSs.emplace_back(*IRHS);
1182 std::advance(IPriv, 1);
1183 std::advance(IRed, 1);
1184 std::advance(ILHS, 1);
1185 std::advance(IRHS, 1);
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001186 }
1187 }
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001188 ReductionCodeGen RedCG(Shareds, Privates, ReductionOps);
1189 unsigned Count = 0;
1190 auto ILHS = LHSs.begin();
1191 auto IRHS = RHSs.begin();
1192 auto IPriv = Privates.begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001193 for (const Expr *IRef : Shareds) {
1194 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*IPriv)->getDecl());
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001195 // Emit private VarDecl with reduction init.
1196 RedCG.emitSharedLValue(*this, Count);
1197 RedCG.emitAggregateType(*this, Count);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001198 AutoVarEmission Emission = EmitAutoVarAlloca(*PrivateVD);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001199 RedCG.emitInitialization(*this, Count, Emission.getAllocatedAddress(),
1200 RedCG.getSharedLValue(Count),
1201 [&Emission](CodeGenFunction &CGF) {
1202 CGF.EmitAutoVarInit(Emission);
1203 return true;
1204 });
1205 EmitAutoVarCleanups(Emission);
1206 Address BaseAddr = RedCG.adjustPrivateAddress(
1207 *this, Count, Emission.getAllocatedAddress());
1208 bool IsRegistered = PrivateScope.addPrivate(
Alexey Bataevddf3db92018-04-13 17:31:06 +00001209 RedCG.getBaseDecl(Count), [BaseAddr]() { return BaseAddr; });
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001210 assert(IsRegistered && "private var already registered as private");
1211 // Silence the warning about unused variable.
1212 (void)IsRegistered;
1213
Alexey Bataevddf3db92018-04-13 17:31:06 +00001214 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl());
1215 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl());
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001216 QualType Type = PrivateVD->getType();
1217 bool isaOMPArraySectionExpr = isa<OMPArraySectionExpr>(IRef);
1218 if (isaOMPArraySectionExpr && Type->isVariablyModifiedType()) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001219 // Store the address of the original variable associated with the LHS
1220 // implicit variable.
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001221 PrivateScope.addPrivate(LHSVD, [&RedCG, Count, this]() {
1222 return RedCG.getSharedLValue(Count).getAddress(*this);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001223 });
Alexey Bataevddf3db92018-04-13 17:31:06 +00001224 PrivateScope.addPrivate(
1225 RHSVD, [this, PrivateVD]() { return GetAddrOfLocalVar(PrivateVD); });
Jonas Hahnfeld4525c822017-10-23 19:01:35 +00001226 } else if ((isaOMPArraySectionExpr && Type->isScalarType()) ||
1227 isa<ArraySubscriptExpr>(IRef)) {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001228 // Store the address of the original variable associated with the LHS
1229 // implicit variable.
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001230 PrivateScope.addPrivate(LHSVD, [&RedCG, Count, this]() {
1231 return RedCG.getSharedLValue(Count).getAddress(*this);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001232 });
Alexey Bataevddf3db92018-04-13 17:31:06 +00001233 PrivateScope.addPrivate(RHSVD, [this, PrivateVD, RHSVD]() {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001234 return Builder.CreateElementBitCast(GetAddrOfLocalVar(PrivateVD),
1235 ConvertTypeForMem(RHSVD->getType()),
1236 "rhs.begin");
1237 });
1238 } else {
1239 QualType Type = PrivateVD->getType();
1240 bool IsArray = getContext().getAsArrayType(Type) != nullptr;
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001241 Address OriginalAddr = RedCG.getSharedLValue(Count).getAddress(*this);
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001242 // Store the address of the original variable associated with the LHS
1243 // implicit variable.
1244 if (IsArray) {
1245 OriginalAddr = Builder.CreateElementBitCast(
1246 OriginalAddr, ConvertTypeForMem(LHSVD->getType()), "lhs.begin");
1247 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00001248 PrivateScope.addPrivate(LHSVD, [OriginalAddr]() { return OriginalAddr; });
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001249 PrivateScope.addPrivate(
Alexey Bataevddf3db92018-04-13 17:31:06 +00001250 RHSVD, [this, PrivateVD, RHSVD, IsArray]() {
Alexey Bataev5c40bec2017-07-13 13:36:14 +00001251 return IsArray
1252 ? Builder.CreateElementBitCast(
1253 GetAddrOfLocalVar(PrivateVD),
1254 ConvertTypeForMem(RHSVD->getType()), "rhs.begin")
1255 : GetAddrOfLocalVar(PrivateVD);
1256 });
1257 }
1258 ++ILHS;
1259 ++IRHS;
1260 ++IPriv;
1261 ++Count;
1262 }
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001263}
1264
1265void CodeGenFunction::EmitOMPReductionClauseFinal(
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00001266 const OMPExecutableDirective &D, const OpenMPDirectiveKind ReductionKind) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001267 if (!HaveInsertPoint())
1268 return;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00001269 llvm::SmallVector<const Expr *, 8> Privates;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001270 llvm::SmallVector<const Expr *, 8> LHSExprs;
1271 llvm::SmallVector<const Expr *, 8> RHSExprs;
1272 llvm::SmallVector<const Expr *, 8> ReductionOps;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001273 bool HasAtLeastOneReduction = false;
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001274 for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) {
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001275 HasAtLeastOneReduction = true;
Alexey Bataevf24e7b12015-10-08 09:10:53 +00001276 Privates.append(C->privates().begin(), C->privates().end());
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001277 LHSExprs.append(C->lhs_exprs().begin(), C->lhs_exprs().end());
1278 RHSExprs.append(C->rhs_exprs().begin(), C->rhs_exprs().end());
1279 ReductionOps.append(C->reduction_ops().begin(), C->reduction_ops().end());
1280 }
1281 if (HasAtLeastOneReduction) {
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00001282 bool WithNowait = D.getSingleClause<OMPNowaitClause>() ||
1283 isOpenMPParallelDirective(D.getDirectiveKind()) ||
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00001284 ReductionKind == OMPD_simd;
1285 bool SimpleReduction = ReductionKind == OMPD_simd;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001286 // Emit nowait reduction if nowait clause is present or directive is a
1287 // parallel directive (it always has implicit barrier).
1288 CGM.getOpenMPRuntime().emitReduction(
Stephen Kelly1c301dc2018-08-09 21:09:38 +00001289 *this, D.getEndLoc(), Privates, LHSExprs, RHSExprs, ReductionOps,
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00001290 {WithNowait, SimpleReduction, ReductionKind});
Alexey Bataev794ba0d2015-04-10 10:43:45 +00001291 }
1292}
1293
Alexey Bataev61205072016-03-02 04:57:40 +00001294static void emitPostUpdateForReductionClause(
1295 CodeGenFunction &CGF, const OMPExecutableDirective &D,
Alexey Bataevddf3db92018-04-13 17:31:06 +00001296 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
Alexey Bataev61205072016-03-02 04:57:40 +00001297 if (!CGF.HaveInsertPoint())
1298 return;
1299 llvm::BasicBlock *DoneBB = nullptr;
1300 for (const auto *C : D.getClausesOfKind<OMPReductionClause>()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001301 if (const Expr *PostUpdate = C->getPostUpdateExpr()) {
Alexey Bataev61205072016-03-02 04:57:40 +00001302 if (!DoneBB) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001303 if (llvm::Value *Cond = CondGen(CGF)) {
Alexey Bataev61205072016-03-02 04:57:40 +00001304 // If the first post-update expression is found, emit conditional
1305 // block if it was requested.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001306 llvm::BasicBlock *ThenBB = CGF.createBasicBlock(".omp.reduction.pu");
Alexey Bataev61205072016-03-02 04:57:40 +00001307 DoneBB = CGF.createBasicBlock(".omp.reduction.pu.done");
1308 CGF.Builder.CreateCondBr(Cond, ThenBB, DoneBB);
1309 CGF.EmitBlock(ThenBB);
1310 }
1311 }
1312 CGF.EmitIgnoredExpr(PostUpdate);
1313 }
1314 }
1315 if (DoneBB)
1316 CGF.EmitBlock(DoneBB, /*IsFinished=*/true);
1317}
1318
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00001319namespace {
1320/// Codegen lambda for appending distribute lower and upper bounds to outlined
1321/// parallel function. This is necessary for combined constructs such as
1322/// 'distribute parallel for'
1323typedef llvm::function_ref<void(CodeGenFunction &,
1324 const OMPExecutableDirective &,
1325 llvm::SmallVectorImpl<llvm::Value *> &)>
1326 CodeGenBoundParametersTy;
1327} // anonymous namespace
1328
Alexey Bataev46978742020-01-30 10:46:11 -05001329static void
1330checkForLastprivateConditionalUpdate(CodeGenFunction &CGF,
1331 const OMPExecutableDirective &S) {
1332 if (CGF.getLangOpts().OpenMP < 50)
1333 return;
1334 llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> PrivateDecls;
1335 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
1336 for (const Expr *Ref : C->varlists()) {
1337 if (!Ref->getType()->isScalarType())
1338 continue;
1339 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1340 if (!DRE)
1341 continue;
1342 PrivateDecls.insert(cast<VarDecl>(DRE->getDecl()));
1343 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, Ref);
1344 }
1345 }
1346 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
1347 for (const Expr *Ref : C->varlists()) {
1348 if (!Ref->getType()->isScalarType())
1349 continue;
1350 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1351 if (!DRE)
1352 continue;
1353 PrivateDecls.insert(cast<VarDecl>(DRE->getDecl()));
1354 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, Ref);
1355 }
1356 }
1357 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) {
1358 for (const Expr *Ref : C->varlists()) {
1359 if (!Ref->getType()->isScalarType())
1360 continue;
1361 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1362 if (!DRE)
1363 continue;
1364 PrivateDecls.insert(cast<VarDecl>(DRE->getDecl()));
1365 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, Ref);
1366 }
1367 }
1368 // Privates should ne analyzed since they are not captured at all.
1369 // Task reductions may be skipped - tasks are ignored.
1370 // Firstprivates do not return value but may be passed by reference - no need
1371 // to check for updated lastprivate conditional.
1372 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
1373 for (const Expr *Ref : C->varlists()) {
1374 if (!Ref->getType()->isScalarType())
1375 continue;
1376 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
1377 if (!DRE)
1378 continue;
1379 PrivateDecls.insert(cast<VarDecl>(DRE->getDecl()));
1380 }
1381 }
1382 CGF.CGM.getOpenMPRuntime().checkAndEmitSharedLastprivateConditional(
1383 CGF, S, PrivateDecls);
1384}
1385
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00001386static void emitCommonOMPParallelDirective(
1387 CodeGenFunction &CGF, const OMPExecutableDirective &S,
1388 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen,
1389 const CodeGenBoundParametersTy &CodeGenBoundParameters) {
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00001390 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
James Y Knight9871db02019-02-05 16:42:33 +00001391 llvm::Function *OutlinedFn =
Alexey Bataevddf3db92018-04-13 17:31:06 +00001392 CGF.CGM.getOpenMPRuntime().emitParallelOutlinedFunction(
1393 S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen);
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001394 if (const auto *NumThreadsClause = S.getSingleClause<OMPNumThreadsClause>()) {
Alexey Bataev1d677132015-04-22 13:57:31 +00001395 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001396 llvm::Value *NumThreads =
1397 CGF.EmitScalarExpr(NumThreadsClause->getNumThreads(),
1398 /*IgnoreResultAssign=*/true);
Alexey Bataev1d677132015-04-22 13:57:31 +00001399 CGF.CGM.getOpenMPRuntime().emitNumThreadsClause(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00001400 CGF, NumThreads, NumThreadsClause->getBeginLoc());
Alexey Bataev1d677132015-04-22 13:57:31 +00001401 }
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001402 if (const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>()) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001403 CodeGenFunction::RunCleanupsScope ProcBindScope(CGF);
Alexey Bataev7f210c62015-06-18 13:40:03 +00001404 CGF.CGM.getOpenMPRuntime().emitProcBindClause(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00001405 CGF, ProcBindClause->getProcBindKind(), ProcBindClause->getBeginLoc());
Alexey Bataev7f210c62015-06-18 13:40:03 +00001406 }
Alexey Bataev1d677132015-04-22 13:57:31 +00001407 const Expr *IfCond = nullptr;
Alexey Bataev7371aa32015-09-03 08:45:56 +00001408 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
1409 if (C->getNameModifier() == OMPD_unknown ||
1410 C->getNameModifier() == OMPD_parallel) {
1411 IfCond = C->getCondition();
1412 break;
1413 }
Alexey Bataev1d677132015-04-22 13:57:31 +00001414 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001415
Arpith Chacko Jacobfe4890a2017-01-18 20:40:48 +00001416 OMPParallelScope Scope(CGF, S);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001417 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00001418 // Combining 'distribute' with 'for' requires sharing each 'distribute' chunk
1419 // lower and upper bounds with the pragma 'for' chunking mechanism.
1420 // The following lambda takes care of appending the lower and upper bound
1421 // parameters when necessary
1422 CodeGenBoundParameters(CGF, S, CapturedVars);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00001423 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00001424 CGF.CGM.getOpenMPRuntime().emitParallelCall(CGF, S.getBeginLoc(), OutlinedFn,
Alexey Bataev2377fe92015-09-10 08:12:02 +00001425 CapturedVars, IfCond);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001426}
1427
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00001428static void emitEmptyBoundParameters(CodeGenFunction &,
1429 const OMPExecutableDirective &,
1430 llvm::SmallVectorImpl<llvm::Value *> &) {}
1431
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001432void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
Johannes Doerfert10fedd92019-12-26 11:23:38 -06001433 if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) {
1434 // Check if we have any if clause associated with the directive.
1435 llvm::Value *IfCond = nullptr;
1436 if (const auto *C = S.getSingleClause<OMPIfClause>())
1437 IfCond = EmitScalarExpr(C->getCondition(),
1438 /*IgnoreResultAssign=*/true);
1439
1440 llvm::Value *NumThreads = nullptr;
1441 if (const auto *NumThreadsClause = S.getSingleClause<OMPNumThreadsClause>())
1442 NumThreads = EmitScalarExpr(NumThreadsClause->getNumThreads(),
1443 /*IgnoreResultAssign=*/true);
1444
1445 ProcBindKind ProcBind = OMP_PROC_BIND_default;
1446 if (const auto *ProcBindClause = S.getSingleClause<OMPProcBindClause>())
1447 ProcBind = ProcBindClause->getProcBindKind();
1448
1449 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
1450
1451 // The cleanup callback that finalizes all variabels at the given location,
1452 // thus calls destructors etc.
1453 auto FiniCB = [this](InsertPointTy IP) {
Fady Ghanimba3f8632020-02-19 13:50:26 -06001454 OMPBuilderCBHelpers::FinalizeOMPRegion(*this, IP);
Johannes Doerfert10fedd92019-12-26 11:23:38 -06001455 };
1456
1457 // Privatization callback that performs appropriate action for
1458 // shared/private/firstprivate/lastprivate/copyin/... variables.
1459 //
1460 // TODO: This defaults to shared right now.
1461 auto PrivCB = [](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1462 llvm::Value &Val, llvm::Value *&ReplVal) {
1463 // The next line is appropriate only for variables (Val) with the
1464 // data-sharing attribute "shared".
1465 ReplVal = &Val;
1466
1467 return CodeGenIP;
1468 };
1469
1470 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
1471 const Stmt *ParallelRegionBodyStmt = CS->getCapturedStmt();
1472
1473 auto BodyGenCB = [ParallelRegionBodyStmt,
1474 this](InsertPointTy AllocaIP, InsertPointTy CodeGenIP,
1475 llvm::BasicBlock &ContinuationBB) {
Fady Ghanimba3f8632020-02-19 13:50:26 -06001476 OMPBuilderCBHelpers::OutlinedRegionBodyRAII ORB(*this, AllocaIP,
1477 ContinuationBB);
1478 OMPBuilderCBHelpers::EmitOMPRegionBody(*this, ParallelRegionBodyStmt,
1479 CodeGenIP, ContinuationBB);
Johannes Doerfert10fedd92019-12-26 11:23:38 -06001480 };
1481
1482 CGCapturedStmtInfo CGSI(*CS, CR_OpenMP);
1483 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*this, &CGSI);
1484 Builder.restoreIP(OMPBuilder->CreateParallel(Builder, BodyGenCB, PrivCB,
1485 FiniCB, IfCond, NumThreads,
1486 ProcBind, S.hasCancel()));
1487 return;
1488 }
1489
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001490 // Emit parallel region as a standalone region.
Alexey Bataevc99042b2018-03-15 18:10:54 +00001491 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00001492 Action.Enter(CGF);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001493 OMPPrivateScope PrivateScope(CGF);
Alexey Bataevf56f98c2015-04-16 05:39:01 +00001494 bool Copyins = CGF.EmitOMPCopyinClause(S);
Alexey Bataevcd8b6a22016-02-15 08:07:17 +00001495 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
1496 if (Copyins) {
Alexey Bataev69c62a92015-04-15 04:52:20 +00001497 // Emit implicit barrier to synchronize threads and avoid data races on
Alexey Bataevcd8b6a22016-02-15 08:07:17 +00001498 // propagation master's thread values of threadprivate variables to local
1499 // instances of that variables of all other implicit threads.
Alexey Bataev25e5b442015-09-15 12:52:43 +00001500 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00001501 CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
Alexey Bataev25e5b442015-09-15 12:52:43 +00001502 /*ForceSimpleCall=*/true);
Alexey Bataev69c62a92015-04-15 04:52:20 +00001503 }
1504 CGF.EmitOMPPrivateClause(S, PrivateScope);
1505 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
1506 (void)PrivateScope.Privatize();
Alexey Bataev475a7442018-01-12 19:39:11 +00001507 CGF.EmitStmt(S.getCapturedStmt(OMPD_parallel)->getCapturedStmt());
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00001508 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001509 };
Alexey Bataev46978742020-01-30 10:46:11 -05001510 {
1511 auto LPCRegion =
1512 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
1513 emitCommonOMPParallelDirective(*this, S, OMPD_parallel, CodeGen,
1514 emitEmptyBoundParameters);
1515 emitPostUpdateForReductionClause(*this, S,
1516 [](CodeGenFunction &) { return nullptr; });
1517 }
1518 // Check for outer lastprivate conditional update.
1519 checkForLastprivateConditionalUpdate(*this, S);
Alexey Bataev9959db52014-05-06 10:08:46 +00001520}
Alexander Musman515ad8c2014-05-22 08:54:05 +00001521
Alexey Bataev8bbf2e32019-11-04 09:59:11 -05001522static void emitBody(CodeGenFunction &CGF, const Stmt *S, const Stmt *NextLoop,
1523 int MaxLevel, int Level = 0) {
1524 assert(Level < MaxLevel && "Too deep lookup during loop body codegen.");
1525 const Stmt *SimplifiedS = S->IgnoreContainers();
1526 if (const auto *CS = dyn_cast<CompoundStmt>(SimplifiedS)) {
1527 PrettyStackTraceLoc CrashInfo(
1528 CGF.getContext().getSourceManager(), CS->getLBracLoc(),
1529 "LLVM IR generation of compound statement ('{}')");
1530
1531 // Keep track of the current cleanup stack depth, including debug scopes.
1532 CodeGenFunction::LexicalScope Scope(CGF, S->getSourceRange());
1533 for (const Stmt *CurStmt : CS->body())
1534 emitBody(CGF, CurStmt, NextLoop, MaxLevel, Level);
1535 return;
1536 }
1537 if (SimplifiedS == NextLoop) {
1538 if (const auto *For = dyn_cast<ForStmt>(SimplifiedS)) {
1539 S = For->getBody();
1540 } else {
1541 assert(isa<CXXForRangeStmt>(SimplifiedS) &&
1542 "Expected canonical for loop or range-based for loop.");
1543 const auto *CXXFor = cast<CXXForRangeStmt>(SimplifiedS);
1544 CGF.EmitStmt(CXXFor->getLoopVarStmt());
1545 S = CXXFor->getBody();
1546 }
1547 if (Level + 1 < MaxLevel) {
1548 NextLoop = OMPLoopDirective::tryToFindNextInnerLoop(
1549 S, /*TryImperfectlyNestedLoops=*/true);
1550 emitBody(CGF, S, NextLoop, MaxLevel, Level + 1);
1551 return;
1552 }
1553 }
1554 CGF.EmitStmt(S);
1555}
1556
Alexey Bataev0f34da12015-07-02 04:17:07 +00001557void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D,
1558 JumpDest LoopExit) {
Alexander Musmana5f070a2014-10-01 06:03:56 +00001559 RunCleanupsScope BodyScope(*this);
1560 // Update counters values on current iteration.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001561 for (const Expr *UE : D.updates())
1562 EmitIgnoredExpr(UE);
Alexander Musman3276a272015-03-21 10:12:56 +00001563 // Update the linear variables.
Alexey Bataev617db5f2017-12-04 15:38:33 +00001564 // In distribute directives only loop counters may be marked as linear, no
1565 // need to generate the code for them.
1566 if (!isOpenMPDistributeDirective(D.getDirectiveKind())) {
1567 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001568 for (const Expr *UE : C->updates())
1569 EmitIgnoredExpr(UE);
Alexey Bataev617db5f2017-12-04 15:38:33 +00001570 }
Alexander Musman3276a272015-03-21 10:12:56 +00001571 }
1572
Alexander Musmana5f070a2014-10-01 06:03:56 +00001573 // On a continue in the body, jump to the end.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001574 JumpDest Continue = getJumpDestInCurrentScope("omp.body.continue");
Alexey Bataev0f34da12015-07-02 04:17:07 +00001575 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
Alexey Bataevf8be4762019-08-14 19:30:06 +00001576 for (const Expr *E : D.finals_conditions()) {
1577 if (!E)
1578 continue;
1579 // Check that loop counter in non-rectangular nest fits into the iteration
1580 // space.
1581 llvm::BasicBlock *NextBB = createBasicBlock("omp.body.next");
1582 EmitBranchOnBoolExpr(E, NextBB, Continue.getBlock(),
1583 getProfileCount(D.getBody()));
1584 EmitBlock(NextBB);
1585 }
Alexey Bataevbef93a92019-10-07 18:54:57 +00001586 // Emit loop variables for C++ range loops.
1587 const Stmt *Body =
1588 D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
Alexander Musmana5f070a2014-10-01 06:03:56 +00001589 // Emit loop body.
Alexey Bataev8bbf2e32019-11-04 09:59:11 -05001590 emitBody(*this, Body,
1591 OMPLoopDirective::tryToFindNextInnerLoop(
1592 Body, /*TryImperfectlyNestedLoops=*/true),
1593 D.getCollapsedNumber());
1594
Alexander Musmana5f070a2014-10-01 06:03:56 +00001595 // The end (updates/cleanups).
1596 EmitBlock(Continue.getBlock());
1597 BreakContinueStack.pop_back();
Alexander Musmana5f070a2014-10-01 06:03:56 +00001598}
1599
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001600void CodeGenFunction::EmitOMPInnerLoop(
1601 const Stmt &S, bool RequiresCleanup, const Expr *LoopCond,
1602 const Expr *IncExpr,
Alexey Bataevddf3db92018-04-13 17:31:06 +00001603 const llvm::function_ref<void(CodeGenFunction &)> BodyGen,
1604 const llvm::function_ref<void(CodeGenFunction &)> PostIncGen) {
Alexander Musmand196ef22014-10-07 08:57:09 +00001605 auto LoopExit = getJumpDestInCurrentScope("omp.inner.for.end");
Alexander Musmana5f070a2014-10-01 06:03:56 +00001606
1607 // Start the loop with a block that tests the condition.
Alexander Musmand196ef22014-10-07 08:57:09 +00001608 auto CondBlock = createBasicBlock("omp.inner.for.cond");
Alexander Musmana5f070a2014-10-01 06:03:56 +00001609 EmitBlock(CondBlock);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001610 const SourceRange R = S.getSourceRange();
Amara Emerson652795d2016-11-10 14:44:30 +00001611 LoopStack.push(CondBlock, SourceLocToDebugLoc(R.getBegin()),
1612 SourceLocToDebugLoc(R.getEnd()));
Alexander Musmana5f070a2014-10-01 06:03:56 +00001613
1614 // If there are any cleanups between here and the loop-exit scope,
1615 // create a block to stage a loop exit along.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001616 llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
Alexey Bataev2df54a02015-03-12 08:53:29 +00001617 if (RequiresCleanup)
Alexander Musmand196ef22014-10-07 08:57:09 +00001618 ExitBlock = createBasicBlock("omp.inner.for.cond.cleanup");
Alexander Musmana5f070a2014-10-01 06:03:56 +00001619
Alexey Bataevddf3db92018-04-13 17:31:06 +00001620 llvm::BasicBlock *LoopBody = createBasicBlock("omp.inner.for.body");
Alexander Musmana5f070a2014-10-01 06:03:56 +00001621
Alexey Bataev2df54a02015-03-12 08:53:29 +00001622 // Emit condition.
Justin Bogner66242d62015-04-23 23:06:47 +00001623 EmitBranchOnBoolExpr(LoopCond, LoopBody, ExitBlock, getProfileCount(&S));
Alexander Musmana5f070a2014-10-01 06:03:56 +00001624 if (ExitBlock != LoopExit.getBlock()) {
1625 EmitBlock(ExitBlock);
1626 EmitBranchThroughCleanup(LoopExit);
1627 }
1628
1629 EmitBlock(LoopBody);
Justin Bogner66242d62015-04-23 23:06:47 +00001630 incrementProfileCounter(&S);
Alexander Musmana5f070a2014-10-01 06:03:56 +00001631
1632 // Create a block for the increment.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001633 JumpDest Continue = getJumpDestInCurrentScope("omp.inner.for.inc");
Alexander Musmana5f070a2014-10-01 06:03:56 +00001634 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
1635
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00001636 BodyGen(*this);
Alexander Musmana5f070a2014-10-01 06:03:56 +00001637
1638 // Emit "IV = IV + 1" and a back-edge to the condition block.
1639 EmitBlock(Continue.getBlock());
Alexey Bataev2df54a02015-03-12 08:53:29 +00001640 EmitIgnoredExpr(IncExpr);
Alexey Bataev98eb6e32015-04-22 11:15:40 +00001641 PostIncGen(*this);
Alexander Musmana5f070a2014-10-01 06:03:56 +00001642 BreakContinueStack.pop_back();
1643 EmitBranch(CondBlock);
1644 LoopStack.pop();
1645 // Emit the fall-through block.
1646 EmitBlock(LoopExit.getBlock());
1647}
1648
Alexey Bataev8c3edfe2017-08-16 15:58:46 +00001649bool CodeGenFunction::EmitOMPLinearClauseInit(const OMPLoopDirective &D) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001650 if (!HaveInsertPoint())
Alexey Bataev8c3edfe2017-08-16 15:58:46 +00001651 return false;
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001652 // Emit inits for the linear variables.
Alexey Bataev8c3edfe2017-08-16 15:58:46 +00001653 bool HasLinears = false;
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001654 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001655 for (const Expr *Init : C->inits()) {
Alexey Bataev8c3edfe2017-08-16 15:58:46 +00001656 HasLinears = true;
Alexey Bataevddf3db92018-04-13 17:31:06 +00001657 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(Init)->getDecl());
1658 if (const auto *Ref =
1659 dyn_cast<DeclRefExpr>(VD->getInit()->IgnoreImpCasts())) {
Alexey Bataevef549a82016-03-09 09:49:09 +00001660 AutoVarEmission Emission = EmitAutoVarAlloca(*VD);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001661 const auto *OrigVD = cast<VarDecl>(Ref->getDecl());
Bruno Ricci5fc4db72018-12-21 14:10:18 +00001662 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
Alexey Bataevef549a82016-03-09 09:49:09 +00001663 CapturedStmtInfo->lookup(OrigVD) != nullptr,
1664 VD->getInit()->getType(), VK_LValue,
1665 VD->getInit()->getExprLoc());
1666 EmitExprAsInit(&DRE, VD, MakeAddrLValue(Emission.getAllocatedAddress(),
1667 VD->getType()),
1668 /*capturedByInit=*/false);
1669 EmitAutoVarCleanups(Emission);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001670 } else {
Alexey Bataevef549a82016-03-09 09:49:09 +00001671 EmitVarDecl(*VD);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001672 }
Alexander Musmana5f070a2014-10-01 06:03:56 +00001673 }
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001674 // Emit the linear steps for the linear clauses.
1675 // If a step is not constant, it is pre-calculated before the loop.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001676 if (const auto *CS = cast_or_null<BinaryOperator>(C->getCalcStep()))
1677 if (const auto *SaveRef = cast<DeclRefExpr>(CS->getLHS())) {
Alexey Bataev3b5b5c42015-06-18 10:10:12 +00001678 EmitVarDecl(*cast<VarDecl>(SaveRef->getDecl()));
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001679 // Emit calculation of the linear step.
Alexey Bataev3b5b5c42015-06-18 10:10:12 +00001680 EmitIgnoredExpr(CS);
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001681 }
Alexander Musmana5f070a2014-10-01 06:03:56 +00001682 }
Alexey Bataev8c3edfe2017-08-16 15:58:46 +00001683 return HasLinears;
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001684}
1685
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001686void CodeGenFunction::EmitOMPLinearClauseFinal(
1687 const OMPLoopDirective &D,
Alexey Bataevddf3db92018-04-13 17:31:06 +00001688 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001689 if (!HaveInsertPoint())
Alexey Bataev8ef31412015-12-18 07:58:25 +00001690 return;
Alexey Bataevef549a82016-03-09 09:49:09 +00001691 llvm::BasicBlock *DoneBB = nullptr;
Alexander Musman3276a272015-03-21 10:12:56 +00001692 // Emit the final values of the linear variables.
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001693 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
Alexey Bataev39f915b82015-05-08 10:41:21 +00001694 auto IC = C->varlist_begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001695 for (const Expr *F : C->finals()) {
Alexey Bataevef549a82016-03-09 09:49:09 +00001696 if (!DoneBB) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001697 if (llvm::Value *Cond = CondGen(*this)) {
Alexey Bataevef549a82016-03-09 09:49:09 +00001698 // If the first post-update expression is found, emit conditional
1699 // block if it was requested.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001700 llvm::BasicBlock *ThenBB = createBasicBlock(".omp.linear.pu");
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001701 DoneBB = createBasicBlock(".omp.linear.pu.done");
1702 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
1703 EmitBlock(ThenBB);
Alexey Bataevef549a82016-03-09 09:49:09 +00001704 }
1705 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00001706 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IC)->getDecl());
Bruno Ricci5fc4db72018-12-21 14:10:18 +00001707 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(OrigVD),
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001708 CapturedStmtInfo->lookup(OrigVD) != nullptr,
Alexey Bataev39f915b82015-05-08 10:41:21 +00001709 (*IC)->getType(), VK_LValue, (*IC)->getExprLoc());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001710 Address OrigAddr = EmitLValue(&DRE).getAddress(*this);
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001711 CodeGenFunction::OMPPrivateScope VarScope(*this);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001712 VarScope.addPrivate(OrigVD, [OrigAddr]() { return OrigAddr; });
Alexey Bataev39f915b82015-05-08 10:41:21 +00001713 (void)VarScope.Privatize();
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001714 EmitIgnoredExpr(F);
Alexey Bataev39f915b82015-05-08 10:41:21 +00001715 ++IC;
Alexander Musman3276a272015-03-21 10:12:56 +00001716 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00001717 if (const Expr *PostUpdate = C->getPostUpdateExpr())
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001718 EmitIgnoredExpr(PostUpdate);
Alexander Musman3276a272015-03-21 10:12:56 +00001719 }
Alexey Bataevef549a82016-03-09 09:49:09 +00001720 if (DoneBB)
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001721 EmitBlock(DoneBB, /*IsFinished=*/true);
Alexander Musmana5f070a2014-10-01 06:03:56 +00001722}
1723
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001724static void emitAlignedClause(CodeGenFunction &CGF,
1725 const OMPExecutableDirective &D) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001726 if (!CGF.HaveInsertPoint())
1727 return;
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001728 for (const auto *Clause : D.getClausesOfKind<OMPAlignedClause>()) {
Erich Keanef7593952019-10-11 14:59:44 +00001729 llvm::APInt ClauseAlignment(64, 0);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001730 if (const Expr *AlignmentExpr = Clause->getAlignment()) {
1731 auto *AlignmentCI =
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001732 cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AlignmentExpr));
Erich Keanef7593952019-10-11 14:59:44 +00001733 ClauseAlignment = AlignmentCI->getValue();
Alexander Musman09184fe2014-09-30 05:29:28 +00001734 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00001735 for (const Expr *E : Clause->varlists()) {
Erich Keanef7593952019-10-11 14:59:44 +00001736 llvm::APInt Alignment(ClauseAlignment);
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001737 if (Alignment == 0) {
1738 // OpenMP [2.8.1, Description]
1739 // If no optional parameter is specified, implementation-defined default
1740 // alignments for SIMD instructions on the target platforms are assumed.
1741 Alignment =
Alexey Bataev00396512015-07-02 03:40:19 +00001742 CGF.getContext()
1743 .toCharUnitsFromBits(CGF.getContext().getOpenMPDefaultSimdAlign(
1744 E->getType()->getPointeeType()))
1745 .getQuantity();
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001746 }
Erich Keanef7593952019-10-11 14:59:44 +00001747 assert((Alignment == 0 || Alignment.isPowerOf2()) &&
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001748 "alignment is not power of 2");
1749 if (Alignment != 0) {
1750 llvm::Value *PtrValue = CGF.EmitScalarExpr(E);
Fangrui Song1d49eb02020-02-13 16:36:27 -08001751 CGF.emitAlignmentAssumption(
Erich Keanef7593952019-10-11 14:59:44 +00001752 PtrValue, E, /*No second loc needed*/ SourceLocation(),
1753 llvm::ConstantInt::get(CGF.getLLVMContext(), Alignment));
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001754 }
Alexander Musman09184fe2014-09-30 05:29:28 +00001755 }
1756 }
1757}
1758
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001759void CodeGenFunction::EmitOMPPrivateLoopCounters(
1760 const OMPLoopDirective &S, CodeGenFunction::OMPPrivateScope &LoopScope) {
1761 if (!HaveInsertPoint())
Alexey Bataev8ef31412015-12-18 07:58:25 +00001762 return;
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001763 auto I = S.private_counters().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001764 for (const Expr *E : S.counters()) {
1765 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
1766 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl());
Alexey Bataevab4ea222018-03-07 18:17:06 +00001767 // Emit var without initialization.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001768 AutoVarEmission VarEmission = EmitAutoVarAlloca(*PrivateVD);
Alexey Bataevab4ea222018-03-07 18:17:06 +00001769 EmitAutoVarCleanups(VarEmission);
1770 LocalDeclMap.erase(PrivateVD);
1771 (void)LoopScope.addPrivate(VD, [&VarEmission]() {
1772 return VarEmission.getAllocatedAddress();
Alexey Bataev435ad7b2014-10-10 09:48:26 +00001773 });
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001774 if (LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD) ||
1775 VD->hasGlobalStorage()) {
Alexey Bataevab4ea222018-03-07 18:17:06 +00001776 (void)LoopScope.addPrivate(PrivateVD, [this, VD, E]() {
Bruno Ricci5fc4db72018-12-21 14:10:18 +00001777 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(VD),
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001778 LocalDeclMap.count(VD) || CapturedStmtInfo->lookup(VD),
1779 E->getType(), VK_LValue, E->getExprLoc());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001780 return EmitLValue(&DRE).getAddress(*this);
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001781 });
Alexey Bataevab4ea222018-03-07 18:17:06 +00001782 } else {
1783 (void)LoopScope.addPrivate(PrivateVD, [&VarEmission]() {
1784 return VarEmission.getAllocatedAddress();
1785 });
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001786 }
Alexey Bataeva8899172015-08-06 12:30:57 +00001787 ++I;
Alexey Bataev435ad7b2014-10-10 09:48:26 +00001788 }
Alexey Bataevf138fda2018-08-13 19:04:24 +00001789 // Privatize extra loop counters used in loops for ordered(n) clauses.
1790 for (const auto *C : S.getClausesOfKind<OMPOrderedClause>()) {
1791 if (!C->getNumForLoops())
1792 continue;
1793 for (unsigned I = S.getCollapsedNumber(),
1794 E = C->getLoopNumIterations().size();
1795 I < E; ++I) {
Mike Rice0ed46662018-09-20 17:19:41 +00001796 const auto *DRE = cast<DeclRefExpr>(C->getLoopCounter(I));
Alexey Bataevf138fda2018-08-13 19:04:24 +00001797 const auto *VD = cast<VarDecl>(DRE->getDecl());
Alexey Bataev0d8fcdf2019-03-14 20:36:00 +00001798 // Override only those variables that can be captured to avoid re-emission
1799 // of the variables declared within the loops.
1800 if (DRE->refersToEnclosingVariableOrCapture()) {
Alexey Bataevf138fda2018-08-13 19:04:24 +00001801 (void)LoopScope.addPrivate(VD, [this, DRE, VD]() {
1802 return CreateMemTemp(DRE->getType(), VD->getName());
1803 });
1804 }
1805 }
1806 }
Alexey Bataev435ad7b2014-10-10 09:48:26 +00001807}
1808
Alexey Bataev62dbb972015-04-22 11:59:37 +00001809static void emitPreCond(CodeGenFunction &CGF, const OMPLoopDirective &S,
1810 const Expr *Cond, llvm::BasicBlock *TrueBlock,
1811 llvm::BasicBlock *FalseBlock, uint64_t TrueCount) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001812 if (!CGF.HaveInsertPoint())
1813 return;
Alexey Bataev6e8248f2015-06-11 10:53:56 +00001814 {
1815 CodeGenFunction::OMPPrivateScope PreCondScope(CGF);
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001816 CGF.EmitOMPPrivateLoopCounters(S, PreCondScope);
Alexey Bataev6e8248f2015-06-11 10:53:56 +00001817 (void)PreCondScope.Privatize();
Alexey Bataev6e8248f2015-06-11 10:53:56 +00001818 // Get initial values of real counters.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001819 for (const Expr *I : S.inits()) {
Alexey Bataev6e8248f2015-06-11 10:53:56 +00001820 CGF.EmitIgnoredExpr(I);
1821 }
Alexey Bataev62dbb972015-04-22 11:59:37 +00001822 }
Alexey Bataevf8be4762019-08-14 19:30:06 +00001823 // Create temp loop control variables with their init values to support
1824 // non-rectangular loops.
1825 CodeGenFunction::OMPMapVars PreCondVars;
1826 for (const Expr * E: S.dependent_counters()) {
1827 if (!E)
1828 continue;
1829 assert(!E->getType().getNonReferenceType()->isRecordType() &&
1830 "dependent counter must not be an iterator.");
1831 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
1832 Address CounterAddr =
1833 CGF.CreateMemTemp(VD->getType().getNonReferenceType());
1834 (void)PreCondVars.setVarAddr(CGF, VD, CounterAddr);
1835 }
1836 (void)PreCondVars.apply(CGF);
1837 for (const Expr *E : S.dependent_inits()) {
1838 if (!E)
1839 continue;
1840 CGF.EmitIgnoredExpr(E);
1841 }
Alexey Bataev62dbb972015-04-22 11:59:37 +00001842 // Check that loop is executed at least one time.
1843 CGF.EmitBranchOnBoolExpr(Cond, TrueBlock, FalseBlock, TrueCount);
Alexey Bataevf8be4762019-08-14 19:30:06 +00001844 PreCondVars.restore(CGF);
Alexey Bataev62dbb972015-04-22 11:59:37 +00001845}
1846
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001847void CodeGenFunction::EmitOMPLinearClause(
1848 const OMPLoopDirective &D, CodeGenFunction::OMPPrivateScope &PrivateScope) {
1849 if (!HaveInsertPoint())
Alexey Bataev8ef31412015-12-18 07:58:25 +00001850 return;
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001851 llvm::DenseSet<const VarDecl *> SIMDLCVs;
1852 if (isOpenMPSimdDirective(D.getDirectiveKind())) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001853 const auto *LoopDirective = cast<OMPLoopDirective>(&D);
1854 for (const Expr *C : LoopDirective->counters()) {
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001855 SIMDLCVs.insert(
1856 cast<VarDecl>(cast<DeclRefExpr>(C)->getDecl())->getCanonicalDecl());
1857 }
1858 }
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001859 for (const auto *C : D.getClausesOfKind<OMPLinearClause>()) {
Alexey Bataevbd9fec12015-08-18 06:47:21 +00001860 auto CurPrivate = C->privates().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001861 for (const Expr *E : C->varlists()) {
1862 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
1863 const auto *PrivateVD =
Alexey Bataevbd9fec12015-08-18 06:47:21 +00001864 cast<VarDecl>(cast<DeclRefExpr>(*CurPrivate)->getDecl());
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001865 if (!SIMDLCVs.count(VD->getCanonicalDecl())) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001866 bool IsRegistered = PrivateScope.addPrivate(VD, [this, PrivateVD]() {
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001867 // Emit private VarDecl with copy init.
1868 EmitVarDecl(*PrivateVD);
1869 return GetAddrOfLocalVar(PrivateVD);
1870 });
1871 assert(IsRegistered && "linear var already registered as private");
1872 // Silence the warning about unused variable.
1873 (void)IsRegistered;
Alexey Bataevddf3db92018-04-13 17:31:06 +00001874 } else {
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001875 EmitVarDecl(*PrivateVD);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001876 }
Alexey Bataevbd9fec12015-08-18 06:47:21 +00001877 ++CurPrivate;
Alexander Musman3276a272015-03-21 10:12:56 +00001878 }
1879 }
1880}
1881
Alexey Bataev45bfad52015-08-21 12:19:04 +00001882static void emitSimdlenSafelenClause(CodeGenFunction &CGF,
Alexey Bataeva6f2a142015-12-31 06:52:34 +00001883 const OMPExecutableDirective &D,
1884 bool IsMonotonic) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001885 if (!CGF.HaveInsertPoint())
1886 return;
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001887 if (const auto *C = D.getSingleClause<OMPSimdlenClause>()) {
Alexey Bataev45bfad52015-08-21 12:19:04 +00001888 RValue Len = CGF.EmitAnyExpr(C->getSimdlen(), AggValueSlot::ignored(),
1889 /*ignoreResult=*/true);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001890 auto *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
Alexey Bataev45bfad52015-08-21 12:19:04 +00001891 CGF.LoopStack.setVectorizeWidth(Val->getZExtValue());
1892 // In presence of finite 'safelen', it may be unsafe to mark all
1893 // the memory instructions parallel, because loop-carried
1894 // dependences of 'safelen' iterations are possible.
Alexey Bataeva6f2a142015-12-31 06:52:34 +00001895 if (!IsMonotonic)
1896 CGF.LoopStack.setParallel(!D.getSingleClause<OMPSafelenClause>());
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00001897 } else if (const auto *C = D.getSingleClause<OMPSafelenClause>()) {
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001898 RValue Len = CGF.EmitAnyExpr(C->getSafelen(), AggValueSlot::ignored(),
1899 /*ignoreResult=*/true);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001900 auto *Val = cast<llvm::ConstantInt>(Len.getScalarVal());
Tyler Nowickida46d0e2015-07-14 23:03:09 +00001901 CGF.LoopStack.setVectorizeWidth(Val->getZExtValue());
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001902 // In presence of finite 'safelen', it may be unsafe to mark all
1903 // the memory instructions parallel, because loop-carried
1904 // dependences of 'safelen' iterations are possible.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001905 CGF.LoopStack.setParallel(/*Enable=*/false);
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00001906 }
1907}
1908
Alexey Bataeva6f2a142015-12-31 06:52:34 +00001909void CodeGenFunction::EmitOMPSimdInit(const OMPLoopDirective &D,
1910 bool IsMonotonic) {
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00001911 // Walk clauses and process safelen/lastprivate.
Alexey Bataeva6f2a142015-12-31 06:52:34 +00001912 LoopStack.setParallel(!IsMonotonic);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001913 LoopStack.setVectorizeEnable();
Alexey Bataeva6f2a142015-12-31 06:52:34 +00001914 emitSimdlenSafelenClause(*this, D, IsMonotonic);
Alexey Bataeva7815212020-02-03 12:08:16 -05001915 if (const auto *C = D.getSingleClause<OMPOrderClause>())
1916 if (C->getKind() == OMPC_ORDER_concurrent)
1917 LoopStack.setParallel(/*Enable=*/true);
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00001918}
1919
Alexey Bataevef549a82016-03-09 09:49:09 +00001920void CodeGenFunction::EmitOMPSimdFinal(
1921 const OMPLoopDirective &D,
Alexey Bataevddf3db92018-04-13 17:31:06 +00001922 const llvm::function_ref<llvm::Value *(CodeGenFunction &)> CondGen) {
Alexey Bataev8ef31412015-12-18 07:58:25 +00001923 if (!HaveInsertPoint())
1924 return;
Alexey Bataevef549a82016-03-09 09:49:09 +00001925 llvm::BasicBlock *DoneBB = nullptr;
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00001926 auto IC = D.counters().begin();
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001927 auto IPC = D.private_counters().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00001928 for (const Expr *F : D.finals()) {
1929 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>((*IC))->getDecl());
1930 const auto *PrivateVD = cast<VarDecl>(cast<DeclRefExpr>((*IPC))->getDecl());
1931 const auto *CED = dyn_cast<OMPCapturedExprDecl>(OrigVD);
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001932 if (LocalDeclMap.count(OrigVD) || CapturedStmtInfo->lookup(OrigVD) ||
1933 OrigVD->hasGlobalStorage() || CED) {
Alexey Bataevef549a82016-03-09 09:49:09 +00001934 if (!DoneBB) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00001935 if (llvm::Value *Cond = CondGen(*this)) {
Alexey Bataevef549a82016-03-09 09:49:09 +00001936 // If the first post-update expression is found, emit conditional
1937 // block if it was requested.
Alexey Bataevddf3db92018-04-13 17:31:06 +00001938 llvm::BasicBlock *ThenBB = createBasicBlock(".omp.final.then");
Alexey Bataevef549a82016-03-09 09:49:09 +00001939 DoneBB = createBasicBlock(".omp.final.done");
1940 Builder.CreateCondBr(Cond, ThenBB, DoneBB);
1941 EmitBlock(ThenBB);
1942 }
1943 }
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001944 Address OrigAddr = Address::invalid();
Alexey Bataevab4ea222018-03-07 18:17:06 +00001945 if (CED) {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001946 OrigAddr =
1947 EmitLValue(CED->getInit()->IgnoreImpCasts()).getAddress(*this);
Alexey Bataevab4ea222018-03-07 18:17:06 +00001948 } else {
Bruno Ricci5fc4db72018-12-21 14:10:18 +00001949 DeclRefExpr DRE(getContext(), const_cast<VarDecl *>(PrivateVD),
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001950 /*RefersToEnclosingVariableOrCapture=*/false,
1951 (*IPC)->getType(), VK_LValue, (*IPC)->getExprLoc());
Akira Hatanakaf139ae32019-12-03 15:17:01 -08001952 OrigAddr = EmitLValue(&DRE).getAddress(*this);
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001953 }
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00001954 OMPPrivateScope VarScope(*this);
Alexey Bataevddf3db92018-04-13 17:31:06 +00001955 VarScope.addPrivate(OrigVD, [OrigAddr]() { return OrigAddr; });
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00001956 (void)VarScope.Privatize();
1957 EmitIgnoredExpr(F);
1958 }
1959 ++IC;
Alexey Bataev5dff95c2016-04-22 03:56:56 +00001960 ++IPC;
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00001961 }
Alexey Bataevef549a82016-03-09 09:49:09 +00001962 if (DoneBB)
1963 EmitBlock(DoneBB, /*IsFinished=*/true);
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00001964}
1965
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00001966static void emitOMPLoopBodyWithStopPoint(CodeGenFunction &CGF,
1967 const OMPLoopDirective &S,
1968 CodeGenFunction::JumpDest LoopExit) {
1969 CGF.EmitOMPLoopBody(S, LoopExit);
1970 CGF.EmitStopPoint(&S);
Hans Wennborged129ae2017-04-27 17:02:25 +00001971}
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00001972
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00001973/// Emit a helper variable and return corresponding lvalue.
1974static LValue EmitOMPHelperVar(CodeGenFunction &CGF,
1975 const DeclRefExpr *Helper) {
1976 auto VDecl = cast<VarDecl>(Helper->getDecl());
1977 CGF.EmitVarDecl(*VDecl);
1978 return CGF.EmitLValue(Helper);
1979}
1980
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05001981static void emitCommonSimdLoop(CodeGenFunction &CGF, const OMPLoopDirective &S,
1982 const RegionCodeGenTy &SimdInitGen,
1983 const RegionCodeGenTy &BodyCodeGen) {
Alexey Bataev0860db92019-12-19 10:01:10 -05001984 auto &&ThenGen = [&S, &SimdInitGen, &BodyCodeGen](CodeGenFunction &CGF,
1985 PrePostActionTy &) {
1986 CGOpenMPRuntime::NontemporalDeclsRAII NontemporalsRegion(CGF.CGM, S);
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05001987 CodeGenFunction::OMPLocalDeclMapRAII Scope(CGF);
1988 SimdInitGen(CGF);
1989
1990 BodyCodeGen(CGF);
1991 };
1992 auto &&ElseGen = [&BodyCodeGen](CodeGenFunction &CGF, PrePostActionTy &) {
1993 CodeGenFunction::OMPLocalDeclMapRAII Scope(CGF);
1994 CGF.LoopStack.setVectorizeEnable(/*Enable=*/false);
1995
1996 BodyCodeGen(CGF);
1997 };
1998 const Expr *IfCond = nullptr;
Alexey Bataev18789bf2020-02-13 09:21:15 -05001999 if (isOpenMPSimdDirective(S.getDirectiveKind())) {
2000 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
2001 if (CGF.getLangOpts().OpenMP >= 50 &&
2002 (C->getNameModifier() == OMPD_unknown ||
2003 C->getNameModifier() == OMPD_simd)) {
2004 IfCond = C->getCondition();
2005 break;
2006 }
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002007 }
2008 }
2009 if (IfCond) {
2010 CGF.CGM.getOpenMPRuntime().emitIfClause(CGF, IfCond, ThenGen, ElseGen);
2011 } else {
2012 RegionCodeGenTy ThenRCG(ThenGen);
2013 ThenRCG(CGF);
2014 }
2015}
2016
Alexey Bataevf8365372017-11-17 17:57:25 +00002017static void emitOMPSimdRegion(CodeGenFunction &CGF, const OMPLoopDirective &S,
2018 PrePostActionTy &Action) {
2019 Action.Enter(CGF);
2020 assert(isOpenMPSimdDirective(S.getDirectiveKind()) &&
2021 "Expected simd directive");
2022 OMPLoopScope PreInitScope(CGF, S);
2023 // if (PreCond) {
2024 // for (IV in 0..LastIteration) BODY;
2025 // <Final counter/linear vars updates>;
2026 // }
2027 //
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00002028 if (isOpenMPDistributeDirective(S.getDirectiveKind()) ||
2029 isOpenMPWorksharingDirective(S.getDirectiveKind()) ||
2030 isOpenMPTaskLoopDirective(S.getDirectiveKind())) {
2031 (void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable()));
2032 (void)EmitOMPHelperVar(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable()));
2033 }
Alexander Musmana5f070a2014-10-01 06:03:56 +00002034
Alexey Bataevf8365372017-11-17 17:57:25 +00002035 // Emit: if (PreCond) - begin.
2036 // If the condition constant folds and can be elided, avoid emitting the
2037 // whole loop.
2038 bool CondConstant;
2039 llvm::BasicBlock *ContBlock = nullptr;
2040 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
2041 if (!CondConstant)
2042 return;
2043 } else {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002044 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("simd.if.then");
Alexey Bataevf8365372017-11-17 17:57:25 +00002045 ContBlock = CGF.createBasicBlock("simd.if.end");
2046 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
2047 CGF.getProfileCount(&S));
2048 CGF.EmitBlock(ThenBlock);
2049 CGF.incrementProfileCounter(&S);
2050 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002051
Alexey Bataevf8365372017-11-17 17:57:25 +00002052 // Emit the loop iteration variable.
2053 const Expr *IVExpr = S.getIterationVariable();
Alexey Bataevddf3db92018-04-13 17:31:06 +00002054 const auto *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
Alexey Bataevf8365372017-11-17 17:57:25 +00002055 CGF.EmitVarDecl(*IVDecl);
2056 CGF.EmitIgnoredExpr(S.getInit());
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002057
Alexey Bataevf8365372017-11-17 17:57:25 +00002058 // Emit the iterations count variable.
2059 // If it is not a variable, Sema decided to calculate iterations count on
2060 // each iteration (e.g., it is foldable into a constant).
Alexey Bataevddf3db92018-04-13 17:31:06 +00002061 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
Alexey Bataevf8365372017-11-17 17:57:25 +00002062 CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
2063 // Emit calculation of the iterations count.
2064 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
2065 }
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002066
Alexey Bataevf8365372017-11-17 17:57:25 +00002067 emitAlignedClause(CGF, S);
2068 (void)CGF.EmitOMPLinearClauseInit(S);
2069 {
2070 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
2071 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
2072 CGF.EmitOMPLinearClause(S, LoopScope);
2073 CGF.EmitOMPPrivateClause(S, LoopScope);
2074 CGF.EmitOMPReductionClauseInit(S, LoopScope);
Alexey Bataeva58da1a2019-12-27 09:44:43 -05002075 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(
2076 CGF, S, CGF.EmitLValue(S.getIterationVariable()));
Alexey Bataevf8365372017-11-17 17:57:25 +00002077 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
2078 (void)LoopScope.Privatize();
Alexey Bataev60705422018-10-30 15:50:12 +00002079 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
2080 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
Alexey Bataevd08c0562019-11-19 12:07:54 -05002081
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002082 emitCommonSimdLoop(
2083 CGF, S,
2084 [&S](CodeGenFunction &CGF, PrePostActionTy &) {
2085 CGF.EmitOMPSimdInit(S);
2086 },
2087 [&S, &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
2088 CGF.EmitOMPInnerLoop(
2089 S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(),
2090 [&S](CodeGenFunction &CGF) {
2091 CGF.EmitOMPLoopBody(S, CodeGenFunction::JumpDest());
2092 CGF.EmitStopPoint(&S);
2093 },
2094 [](CodeGenFunction &) {});
2095 });
Alexey Bataevddf3db92018-04-13 17:31:06 +00002096 CGF.EmitOMPSimdFinal(S, [](CodeGenFunction &) { return nullptr; });
Alexey Bataevf8365372017-11-17 17:57:25 +00002097 // Emit final copy of the lastprivate variables at the end of loops.
2098 if (HasLastprivateClause)
2099 CGF.EmitOMPLastprivateClauseFinal(S, /*NoFinals=*/true);
2100 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_simd);
Alexey Bataevddf3db92018-04-13 17:31:06 +00002101 emitPostUpdateForReductionClause(CGF, S,
2102 [](CodeGenFunction &) { return nullptr; });
Alexey Bataevf8365372017-11-17 17:57:25 +00002103 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00002104 CGF.EmitOMPLinearClauseFinal(S, [](CodeGenFunction &) { return nullptr; });
Alexey Bataevf8365372017-11-17 17:57:25 +00002105 // Emit: if (PreCond) - end.
2106 if (ContBlock) {
2107 CGF.EmitBranch(ContBlock);
2108 CGF.EmitBlock(ContBlock, true);
2109 }
2110}
2111
2112void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
2113 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
2114 emitOMPSimdRegion(CGF, S, Action);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002115 };
Alexey Bataev46978742020-01-30 10:46:11 -05002116 {
2117 auto LPCRegion =
2118 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
2119 OMPLexicalScope Scope(*this, S, OMPD_unknown);
2120 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
2121 }
2122 // Check for outer lastprivate conditional update.
2123 checkForLastprivateConditionalUpdate(*this, S);
Alexander Musman515ad8c2014-05-22 08:54:05 +00002124}
2125
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002126void CodeGenFunction::EmitOMPOuterLoop(
2127 bool DynamicOrOrdered, bool IsMonotonic, const OMPLoopDirective &S,
2128 CodeGenFunction::OMPPrivateScope &LoopScope,
2129 const CodeGenFunction::OMPLoopArguments &LoopArgs,
2130 const CodeGenFunction::CodeGenLoopTy &CodeGenLoop,
2131 const CodeGenFunction::CodeGenOrderedTy &CodeGenOrdered) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002132 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
Alexander Musman92bdaab2015-03-12 13:37:50 +00002133
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002134 const Expr *IVExpr = S.getIterationVariable();
2135 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
2136 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
2137
Alexey Bataevddf3db92018-04-13 17:31:06 +00002138 JumpDest LoopExit = getJumpDestInCurrentScope("omp.dispatch.end");
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002139
2140 // Start the loop with a block that tests the condition.
Alexey Bataevddf3db92018-04-13 17:31:06 +00002141 llvm::BasicBlock *CondBlock = createBasicBlock("omp.dispatch.cond");
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002142 EmitBlock(CondBlock);
Alexey Bataevddf3db92018-04-13 17:31:06 +00002143 const SourceRange R = S.getSourceRange();
Amara Emerson652795d2016-11-10 14:44:30 +00002144 LoopStack.push(CondBlock, SourceLocToDebugLoc(R.getBegin()),
2145 SourceLocToDebugLoc(R.getEnd()));
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002146
2147 llvm::Value *BoolCondVal = nullptr;
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002148 if (!DynamicOrOrdered) {
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002149 // UB = min(UB, GlobalUB) or
2150 // UB = min(UB, PrevUB) for combined loop sharing constructs (e.g.
2151 // 'distribute parallel for')
2152 EmitIgnoredExpr(LoopArgs.EUB);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002153 // IV = LB
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002154 EmitIgnoredExpr(LoopArgs.Init);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002155 // IV < UB
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002156 BoolCondVal = EvaluateExprAsBool(LoopArgs.Cond);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002157 } else {
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002158 BoolCondVal =
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002159 RT.emitForNext(*this, S.getBeginLoc(), IVSize, IVSigned, LoopArgs.IL,
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002160 LoopArgs.LB, LoopArgs.UB, LoopArgs.ST);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002161 }
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002162
2163 // If there are any cleanups between here and the loop-exit scope,
2164 // create a block to stage a loop exit along.
Alexey Bataevddf3db92018-04-13 17:31:06 +00002165 llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002166 if (LoopScope.requiresCleanups())
2167 ExitBlock = createBasicBlock("omp.dispatch.cleanup");
2168
Alexey Bataevddf3db92018-04-13 17:31:06 +00002169 llvm::BasicBlock *LoopBody = createBasicBlock("omp.dispatch.body");
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002170 Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
2171 if (ExitBlock != LoopExit.getBlock()) {
2172 EmitBlock(ExitBlock);
2173 EmitBranchThroughCleanup(LoopExit);
2174 }
2175 EmitBlock(LoopBody);
2176
Alexander Musman92bdaab2015-03-12 13:37:50 +00002177 // Emit "IV = LB" (in case of static schedule, we have already calculated new
2178 // LB for loop condition and emitted it above).
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002179 if (DynamicOrOrdered)
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002180 EmitIgnoredExpr(LoopArgs.Init);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002181
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002182 // Create a block for the increment.
Alexey Bataevddf3db92018-04-13 17:31:06 +00002183 JumpDest Continue = getJumpDestInCurrentScope("omp.dispatch.inc");
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002184 BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
2185
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002186 emitCommonSimdLoop(
2187 *this, S,
2188 [&S, IsMonotonic](CodeGenFunction &CGF, PrePostActionTy &) {
2189 // Generate !llvm.loop.parallel metadata for loads and stores for loops
2190 // with dynamic/guided scheduling and without ordered clause.
Alexey Bataeva7815212020-02-03 12:08:16 -05002191 if (!isOpenMPSimdDirective(S.getDirectiveKind())) {
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002192 CGF.LoopStack.setParallel(!IsMonotonic);
Alexey Bataeva7815212020-02-03 12:08:16 -05002193 if (const auto *C = S.getSingleClause<OMPOrderClause>())
2194 if (C->getKind() == OMPC_ORDER_concurrent)
2195 CGF.LoopStack.setParallel(/*Enable=*/true);
2196 } else {
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002197 CGF.EmitOMPSimdInit(S, IsMonotonic);
Alexey Bataeva7815212020-02-03 12:08:16 -05002198 }
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002199 },
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002200 [&S, &LoopArgs, LoopExit, &CodeGenLoop, IVSize, IVSigned, &CodeGenOrdered,
2201 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
2202 SourceLocation Loc = S.getBeginLoc();
2203 // when 'distribute' is not combined with a 'for':
2204 // while (idx <= UB) { BODY; ++idx; }
2205 // when 'distribute' is combined with a 'for'
2206 // (e.g. 'distribute parallel for')
2207 // while (idx <= UB) { <CodeGen rest of pragma>; idx += ST; }
2208 CGF.EmitOMPInnerLoop(
2209 S, LoopScope.requiresCleanups(), LoopArgs.Cond, LoopArgs.IncExpr,
2210 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
2211 CodeGenLoop(CGF, S, LoopExit);
2212 },
2213 [IVSize, IVSigned, Loc, &CodeGenOrdered](CodeGenFunction &CGF) {
2214 CodeGenOrdered(CGF, Loc, IVSize, IVSigned);
2215 });
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002216 });
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002217
2218 EmitBlock(Continue.getBlock());
2219 BreakContinueStack.pop_back();
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002220 if (!DynamicOrOrdered) {
Alexander Musman92bdaab2015-03-12 13:37:50 +00002221 // Emit "LB = LB + Stride", "UB = UB + Stride".
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002222 EmitIgnoredExpr(LoopArgs.NextLB);
2223 EmitIgnoredExpr(LoopArgs.NextUB);
Alexander Musman92bdaab2015-03-12 13:37:50 +00002224 }
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002225
2226 EmitBranch(CondBlock);
2227 LoopStack.pop();
2228 // Emit the fall-through block.
2229 EmitBlock(LoopExit.getBlock());
2230
2231 // Tell the runtime we are done.
Alexey Bataev957d8562016-11-17 15:12:05 +00002232 auto &&CodeGen = [DynamicOrOrdered, &S](CodeGenFunction &CGF) {
2233 if (!DynamicOrOrdered)
Stephen Kelly1c301dc2018-08-09 21:09:38 +00002234 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
Alexey Bataevf43f7142017-09-06 16:17:35 +00002235 S.getDirectiveKind());
Alexey Bataev957d8562016-11-17 15:12:05 +00002236 };
2237 OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002238}
2239
2240void CodeGenFunction::EmitOMPForOuterLoop(
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002241 const OpenMPScheduleTy &ScheduleKind, bool IsMonotonic,
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002242 const OMPLoopDirective &S, OMPPrivateScope &LoopScope, bool Ordered,
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002243 const OMPLoopArguments &LoopArgs,
2244 const CodeGenDispatchBoundsTy &CGDispatchBounds) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002245 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002246
2247 // Dynamic scheduling of the outer loop (dynamic, guided, auto, runtime).
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002248 const bool DynamicOrOrdered =
2249 Ordered || RT.isDynamic(ScheduleKind.Schedule);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002250
2251 assert((Ordered ||
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002252 !RT.isStaticNonchunked(ScheduleKind.Schedule,
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002253 LoopArgs.Chunk != nullptr)) &&
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002254 "static non-chunked schedule does not need outer loop");
2255
2256 // Emit outer loop.
2257 //
2258 // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
2259 // When schedule(dynamic,chunk_size) is specified, the iterations are
2260 // distributed to threads in the team in chunks as the threads request them.
2261 // Each thread executes a chunk of iterations, then requests another chunk,
2262 // until no chunks remain to be distributed. Each chunk contains chunk_size
2263 // iterations, except for the last chunk to be distributed, which may have
2264 // fewer iterations. When no chunk_size is specified, it defaults to 1.
2265 //
2266 // When schedule(guided,chunk_size) is specified, the iterations are assigned
2267 // to threads in the team in chunks as the executing threads request them.
2268 // Each thread executes a chunk of iterations, then requests another chunk,
2269 // until no chunks remain to be assigned. For a chunk_size of 1, the size of
2270 // each chunk is proportional to the number of unassigned iterations divided
2271 // by the number of threads in the team, decreasing to 1. For a chunk_size
2272 // with value k (greater than 1), the size of each chunk is determined in the
2273 // same way, with the restriction that the chunks do not contain fewer than k
2274 // iterations (except for the last chunk to be assigned, which may have fewer
2275 // than k iterations).
2276 //
2277 // When schedule(auto) is specified, the decision regarding scheduling is
2278 // delegated to the compiler and/or runtime system. The programmer gives the
2279 // implementation the freedom to choose any possible mapping of iterations to
2280 // threads in the team.
2281 //
2282 // When schedule(runtime) is specified, the decision regarding scheduling is
2283 // deferred until run time, and the schedule and chunk size are taken from the
2284 // run-sched-var ICV. If the ICV is set to auto, the schedule is
2285 // implementation defined
2286 //
2287 // while(__kmpc_dispatch_next(&LB, &UB)) {
2288 // idx = LB;
2289 // while (idx <= UB) { BODY; ++idx;
2290 // __kmpc_dispatch_fini_(4|8)[u](); // For ordered loops only.
2291 // } // inner loop
2292 // }
2293 //
2294 // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
2295 // When schedule(static, chunk_size) is specified, iterations are divided into
2296 // chunks of size chunk_size, and the chunks are assigned to the threads in
2297 // the team in a round-robin fashion in the order of the thread number.
2298 //
2299 // while(UB = min(UB, GlobalUB), idx = LB, idx < UB) {
2300 // while (idx <= UB) { BODY; ++idx; } // inner loop
2301 // LB = LB + ST;
2302 // UB = UB + ST;
2303 // }
2304 //
2305
2306 const Expr *IVExpr = S.getIterationVariable();
2307 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
2308 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
2309
2310 if (DynamicOrOrdered) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002311 const std::pair<llvm::Value *, llvm::Value *> DispatchBounds =
2312 CGDispatchBounds(*this, S, LoopArgs.LB, LoopArgs.UB);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002313 llvm::Value *LBVal = DispatchBounds.first;
2314 llvm::Value *UBVal = DispatchBounds.second;
2315 CGOpenMPRuntime::DispatchRTInput DipatchRTInputValues = {LBVal, UBVal,
2316 LoopArgs.Chunk};
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002317 RT.emitForDispatchInit(*this, S.getBeginLoc(), ScheduleKind, IVSize,
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002318 IVSigned, Ordered, DipatchRTInputValues);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002319 } else {
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00002320 CGOpenMPRuntime::StaticRTInput StaticInit(
2321 IVSize, IVSigned, Ordered, LoopArgs.IL, LoopArgs.LB, LoopArgs.UB,
2322 LoopArgs.ST, LoopArgs.Chunk);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002323 RT.emitForStaticInit(*this, S.getBeginLoc(), S.getDirectiveKind(),
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00002324 ScheduleKind, StaticInit);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002325 }
2326
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002327 auto &&CodeGenOrdered = [Ordered](CodeGenFunction &CGF, SourceLocation Loc,
2328 const unsigned IVSize,
2329 const bool IVSigned) {
2330 if (Ordered) {
2331 CGF.CGM.getOpenMPRuntime().emitForOrderedIterationEnd(CGF, Loc, IVSize,
2332 IVSigned);
2333 }
2334 };
2335
2336 OMPLoopArguments OuterLoopArgs(LoopArgs.LB, LoopArgs.UB, LoopArgs.ST,
2337 LoopArgs.IL, LoopArgs.Chunk, LoopArgs.EUB);
2338 OuterLoopArgs.IncExpr = S.getInc();
2339 OuterLoopArgs.Init = S.getInit();
2340 OuterLoopArgs.Cond = S.getCond();
2341 OuterLoopArgs.NextLB = S.getNextLowerBound();
2342 OuterLoopArgs.NextUB = S.getNextUpperBound();
2343 EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
2344 emitOMPLoopBodyWithStopPoint, CodeGenOrdered);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002345}
2346
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002347static void emitEmptyOrdered(CodeGenFunction &, SourceLocation Loc,
2348 const unsigned IVSize, const bool IVSigned) {}
2349
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002350void CodeGenFunction::EmitOMPDistributeOuterLoop(
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002351 OpenMPDistScheduleClauseKind ScheduleKind, const OMPLoopDirective &S,
2352 OMPPrivateScope &LoopScope, const OMPLoopArguments &LoopArgs,
2353 const CodeGenLoopTy &CodeGenLoopContent) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002354
Alexey Bataevddf3db92018-04-13 17:31:06 +00002355 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002356
2357 // Emit outer loop.
2358 // Same behavior as a OMPForOuterLoop, except that schedule cannot be
2359 // dynamic
2360 //
2361
2362 const Expr *IVExpr = S.getIterationVariable();
2363 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
2364 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
2365
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00002366 CGOpenMPRuntime::StaticRTInput StaticInit(
2367 IVSize, IVSigned, /* Ordered = */ false, LoopArgs.IL, LoopArgs.LB,
2368 LoopArgs.UB, LoopArgs.ST, LoopArgs.Chunk);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002369 RT.emitDistributeStaticInit(*this, S.getBeginLoc(), ScheduleKind, StaticInit);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00002370
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002371 // for combined 'distribute' and 'for' the increment expression of distribute
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00002372 // is stored in DistInc. For 'distribute' alone, it is in Inc.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002373 Expr *IncExpr;
2374 if (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind()))
2375 IncExpr = S.getDistInc();
2376 else
2377 IncExpr = S.getInc();
2378
2379 // this routine is shared by 'omp distribute parallel for' and
2380 // 'omp distribute': select the right EUB expression depending on the
2381 // directive
2382 OMPLoopArguments OuterLoopArgs;
2383 OuterLoopArgs.LB = LoopArgs.LB;
2384 OuterLoopArgs.UB = LoopArgs.UB;
2385 OuterLoopArgs.ST = LoopArgs.ST;
2386 OuterLoopArgs.IL = LoopArgs.IL;
2387 OuterLoopArgs.Chunk = LoopArgs.Chunk;
2388 OuterLoopArgs.EUB = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
2389 ? S.getCombinedEnsureUpperBound()
2390 : S.getEnsureUpperBound();
2391 OuterLoopArgs.IncExpr = IncExpr;
2392 OuterLoopArgs.Init = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
2393 ? S.getCombinedInit()
2394 : S.getInit();
2395 OuterLoopArgs.Cond = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
2396 ? S.getCombinedCond()
2397 : S.getCond();
2398 OuterLoopArgs.NextLB = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
2399 ? S.getCombinedNextLowerBound()
2400 : S.getNextLowerBound();
2401 OuterLoopArgs.NextUB = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
2402 ? S.getCombinedNextUpperBound()
2403 : S.getNextUpperBound();
2404
2405 EmitOMPOuterLoop(/* DynamicOrOrdered = */ false, /* IsMonotonic = */ false, S,
2406 LoopScope, OuterLoopArgs, CodeGenLoopContent,
2407 emitEmptyOrdered);
2408}
2409
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002410static std::pair<LValue, LValue>
2411emitDistributeParallelForInnerBounds(CodeGenFunction &CGF,
2412 const OMPExecutableDirective &S) {
2413 const OMPLoopDirective &LS = cast<OMPLoopDirective>(S);
2414 LValue LB =
2415 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getLowerBoundVariable()));
2416 LValue UB =
2417 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getUpperBoundVariable()));
2418
2419 // When composing 'distribute' with 'for' (e.g. as in 'distribute
2420 // parallel for') we need to use the 'distribute'
2421 // chunk lower and upper bounds rather than the whole loop iteration
2422 // space. These are parameters to the outlined function for 'parallel'
2423 // and we copy the bounds of the previous schedule into the
2424 // the current ones.
2425 LValue PrevLB = CGF.EmitLValue(LS.getPrevLowerBoundVariable());
2426 LValue PrevUB = CGF.EmitLValue(LS.getPrevUpperBoundVariable());
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00002427 llvm::Value *PrevLBVal = CGF.EmitLoadOfScalar(
2428 PrevLB, LS.getPrevLowerBoundVariable()->getExprLoc());
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002429 PrevLBVal = CGF.EmitScalarConversion(
2430 PrevLBVal, LS.getPrevLowerBoundVariable()->getType(),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00002431 LS.getIterationVariable()->getType(),
2432 LS.getPrevLowerBoundVariable()->getExprLoc());
2433 llvm::Value *PrevUBVal = CGF.EmitLoadOfScalar(
2434 PrevUB, LS.getPrevUpperBoundVariable()->getExprLoc());
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002435 PrevUBVal = CGF.EmitScalarConversion(
2436 PrevUBVal, LS.getPrevUpperBoundVariable()->getType(),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00002437 LS.getIterationVariable()->getType(),
2438 LS.getPrevUpperBoundVariable()->getExprLoc());
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002439
2440 CGF.EmitStoreOfScalar(PrevLBVal, LB);
2441 CGF.EmitStoreOfScalar(PrevUBVal, UB);
2442
2443 return {LB, UB};
2444}
2445
2446/// if the 'for' loop has a dispatch schedule (e.g. dynamic, guided) then
2447/// we need to use the LB and UB expressions generated by the worksharing
2448/// code generation support, whereas in non combined situations we would
2449/// just emit 0 and the LastIteration expression
2450/// This function is necessary due to the difference of the LB and UB
2451/// types for the RT emission routines for 'for_static_init' and
2452/// 'for_dispatch_init'
2453static std::pair<llvm::Value *, llvm::Value *>
2454emitDistributeParallelForDispatchBounds(CodeGenFunction &CGF,
2455 const OMPExecutableDirective &S,
2456 Address LB, Address UB) {
2457 const OMPLoopDirective &LS = cast<OMPLoopDirective>(S);
2458 const Expr *IVExpr = LS.getIterationVariable();
2459 // when implementing a dynamic schedule for a 'for' combined with a
2460 // 'distribute' (e.g. 'distribute parallel for'), the 'for' loop
2461 // is not normalized as each team only executes its own assigned
2462 // distribute chunk
2463 QualType IteratorTy = IVExpr->getType();
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00002464 llvm::Value *LBVal =
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002465 CGF.EmitLoadOfScalar(LB, /*Volatile=*/false, IteratorTy, S.getBeginLoc());
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00002466 llvm::Value *UBVal =
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002467 CGF.EmitLoadOfScalar(UB, /*Volatile=*/false, IteratorTy, S.getBeginLoc());
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002468 return {LBVal, UBVal};
Hans Wennborged129ae2017-04-27 17:02:25 +00002469}
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002470
2471static void emitDistributeParallelForDistributeInnerBoundParams(
2472 CodeGenFunction &CGF, const OMPExecutableDirective &S,
2473 llvm::SmallVectorImpl<llvm::Value *> &CapturedVars) {
2474 const auto &Dir = cast<OMPLoopDirective>(S);
2475 LValue LB =
2476 CGF.EmitLValue(cast<DeclRefExpr>(Dir.getCombinedLowerBoundVariable()));
Akira Hatanakaf139ae32019-12-03 15:17:01 -08002477 llvm::Value *LBCast =
2478 CGF.Builder.CreateIntCast(CGF.Builder.CreateLoad(LB.getAddress(CGF)),
2479 CGF.SizeTy, /*isSigned=*/false);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002480 CapturedVars.push_back(LBCast);
2481 LValue UB =
2482 CGF.EmitLValue(cast<DeclRefExpr>(Dir.getCombinedUpperBoundVariable()));
2483
Akira Hatanakaf139ae32019-12-03 15:17:01 -08002484 llvm::Value *UBCast =
2485 CGF.Builder.CreateIntCast(CGF.Builder.CreateLoad(UB.getAddress(CGF)),
2486 CGF.SizeTy, /*isSigned=*/false);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002487 CapturedVars.push_back(UBCast);
Hans Wennborged129ae2017-04-27 17:02:25 +00002488}
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002489
2490static void
2491emitInnerParallelForWhenCombined(CodeGenFunction &CGF,
2492 const OMPLoopDirective &S,
2493 CodeGenFunction::JumpDest LoopExit) {
2494 auto &&CGInlinedWorksharingLoop = [&S](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00002495 PrePostActionTy &Action) {
2496 Action.Enter(CGF);
Alexey Bataevdcb4b8fb2017-11-22 20:19:50 +00002497 bool HasCancel = false;
2498 if (!isOpenMPSimdDirective(S.getDirectiveKind())) {
2499 if (const auto *D = dyn_cast<OMPTeamsDistributeParallelForDirective>(&S))
2500 HasCancel = D->hasCancel();
2501 else if (const auto *D = dyn_cast<OMPDistributeParallelForDirective>(&S))
2502 HasCancel = D->hasCancel();
Alexey Bataev16e79882017-11-22 21:12:03 +00002503 else if (const auto *D =
2504 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&S))
2505 HasCancel = D->hasCancel();
Alexey Bataevdcb4b8fb2017-11-22 20:19:50 +00002506 }
2507 CodeGenFunction::OMPCancelStackRAII CancelRegion(CGF, S.getDirectiveKind(),
2508 HasCancel);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002509 CGF.EmitOMPWorksharingLoop(S, S.getPrevEnsureUpperBound(),
2510 emitDistributeParallelForInnerBounds,
2511 emitDistributeParallelForDispatchBounds);
2512 };
2513
2514 emitCommonOMPParallelDirective(
Alexey Bataevdcb4b8fb2017-11-22 20:19:50 +00002515 CGF, S,
2516 isOpenMPSimdDirective(S.getDirectiveKind()) ? OMPD_for_simd : OMPD_for,
2517 CGInlinedWorksharingLoop,
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002518 emitDistributeParallelForDistributeInnerBoundParams);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002519}
2520
Carlo Bertolli9925f152016-06-27 14:55:37 +00002521void CodeGenFunction::EmitOMPDistributeParallelForDirective(
2522 const OMPDistributeParallelForDirective &S) {
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002523 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
2524 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
2525 S.getDistInc());
2526 };
Alexey Bataev475a7442018-01-12 19:39:11 +00002527 OMPLexicalScope Scope(*this, S, OMPD_parallel);
Alexey Bataev10a54312017-11-27 16:54:08 +00002528 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen);
Carlo Bertolli9925f152016-06-27 14:55:37 +00002529}
2530
Kelvin Li4a39add2016-07-05 05:00:15 +00002531void CodeGenFunction::EmitOMPDistributeParallelForSimdDirective(
2532 const OMPDistributeParallelForSimdDirective &S) {
Alexey Bataev0b49f9e2017-11-27 19:38:58 +00002533 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
2534 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
2535 S.getDistInc());
2536 };
Alexey Bataev475a7442018-01-12 19:39:11 +00002537 OMPLexicalScope Scope(*this, S, OMPD_parallel);
Alexey Bataev0b49f9e2017-11-27 19:38:58 +00002538 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen);
Kelvin Li4a39add2016-07-05 05:00:15 +00002539}
Kelvin Li787f3fc2016-07-06 04:45:38 +00002540
2541void CodeGenFunction::EmitOMPDistributeSimdDirective(
2542 const OMPDistributeSimdDirective &S) {
Alexey Bataev617db5f2017-12-04 15:38:33 +00002543 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
2544 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
2545 };
Alexey Bataev475a7442018-01-12 19:39:11 +00002546 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataev617db5f2017-12-04 15:38:33 +00002547 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
Kelvin Li787f3fc2016-07-06 04:45:38 +00002548}
2549
Alexey Bataevf8365372017-11-17 17:57:25 +00002550void CodeGenFunction::EmitOMPTargetSimdDeviceFunction(
2551 CodeGenModule &CGM, StringRef ParentName, const OMPTargetSimdDirective &S) {
2552 // Emit SPMD target parallel for region as a standalone region.
2553 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
2554 emitOMPSimdRegion(CGF, S, Action);
2555 };
2556 llvm::Function *Fn;
2557 llvm::Constant *Addr;
2558 // Emit target region as a standalone region.
2559 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
2560 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
2561 assert(Fn && Addr && "Target device function emission failed.");
2562}
2563
Kelvin Li986330c2016-07-20 22:57:10 +00002564void CodeGenFunction::EmitOMPTargetSimdDirective(
2565 const OMPTargetSimdDirective &S) {
Alexey Bataevf8365372017-11-17 17:57:25 +00002566 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
2567 emitOMPSimdRegion(CGF, S, Action);
2568 };
2569 emitCommonOMPTargetDirective(*this, S, CodeGen);
Kelvin Li986330c2016-07-20 22:57:10 +00002570}
2571
Alexey Bataeva6f2a142015-12-31 06:52:34 +00002572namespace {
2573 struct ScheduleKindModifiersTy {
2574 OpenMPScheduleClauseKind Kind;
2575 OpenMPScheduleClauseModifier M1;
2576 OpenMPScheduleClauseModifier M2;
2577 ScheduleKindModifiersTy(OpenMPScheduleClauseKind Kind,
2578 OpenMPScheduleClauseModifier M1,
2579 OpenMPScheduleClauseModifier M2)
2580 : Kind(Kind), M1(M1), M2(M2) {}
2581 };
2582} // namespace
2583
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002584bool CodeGenFunction::EmitOMPWorksharingLoop(
2585 const OMPLoopDirective &S, Expr *EUB,
2586 const CodeGenLoopBoundsTy &CodeGenLoopBounds,
2587 const CodeGenDispatchBoundsTy &CGDispatchBounds) {
Alexander Musmanc6388682014-12-15 07:07:06 +00002588 // Emit the loop iteration variable.
Alexey Bataevddf3db92018-04-13 17:31:06 +00002589 const auto *IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
2590 const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl());
Alexander Musmanc6388682014-12-15 07:07:06 +00002591 EmitVarDecl(*IVDecl);
2592
2593 // Emit the iterations count variable.
2594 // If it is not a variable, Sema decided to calculate iterations count on each
2595 // iteration (e.g., it is foldable into a constant).
Alexey Bataevddf3db92018-04-13 17:31:06 +00002596 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
Alexander Musmanc6388682014-12-15 07:07:06 +00002597 EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
2598 // Emit calculation of the iterations count.
2599 EmitIgnoredExpr(S.getCalcLastIteration());
2600 }
2601
Alexey Bataevddf3db92018-04-13 17:31:06 +00002602 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
Alexander Musmanc6388682014-12-15 07:07:06 +00002603
Alexey Bataev38e89532015-04-16 04:54:05 +00002604 bool HasLastprivateClause;
Alexander Musmanc6388682014-12-15 07:07:06 +00002605 // Check pre-condition.
2606 {
Alexey Bataev5a3af132016-03-29 08:58:54 +00002607 OMPLoopScope PreInitScope(*this, S);
Alexander Musmanc6388682014-12-15 07:07:06 +00002608 // Skip the entire loop if we don't meet the precondition.
Alexey Bataev62dbb972015-04-22 11:59:37 +00002609 // If the condition constant folds and can be elided, avoid emitting the
2610 // whole loop.
2611 bool CondConstant;
2612 llvm::BasicBlock *ContBlock = nullptr;
2613 if (ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
2614 if (!CondConstant)
2615 return false;
2616 } else {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002617 llvm::BasicBlock *ThenBlock = createBasicBlock("omp.precond.then");
Alexey Bataev62dbb972015-04-22 11:59:37 +00002618 ContBlock = createBasicBlock("omp.precond.end");
2619 emitPreCond(*this, S, S.getPreCond(), ThenBlock, ContBlock,
Justin Bogner66242d62015-04-23 23:06:47 +00002620 getProfileCount(&S));
Alexey Bataev62dbb972015-04-22 11:59:37 +00002621 EmitBlock(ThenBlock);
Justin Bogner66242d62015-04-23 23:06:47 +00002622 incrementProfileCounter(&S);
Alexey Bataev62dbb972015-04-22 11:59:37 +00002623 }
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00002624
Alexey Bataevea33dee2018-02-15 23:39:43 +00002625 RunCleanupsScope DoacrossCleanupScope(*this);
Alexey Bataev8b427062016-05-25 12:36:08 +00002626 bool Ordered = false;
Alexey Bataevddf3db92018-04-13 17:31:06 +00002627 if (const auto *OrderedClause = S.getSingleClause<OMPOrderedClause>()) {
Alexey Bataev8b427062016-05-25 12:36:08 +00002628 if (OrderedClause->getNumForLoops())
Alexey Bataevf138fda2018-08-13 19:04:24 +00002629 RT.emitDoacrossInit(*this, S, OrderedClause->getLoopNumIterations());
Alexey Bataev8b427062016-05-25 12:36:08 +00002630 else
2631 Ordered = true;
2632 }
2633
Alexey Bataev5dff95c2016-04-22 03:56:56 +00002634 llvm::DenseSet<const Expr *> EmittedFinals;
Alexey Bataev58e5bdb2015-06-18 04:45:29 +00002635 emitAlignedClause(*this, S);
Alexey Bataev8c3edfe2017-08-16 15:58:46 +00002636 bool HasLinears = EmitOMPLinearClauseInit(S);
Alexey Bataevef549a82016-03-09 09:49:09 +00002637 // Emit helper vars inits.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002638
2639 std::pair<LValue, LValue> Bounds = CodeGenLoopBounds(*this, S);
2640 LValue LB = Bounds.first;
2641 LValue UB = Bounds.second;
Alexey Bataevef549a82016-03-09 09:49:09 +00002642 LValue ST =
2643 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getStrideVariable()));
2644 LValue IL =
2645 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable()));
2646
Alexander Musmanc6388682014-12-15 07:07:06 +00002647 // Emit 'then' code.
2648 {
Alexander Musmanc6388682014-12-15 07:07:06 +00002649 OMPPrivateScope LoopScope(*this);
Alexey Bataev8c3edfe2017-08-16 15:58:46 +00002650 if (EmitOMPFirstprivateClause(S, LoopScope) || HasLinears) {
Alexey Bataev69c62a92015-04-15 04:52:20 +00002651 // Emit implicit barrier to synchronize threads and avoid data races on
Alexey Bataevcd8b6a22016-02-15 08:07:17 +00002652 // initialization of firstprivate variables and post-update of
2653 // lastprivate variables.
Alexey Bataev25e5b442015-09-15 12:52:43 +00002654 CGM.getOpenMPRuntime().emitBarrierCall(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002655 *this, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
Alexey Bataev25e5b442015-09-15 12:52:43 +00002656 /*ForceSimpleCall=*/true);
Alexey Bataev69c62a92015-04-15 04:52:20 +00002657 }
Alexey Bataev50a64582015-04-22 12:24:45 +00002658 EmitOMPPrivateClause(S, LoopScope);
Alexey Bataeva58da1a2019-12-27 09:44:43 -05002659 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(
2660 *this, S, EmitLValue(S.getIterationVariable()));
Alexey Bataev38e89532015-04-16 04:54:05 +00002661 HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope);
Alexey Bataev7ebe5fd2015-04-22 13:43:03 +00002662 EmitOMPReductionClauseInit(S, LoopScope);
Alexey Bataev5dff95c2016-04-22 03:56:56 +00002663 EmitOMPPrivateLoopCounters(S, LoopScope);
2664 EmitOMPLinearClause(S, LoopScope);
Alexander Musman7931b982015-03-16 07:14:41 +00002665 (void)LoopScope.Privatize();
Alexey Bataev60705422018-10-30 15:50:12 +00002666 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
2667 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*this, S);
Alexander Musmanc6388682014-12-15 07:07:06 +00002668
2669 // Detect the loop schedule kind and chunk.
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00002670 const Expr *ChunkExpr = nullptr;
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002671 OpenMPScheduleTy ScheduleKind;
Alexey Bataevddf3db92018-04-13 17:31:06 +00002672 if (const auto *C = S.getSingleClause<OMPScheduleClause>()) {
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002673 ScheduleKind.Schedule = C->getScheduleKind();
2674 ScheduleKind.M1 = C->getFirstScheduleModifier();
2675 ScheduleKind.M2 = C->getSecondScheduleModifier();
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00002676 ChunkExpr = C->getChunkSize();
Gheorghe-Teodor Bercea8233af92018-09-27 20:29:00 +00002677 } else {
2678 // Default behaviour for schedule clause.
2679 CGM.getOpenMPRuntime().getDefaultScheduleAndChunk(
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00002680 *this, S, ScheduleKind.Schedule, ChunkExpr);
2681 }
2682 bool HasChunkSizeOne = false;
2683 llvm::Value *Chunk = nullptr;
2684 if (ChunkExpr) {
2685 Chunk = EmitScalarExpr(ChunkExpr);
2686 Chunk = EmitScalarConversion(Chunk, ChunkExpr->getType(),
2687 S.getIterationVariable()->getType(),
2688 S.getBeginLoc());
Fangrui Song407659a2018-11-30 23:41:18 +00002689 Expr::EvalResult Result;
2690 if (ChunkExpr->EvaluateAsInt(Result, getContext())) {
2691 llvm::APSInt EvaluatedChunk = Result.Val.getInt();
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00002692 HasChunkSizeOne = (EvaluatedChunk.getLimitedValue() == 1);
Fangrui Song407659a2018-11-30 23:41:18 +00002693 }
Alexey Bataev3392d762016-02-16 11:18:12 +00002694 }
Alexander Musmanc6388682014-12-15 07:07:06 +00002695 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
2696 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
Alexey Bataeva6f2a142015-12-31 06:52:34 +00002697 // OpenMP 4.5, 2.7.1 Loop Construct, Description.
2698 // If the static schedule kind is specified or if the ordered clause is
2699 // specified, and if no monotonic modifier is specified, the effect will
2700 // be as if the monotonic modifier was specified.
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00002701 bool StaticChunkedOne = RT.isStaticChunked(ScheduleKind.Schedule,
2702 /* Chunked */ Chunk != nullptr) && HasChunkSizeOne &&
2703 isOpenMPLoopBoundSharingDirective(S.getDirectiveKind());
2704 if ((RT.isStaticNonchunked(ScheduleKind.Schedule,
2705 /* Chunked */ Chunk != nullptr) ||
2706 StaticChunkedOne) &&
Alexey Bataevd7589ffe2015-05-20 13:12:48 +00002707 !Ordered) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002708 JumpDest LoopExit =
Alexey Bataeva6f2a142015-12-31 06:52:34 +00002709 getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit"));
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002710 emitCommonSimdLoop(
2711 *this, S,
2712 [&S](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataeva7815212020-02-03 12:08:16 -05002713 if (isOpenMPSimdDirective(S.getDirectiveKind())) {
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002714 CGF.EmitOMPSimdInit(S, /*IsMonotonic=*/true);
Alexey Bataeva7815212020-02-03 12:08:16 -05002715 } else if (const auto *C = S.getSingleClause<OMPOrderClause>()) {
2716 if (C->getKind() == OMPC_ORDER_concurrent)
2717 CGF.LoopStack.setParallel(/*Enable=*/true);
2718 }
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00002719 },
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002720 [IVSize, IVSigned, Ordered, IL, LB, UB, ST, StaticChunkedOne, Chunk,
2721 &S, ScheduleKind, LoopExit,
2722 &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
2723 // OpenMP [2.7.1, Loop Construct, Description, table 2-1]
2724 // When no chunk_size is specified, the iteration space is divided
2725 // into chunks that are approximately equal in size, and at most
2726 // one chunk is distributed to each thread. Note that the size of
2727 // the chunks is unspecified in this case.
2728 CGOpenMPRuntime::StaticRTInput StaticInit(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08002729 IVSize, IVSigned, Ordered, IL.getAddress(CGF),
2730 LB.getAddress(CGF), UB.getAddress(CGF), ST.getAddress(CGF),
Alexey Bataev103f3c9e2019-11-20 15:59:03 -05002731 StaticChunkedOne ? Chunk : nullptr);
2732 CGF.CGM.getOpenMPRuntime().emitForStaticInit(
2733 CGF, S.getBeginLoc(), S.getDirectiveKind(), ScheduleKind,
2734 StaticInit);
2735 // UB = min(UB, GlobalUB);
2736 if (!StaticChunkedOne)
2737 CGF.EmitIgnoredExpr(S.getEnsureUpperBound());
2738 // IV = LB;
2739 CGF.EmitIgnoredExpr(S.getInit());
2740 // For unchunked static schedule generate:
2741 //
2742 // while (idx <= UB) {
2743 // BODY;
2744 // ++idx;
2745 // }
2746 //
2747 // For static schedule with chunk one:
2748 //
2749 // while (IV <= PrevUB) {
2750 // BODY;
2751 // IV += ST;
2752 // }
2753 CGF.EmitOMPInnerLoop(
2754 S, LoopScope.requiresCleanups(),
2755 StaticChunkedOne ? S.getCombinedParForInDistCond()
2756 : S.getCond(),
2757 StaticChunkedOne ? S.getDistInc() : S.getInc(),
2758 [&S, LoopExit](CodeGenFunction &CGF) {
2759 CGF.EmitOMPLoopBody(S, LoopExit);
2760 CGF.EmitStopPoint(&S);
2761 },
2762 [](CodeGenFunction &) {});
2763 });
Alexey Bataev0f34da12015-07-02 04:17:07 +00002764 EmitBlock(LoopExit.getBlock());
Alexander Musmanc6388682014-12-15 07:07:06 +00002765 // Tell the runtime we are done.
Alexey Bataev957d8562016-11-17 15:12:05 +00002766 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
Stephen Kelly1c301dc2018-08-09 21:09:38 +00002767 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
Alexey Bataevf43f7142017-09-06 16:17:35 +00002768 S.getDirectiveKind());
Alexey Bataev957d8562016-11-17 15:12:05 +00002769 };
2770 OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002771 } else {
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002772 const bool IsMonotonic =
2773 Ordered || ScheduleKind.Schedule == OMPC_SCHEDULE_static ||
2774 ScheduleKind.Schedule == OMPC_SCHEDULE_unknown ||
2775 ScheduleKind.M1 == OMPC_SCHEDULE_MODIFIER_monotonic ||
2776 ScheduleKind.M2 == OMPC_SCHEDULE_MODIFIER_monotonic;
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002777 // Emit the outer loop, which requests its work chunk [LB..UB] from
2778 // runtime and runs the inner loop to process it.
Akira Hatanakaf139ae32019-12-03 15:17:01 -08002779 const OMPLoopArguments LoopArguments(
2780 LB.getAddress(*this), UB.getAddress(*this), ST.getAddress(*this),
2781 IL.getAddress(*this), Chunk, EUB);
Alexey Bataeva6f2a142015-12-31 06:52:34 +00002782 EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002783 LoopArguments, CGDispatchBounds);
Alexander Musmandf7a8e22015-01-22 08:49:35 +00002784 }
Alexey Bataev5dff95c2016-04-22 03:56:56 +00002785 if (isOpenMPSimdDirective(S.getDirectiveKind())) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002786 EmitOMPSimdFinal(S, [IL, &S](CodeGenFunction &CGF) {
2787 return CGF.Builder.CreateIsNotNull(
2788 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
2789 });
Alexey Bataev5dff95c2016-04-22 03:56:56 +00002790 }
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00002791 EmitOMPReductionClauseFinal(
2792 S, /*ReductionKind=*/isOpenMPSimdDirective(S.getDirectiveKind())
2793 ? /*Parallel and Simd*/ OMPD_parallel_for_simd
2794 : /*Parallel only*/ OMPD_parallel);
Alexey Bataev61205072016-03-02 04:57:40 +00002795 // Emit post-update of the reduction variables if IsLastIter != 0.
2796 emitPostUpdateForReductionClause(
Alexey Bataevddf3db92018-04-13 17:31:06 +00002797 *this, S, [IL, &S](CodeGenFunction &CGF) {
Alexey Bataev61205072016-03-02 04:57:40 +00002798 return CGF.Builder.CreateIsNotNull(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002799 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
Alexey Bataev61205072016-03-02 04:57:40 +00002800 });
Alexey Bataev38e89532015-04-16 04:54:05 +00002801 // Emit final copy of the lastprivate variables if IsLastIter != 0.
2802 if (HasLastprivateClause)
2803 EmitOMPLastprivateClauseFinal(
Alexey Bataev5dff95c2016-04-22 03:56:56 +00002804 S, isOpenMPSimdDirective(S.getDirectiveKind()),
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002805 Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getBeginLoc())));
Alexander Musmanc6388682014-12-15 07:07:06 +00002806 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00002807 EmitOMPLinearClauseFinal(S, [IL, &S](CodeGenFunction &CGF) {
Alexey Bataevef549a82016-03-09 09:49:09 +00002808 return CGF.Builder.CreateIsNotNull(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002809 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
Alexey Bataevef549a82016-03-09 09:49:09 +00002810 });
Alexey Bataevea33dee2018-02-15 23:39:43 +00002811 DoacrossCleanupScope.ForceCleanup();
Alexander Musmanc6388682014-12-15 07:07:06 +00002812 // We're now done with the loop, so jump to the continuation block.
Alexey Bataev62dbb972015-04-22 11:59:37 +00002813 if (ContBlock) {
2814 EmitBranch(ContBlock);
Alexey Bataevddf3db92018-04-13 17:31:06 +00002815 EmitBlock(ContBlock, /*IsFinished=*/true);
Alexey Bataev62dbb972015-04-22 11:59:37 +00002816 }
Alexander Musmanc6388682014-12-15 07:07:06 +00002817 }
Alexey Bataev38e89532015-04-16 04:54:05 +00002818 return HasLastprivateClause;
Alexander Musmanc6388682014-12-15 07:07:06 +00002819}
2820
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002821/// The following two functions generate expressions for the loop lower
2822/// and upper bounds in case of static and dynamic (dispatch) schedule
2823/// of the associated 'for' or 'distribute' loop.
2824static std::pair<LValue, LValue>
2825emitForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002826 const auto &LS = cast<OMPLoopDirective>(S);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002827 LValue LB =
2828 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getLowerBoundVariable()));
2829 LValue UB =
2830 EmitOMPHelperVar(CGF, cast<DeclRefExpr>(LS.getUpperBoundVariable()));
2831 return {LB, UB};
2832}
2833
2834/// When dealing with dispatch schedules (e.g. dynamic, guided) we do not
2835/// consider the lower and upper bound expressions generated by the
2836/// worksharing loop support, but we use 0 and the iteration space size as
2837/// constants
2838static std::pair<llvm::Value *, llvm::Value *>
2839emitDispatchForLoopBounds(CodeGenFunction &CGF, const OMPExecutableDirective &S,
2840 Address LB, Address UB) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002841 const auto &LS = cast<OMPLoopDirective>(S);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002842 const Expr *IVExpr = LS.getIterationVariable();
2843 const unsigned IVSize = CGF.getContext().getTypeSize(IVExpr->getType());
2844 llvm::Value *LBVal = CGF.Builder.getIntN(IVSize, 0);
2845 llvm::Value *UBVal = CGF.EmitScalarExpr(LS.getLastIteration());
2846 return {LBVal, UBVal};
2847}
2848
Alexander Musmanc6388682014-12-15 07:07:06 +00002849void CodeGenFunction::EmitOMPForDirective(const OMPForDirective &S) {
Alexey Bataev38e89532015-04-16 04:54:05 +00002850 bool HasLastprivates = false;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002851 auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
2852 PrePostActionTy &) {
Alexey Bataev957d8562016-11-17 15:12:05 +00002853 OMPCancelStackRAII CancelRegion(CGF, OMPD_for, S.hasCancel());
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002854 HasLastprivates = CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(),
2855 emitForLoopBounds,
2856 emitDispatchForLoopBounds);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002857 };
Alexey Bataev3392d762016-02-16 11:18:12 +00002858 {
Alexey Bataev46978742020-01-30 10:46:11 -05002859 auto LPCRegion =
2860 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev475a7442018-01-12 19:39:11 +00002861 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataev3392d762016-02-16 11:18:12 +00002862 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_for, CodeGen,
2863 S.hasCancel());
2864 }
Alexander Musmanc6388682014-12-15 07:07:06 +00002865
2866 // Emit an implicit barrier at the end.
Alexey Bataevddf3db92018-04-13 17:31:06 +00002867 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002868 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_for);
Alexey Bataev46978742020-01-30 10:46:11 -05002869 // Check for outer lastprivate conditional update.
2870 checkForLastprivateConditionalUpdate(*this, S);
Alexey Bataevf29276e2014-06-18 04:14:57 +00002871}
Alexey Bataevd3f8dd22014-06-25 11:44:49 +00002872
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00002873void CodeGenFunction::EmitOMPForSimdDirective(const OMPForSimdDirective &S) {
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00002874 bool HasLastprivates = false;
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002875 auto &&CodeGen = [&S, &HasLastprivates](CodeGenFunction &CGF,
2876 PrePostActionTy &) {
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00002877 HasLastprivates = CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(),
2878 emitForLoopBounds,
2879 emitDispatchForLoopBounds);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00002880 };
Alexey Bataev3392d762016-02-16 11:18:12 +00002881 {
Alexey Bataev46978742020-01-30 10:46:11 -05002882 auto LPCRegion =
2883 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev475a7442018-01-12 19:39:11 +00002884 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataev3392d762016-02-16 11:18:12 +00002885 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_simd, CodeGen);
2886 }
Alexey Bataevcbdcbb72015-06-17 07:45:51 +00002887
2888 // Emit an implicit barrier at the end.
Alexey Bataevddf3db92018-04-13 17:31:06 +00002889 if (!S.getSingleClause<OMPNowaitClause>() || HasLastprivates)
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002890 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_for);
Alexey Bataev46978742020-01-30 10:46:11 -05002891 // Check for outer lastprivate conditional update.
2892 checkForLastprivateConditionalUpdate(*this, S);
Alexander Musmanf82886e2014-09-18 05:12:34 +00002893}
2894
Alexey Bataev2df54a02015-03-12 08:53:29 +00002895static LValue createSectionLVal(CodeGenFunction &CGF, QualType Ty,
2896 const Twine &Name,
2897 llvm::Value *Init = nullptr) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002898 LValue LVal = CGF.MakeAddrLValue(CGF.CreateMemTemp(Ty, Name), Ty);
Alexey Bataev2df54a02015-03-12 08:53:29 +00002899 if (Init)
Akira Hatanaka642f7992016-10-18 19:05:41 +00002900 CGF.EmitStoreThroughLValue(RValue::get(Init), LVal, /*isInit*/ true);
Alexey Bataev2df54a02015-03-12 08:53:29 +00002901 return LVal;
Alexey Bataevd3f8dd22014-06-25 11:44:49 +00002902}
2903
Alexey Bataev3392d762016-02-16 11:18:12 +00002904void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002905 const Stmt *CapturedStmt = S.getInnermostCapturedStmt()->getCapturedStmt();
2906 const auto *CS = dyn_cast<CompoundStmt>(CapturedStmt);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002907 bool HasLastprivates = false;
Alexey Bataevddf3db92018-04-13 17:31:06 +00002908 auto &&CodeGen = [&S, CapturedStmt, CS,
2909 &HasLastprivates](CodeGenFunction &CGF, PrePostActionTy &) {
2910 ASTContext &C = CGF.getContext();
2911 QualType KmpInt32Ty =
2912 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002913 // Emit helper vars inits.
2914 LValue LB = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.lb.",
2915 CGF.Builder.getInt32(0));
Alexey Bataevddf3db92018-04-13 17:31:06 +00002916 llvm::ConstantInt *GlobalUBVal = CS != nullptr
2917 ? CGF.Builder.getInt32(CS->size() - 1)
2918 : CGF.Builder.getInt32(0);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002919 LValue UB =
2920 createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.ub.", GlobalUBVal);
2921 LValue ST = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.st.",
2922 CGF.Builder.getInt32(1));
2923 LValue IL = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.il.",
2924 CGF.Builder.getInt32(0));
2925 // Loop counter.
2926 LValue IV = createSectionLVal(CGF, KmpInt32Ty, ".omp.sections.iv.");
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002927 OpaqueValueExpr IVRefExpr(S.getBeginLoc(), KmpInt32Ty, VK_LValue);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002928 CodeGenFunction::OpaqueValueMapping OpaqueIV(CGF, &IVRefExpr, IV);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002929 OpaqueValueExpr UBRefExpr(S.getBeginLoc(), KmpInt32Ty, VK_LValue);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002930 CodeGenFunction::OpaqueValueMapping OpaqueUB(CGF, &UBRefExpr, UB);
2931 // Generate condition for loop.
2932 BinaryOperator Cond(&IVRefExpr, &UBRefExpr, BO_LE, C.BoolTy, VK_RValue,
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002933 OK_Ordinary, S.getBeginLoc(), FPOptions());
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002934 // Increment for loop counter.
2935 UnaryOperator Inc(&IVRefExpr, UO_PreInc, KmpInt32Ty, VK_RValue, OK_Ordinary,
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002936 S.getBeginLoc(), true);
Alexey Bataevddf3db92018-04-13 17:31:06 +00002937 auto &&BodyGen = [CapturedStmt, CS, &S, &IV](CodeGenFunction &CGF) {
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002938 // Iterate through all sections and emit a switch construct:
2939 // switch (IV) {
2940 // case 0:
2941 // <SectionStmt[0]>;
2942 // break;
2943 // ...
2944 // case <NumSection> - 1:
2945 // <SectionStmt[<NumSection> - 1]>;
2946 // break;
2947 // }
2948 // .omp.sections.exit:
Alexey Bataevddf3db92018-04-13 17:31:06 +00002949 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".omp.sections.exit");
2950 llvm::SwitchInst *SwitchStmt =
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002951 CGF.Builder.CreateSwitch(CGF.EmitLoadOfScalar(IV, S.getBeginLoc()),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00002952 ExitBB, CS == nullptr ? 1 : CS->size());
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002953 if (CS) {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002954 unsigned CaseNumber = 0;
Alexey Bataevddf3db92018-04-13 17:31:06 +00002955 for (const Stmt *SubStmt : CS->children()) {
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002956 auto CaseBB = CGF.createBasicBlock(".omp.sections.case");
2957 CGF.EmitBlock(CaseBB);
2958 SwitchStmt->addCase(CGF.Builder.getInt32(CaseNumber), CaseBB);
Benjamin Kramer642f1732015-07-02 21:03:14 +00002959 CGF.EmitStmt(SubStmt);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002960 CGF.EmitBranch(ExitBB);
Benjamin Kramer642f1732015-07-02 21:03:14 +00002961 ++CaseNumber;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002962 }
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002963 } else {
Alexey Bataevddf3db92018-04-13 17:31:06 +00002964 llvm::BasicBlock *CaseBB = CGF.createBasicBlock(".omp.sections.case");
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002965 CGF.EmitBlock(CaseBB);
2966 SwitchStmt->addCase(CGF.Builder.getInt32(0), CaseBB);
Alexey Bataevddf3db92018-04-13 17:31:06 +00002967 CGF.EmitStmt(CapturedStmt);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002968 CGF.EmitBranch(ExitBB);
Alexey Bataev2cb9b952015-04-24 03:37:03 +00002969 }
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002970 CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
Alexey Bataev2df54a02015-03-12 08:53:29 +00002971 };
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00002972
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002973 CodeGenFunction::OMPPrivateScope LoopScope(CGF);
2974 if (CGF.EmitOMPFirstprivateClause(S, LoopScope)) {
Alexey Bataev9efc03b2015-04-27 04:34:03 +00002975 // Emit implicit barrier to synchronize threads and avoid data races on
Alexey Bataevcd8b6a22016-02-15 08:07:17 +00002976 // initialization of firstprivate variables and post-update of lastprivate
2977 // variables.
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002978 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002979 CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002980 /*ForceSimpleCall=*/true);
Alexey Bataev9efc03b2015-04-27 04:34:03 +00002981 }
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002982 CGF.EmitOMPPrivateClause(S, LoopScope);
Alexey Bataeva58da1a2019-12-27 09:44:43 -05002983 CGOpenMPRuntime::LastprivateConditionalRAII LPCRegion(CGF, S, IV);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002984 HasLastprivates = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
2985 CGF.EmitOMPReductionClauseInit(S, LoopScope);
2986 (void)LoopScope.Privatize();
Alexey Bataev60705422018-10-30 15:50:12 +00002987 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
2988 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
Alexey Bataev2cb9b952015-04-24 03:37:03 +00002989
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002990 // Emit static non-chunked loop.
Alexey Bataev9ebd7422016-05-10 09:57:36 +00002991 OpenMPScheduleTy ScheduleKind;
2992 ScheduleKind.Schedule = OMPC_SCHEDULE_static;
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00002993 CGOpenMPRuntime::StaticRTInput StaticInit(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08002994 /*IVSize=*/32, /*IVSigned=*/true, /*Ordered=*/false, IL.getAddress(CGF),
2995 LB.getAddress(CGF), UB.getAddress(CGF), ST.getAddress(CGF));
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002996 CGF.CGM.getOpenMPRuntime().emitForStaticInit(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002997 CGF, S.getBeginLoc(), S.getDirectiveKind(), ScheduleKind, StaticInit);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00002998 // UB = min(UB, GlobalUB);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00002999 llvm::Value *UBVal = CGF.EmitLoadOfScalar(UB, S.getBeginLoc());
Alexey Bataevddf3db92018-04-13 17:31:06 +00003000 llvm::Value *MinUBGlobalUB = CGF.Builder.CreateSelect(
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003001 CGF.Builder.CreateICmpSLT(UBVal, GlobalUBVal), UBVal, GlobalUBVal);
3002 CGF.EmitStoreOfScalar(MinUBGlobalUB, UB);
3003 // IV = LB;
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003004 CGF.EmitStoreOfScalar(CGF.EmitLoadOfScalar(LB, S.getBeginLoc()), IV);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003005 // while (idx <= UB) { BODY; ++idx; }
3006 CGF.EmitOMPInnerLoop(S, /*RequiresCleanup=*/false, &Cond, &Inc, BodyGen,
3007 [](CodeGenFunction &) {});
3008 // Tell the runtime we are done.
Alexey Bataev957d8562016-11-17 15:12:05 +00003009 auto &&CodeGen = [&S](CodeGenFunction &CGF) {
Stephen Kelly1c301dc2018-08-09 21:09:38 +00003010 CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
Alexey Bataevf43f7142017-09-06 16:17:35 +00003011 S.getDirectiveKind());
Alexey Bataev957d8562016-11-17 15:12:05 +00003012 };
3013 CGF.OMPCancelStack.emitExit(CGF, S.getDirectiveKind(), CodeGen);
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00003014 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
Alexey Bataev61205072016-03-02 04:57:40 +00003015 // Emit post-update of the reduction variables if IsLastIter != 0.
Alexey Bataevddf3db92018-04-13 17:31:06 +00003016 emitPostUpdateForReductionClause(CGF, S, [IL, &S](CodeGenFunction &CGF) {
3017 return CGF.Builder.CreateIsNotNull(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003018 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
Alexey Bataevddf3db92018-04-13 17:31:06 +00003019 });
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003020
3021 // Emit final copy of the lastprivate variables if IsLastIter != 0.
3022 if (HasLastprivates)
3023 CGF.EmitOMPLastprivateClauseFinal(
Alexey Bataev5dff95c2016-04-22 03:56:56 +00003024 S, /*NoFinals=*/false,
3025 CGF.Builder.CreateIsNotNull(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003026 CGF.EmitLoadOfScalar(IL, S.getBeginLoc())));
Alexey Bataev68adb7d2015-04-14 03:29:22 +00003027 };
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003028
3029 bool HasCancel = false;
3030 if (auto *OSD = dyn_cast<OMPSectionsDirective>(&S))
3031 HasCancel = OSD->hasCancel();
3032 else if (auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&S))
3033 HasCancel = OPSD->hasCancel();
Alexey Bataev957d8562016-11-17 15:12:05 +00003034 OMPCancelStackRAII CancelRegion(*this, S.getDirectiveKind(), HasCancel);
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003035 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_sections, CodeGen,
3036 HasCancel);
3037 // Emit barrier for lastprivates only if 'sections' directive has 'nowait'
3038 // clause. Otherwise the barrier will be generated by the codegen for the
3039 // directive.
3040 if (HasLastprivates && S.getSingleClause<OMPNowaitClause>()) {
Alexey Bataev2cb9b952015-04-24 03:37:03 +00003041 // Emit implicit barrier to synchronize threads and avoid data races on
3042 // initialization of firstprivate variables.
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003043 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(),
Alexey Bataev3015bcc2016-01-22 08:56:50 +00003044 OMPD_unknown);
Alexey Bataev2cb9b952015-04-24 03:37:03 +00003045 }
Alexey Bataev68adb7d2015-04-14 03:29:22 +00003046}
Alexey Bataev2df54a02015-03-12 08:53:29 +00003047
Alexey Bataev68adb7d2015-04-14 03:29:22 +00003048void CodeGenFunction::EmitOMPSectionsDirective(const OMPSectionsDirective &S) {
Alexey Bataev3392d762016-02-16 11:18:12 +00003049 {
Alexey Bataev46978742020-01-30 10:46:11 -05003050 auto LPCRegion =
3051 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev475a7442018-01-12 19:39:11 +00003052 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataev3392d762016-02-16 11:18:12 +00003053 EmitSections(S);
3054 }
Alexey Bataev2df54a02015-03-12 08:53:29 +00003055 // Emit an implicit barrier at the end.
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00003056 if (!S.getSingleClause<OMPNowaitClause>()) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003057 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(),
Alexey Bataev3392d762016-02-16 11:18:12 +00003058 OMPD_sections);
Alexey Bataevf2685682015-03-30 04:30:22 +00003059 }
Alexey Bataev46978742020-01-30 10:46:11 -05003060 // Check for outer lastprivate conditional update.
3061 checkForLastprivateConditionalUpdate(*this, S);
Alexey Bataev2df54a02015-03-12 08:53:29 +00003062}
3063
3064void CodeGenFunction::EmitOMPSectionDirective(const OMPSectionDirective &S) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003065 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev475a7442018-01-12 19:39:11 +00003066 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003067 };
Alexey Bataev475a7442018-01-12 19:39:11 +00003068 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataev25e5b442015-09-15 12:52:43 +00003069 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_section, CodeGen,
3070 S.hasCancel());
Alexey Bataev1e0498a2014-06-26 08:21:58 +00003071}
3072
Alexey Bataev6956e2e2015-02-05 06:35:41 +00003073void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &S) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00003074 llvm::SmallVector<const Expr *, 8> CopyprivateVars;
Alexey Bataev420d45b2015-04-14 05:11:24 +00003075 llvm::SmallVector<const Expr *, 8> DestExprs;
Alexey Bataeva63048e2015-03-23 06:18:07 +00003076 llvm::SmallVector<const Expr *, 8> SrcExprs;
Alexey Bataeva63048e2015-03-23 06:18:07 +00003077 llvm::SmallVector<const Expr *, 8> AssignmentOps;
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003078 // Check if there are any 'copyprivate' clauses associated with this
Alexey Bataevcd8b6a22016-02-15 08:07:17 +00003079 // 'single' construct.
Alexey Bataeva63048e2015-03-23 06:18:07 +00003080 // Build a list of copyprivate variables along with helper expressions
3081 // (<source>, <destination>, <destination>=<source> expressions)
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00003082 for (const auto *C : S.getClausesOfKind<OMPCopyprivateClause>()) {
Alexey Bataeva63048e2015-03-23 06:18:07 +00003083 CopyprivateVars.append(C->varlists().begin(), C->varlists().end());
Alexey Bataev420d45b2015-04-14 05:11:24 +00003084 DestExprs.append(C->destination_exprs().begin(),
3085 C->destination_exprs().end());
Alexey Bataeva63048e2015-03-23 06:18:07 +00003086 SrcExprs.append(C->source_exprs().begin(), C->source_exprs().end());
Alexey Bataeva63048e2015-03-23 06:18:07 +00003087 AssignmentOps.append(C->assignment_ops().begin(),
3088 C->assignment_ops().end());
3089 }
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003090 // Emit code for 'single' region along with 'copyprivate' clauses
3091 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3092 Action.Enter(CGF);
3093 OMPPrivateScope SingleScope(CGF);
3094 (void)CGF.EmitOMPFirstprivateClause(S, SingleScope);
3095 CGF.EmitOMPPrivateClause(S, SingleScope);
3096 (void)SingleScope.Privatize();
Alexey Bataev475a7442018-01-12 19:39:11 +00003097 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003098 };
Alexey Bataev3392d762016-02-16 11:18:12 +00003099 {
Alexey Bataev46978742020-01-30 10:46:11 -05003100 auto LPCRegion =
3101 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev475a7442018-01-12 19:39:11 +00003102 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003103 CGM.getOpenMPRuntime().emitSingleRegion(*this, CodeGen, S.getBeginLoc(),
Alexey Bataev3392d762016-02-16 11:18:12 +00003104 CopyprivateVars, DestExprs,
3105 SrcExprs, AssignmentOps);
3106 }
3107 // Emit an implicit barrier at the end (to avoid data race on firstprivate
3108 // init or if no 'nowait' clause was specified and no 'copyprivate' clause).
Alexey Bataev417089f2016-02-17 13:19:37 +00003109 if (!S.getSingleClause<OMPNowaitClause>() && CopyprivateVars.empty()) {
Alexey Bataev5521d782015-04-24 04:21:15 +00003110 CGM.getOpenMPRuntime().emitBarrierCall(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003111 *this, S.getBeginLoc(),
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00003112 S.getSingleClause<OMPNowaitClause>() ? OMPD_unknown : OMPD_single);
Alexey Bataevf2685682015-03-30 04:30:22 +00003113 }
Alexey Bataev46978742020-01-30 10:46:11 -05003114 // Check for outer lastprivate conditional update.
3115 checkForLastprivateConditionalUpdate(*this, S);
Alexey Bataevd1e40fb2014-06-26 12:05:45 +00003116}
3117
cchen47d60942019-12-05 13:43:48 -05003118static void emitMaster(CodeGenFunction &CGF, const OMPExecutableDirective &S) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003119 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3120 Action.Enter(CGF);
Alexey Bataev475a7442018-01-12 19:39:11 +00003121 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003122 };
cchen47d60942019-12-05 13:43:48 -05003123 CGF.CGM.getOpenMPRuntime().emitMasterRegion(CGF, CodeGen, S.getBeginLoc());
3124}
3125
3126void CodeGenFunction::EmitOMPMasterDirective(const OMPMasterDirective &S) {
Fady Ghanim7438059a2020-02-15 00:42:23 -06003127 if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) {
3128 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
3129
3130 const CapturedStmt *CS = S.getInnermostCapturedStmt();
3131 const Stmt *MasterRegionBodyStmt = CS->getCapturedStmt();
3132
Fady Ghanim7438059a2020-02-15 00:42:23 -06003133 auto FiniCB = [this](InsertPointTy IP) {
Fady Ghanimba3f8632020-02-19 13:50:26 -06003134 OMPBuilderCBHelpers::FinalizeOMPRegion(*this, IP);
Fady Ghanim7438059a2020-02-15 00:42:23 -06003135 };
3136
Fady Ghanim7438059a2020-02-15 00:42:23 -06003137 auto BodyGenCB = [MasterRegionBodyStmt, this](InsertPointTy AllocaIP,
3138 InsertPointTy CodeGenIP,
3139 llvm::BasicBlock &FiniBB) {
Fady Ghanimba3f8632020-02-19 13:50:26 -06003140 OMPBuilderCBHelpers::InlinedRegionBodyRAII IRB(*this, AllocaIP, FiniBB);
3141 OMPBuilderCBHelpers::EmitOMPRegionBody(*this, MasterRegionBodyStmt,
3142 CodeGenIP, FiniBB);
Fady Ghanim7438059a2020-02-15 00:42:23 -06003143 };
Fady Ghanimba3f8632020-02-19 13:50:26 -06003144
Fady Ghanim7438059a2020-02-15 00:42:23 -06003145 CGCapturedStmtInfo CGSI(*CS, CR_OpenMP);
3146 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*this, &CGSI);
3147 Builder.restoreIP(OMPBuilder->CreateMaster(Builder, BodyGenCB, FiniCB));
3148
3149 return;
3150 }
Alexey Bataev475a7442018-01-12 19:39:11 +00003151 OMPLexicalScope Scope(*this, S, OMPD_unknown);
cchen47d60942019-12-05 13:43:48 -05003152 emitMaster(*this, S);
Alexander Musman80c22892014-07-17 08:54:58 +00003153}
3154
Alexey Bataev3a3bf0b2014-09-22 10:01:53 +00003155void CodeGenFunction::EmitOMPCriticalDirective(const OMPCriticalDirective &S) {
Fady Ghanim7438059a2020-02-15 00:42:23 -06003156 if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) {
3157 using InsertPointTy = llvm::OpenMPIRBuilder::InsertPointTy;
3158
3159 const CapturedStmt *CS = S.getInnermostCapturedStmt();
3160 const Stmt *CriticalRegionBodyStmt = CS->getCapturedStmt();
3161 const Expr *Hint = nullptr;
3162 if (const auto *HintClause = S.getSingleClause<OMPHintClause>())
3163 Hint = HintClause->getHint();
3164
3165 // TODO: This is slightly different from what's currently being done in
3166 // clang. Fix the Int32Ty to IntPtrTy (pointer width size) when everything
3167 // about typing is final.
3168 llvm::Value *HintInst = nullptr;
3169 if (Hint)
3170 HintInst =
3171 Builder.CreateIntCast(EmitScalarExpr(Hint), CGM.Int32Ty, false);
3172
Fady Ghanim7438059a2020-02-15 00:42:23 -06003173 auto FiniCB = [this](InsertPointTy IP) {
Fady Ghanimba3f8632020-02-19 13:50:26 -06003174 OMPBuilderCBHelpers::FinalizeOMPRegion(*this, IP);
Fady Ghanim7438059a2020-02-15 00:42:23 -06003175 };
3176
Fady Ghanim7438059a2020-02-15 00:42:23 -06003177 auto BodyGenCB = [CriticalRegionBodyStmt, this](InsertPointTy AllocaIP,
3178 InsertPointTy CodeGenIP,
3179 llvm::BasicBlock &FiniBB) {
Fady Ghanimba3f8632020-02-19 13:50:26 -06003180 OMPBuilderCBHelpers::InlinedRegionBodyRAII IRB(*this, AllocaIP, FiniBB);
3181 OMPBuilderCBHelpers::EmitOMPRegionBody(*this, CriticalRegionBodyStmt,
3182 CodeGenIP, FiniBB);
Fady Ghanim7438059a2020-02-15 00:42:23 -06003183 };
3184
3185 CGCapturedStmtInfo CGSI(*CS, CR_OpenMP);
3186 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(*this, &CGSI);
3187 Builder.restoreIP(OMPBuilder->CreateCritical(
3188 Builder, BodyGenCB, FiniCB, S.getDirectiveName().getAsString(),
3189 HintInst));
3190
3191 return;
3192 }
3193
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003194 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3195 Action.Enter(CGF);
Alexey Bataev475a7442018-01-12 19:39:11 +00003196 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003197 };
Alexey Bataevddf3db92018-04-13 17:31:06 +00003198 const Expr *Hint = nullptr;
3199 if (const auto *HintClause = S.getSingleClause<OMPHintClause>())
Alexey Bataevfc57d162015-12-15 10:55:09 +00003200 Hint = HintClause->getHint();
Alexey Bataev475a7442018-01-12 19:39:11 +00003201 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataevfc57d162015-12-15 10:55:09 +00003202 CGM.getOpenMPRuntime().emitCriticalRegion(*this,
3203 S.getDirectiveName().getAsString(),
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003204 CodeGen, S.getBeginLoc(), Hint);
Alexander Musmand9ed09f2014-07-21 09:42:05 +00003205}
3206
Alexey Bataev671605e2015-04-13 05:28:11 +00003207void CodeGenFunction::EmitOMPParallelForDirective(
3208 const OMPParallelForDirective &S) {
3209 // Emit directive as a combined directive that consists of two implicit
3210 // directives: 'parallel' with 'for' directive.
Alexey Bataevc99042b2018-03-15 18:10:54 +00003211 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3212 Action.Enter(CGF);
Alexey Bataev957d8562016-11-17 15:12:05 +00003213 OMPCancelStackRAII CancelRegion(CGF, OMPD_parallel_for, S.hasCancel());
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003214 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
3215 emitDispatchForLoopBounds);
Alexey Bataev671605e2015-04-13 05:28:11 +00003216 };
Alexey Bataev46978742020-01-30 10:46:11 -05003217 {
3218 auto LPCRegion =
3219 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
3220 emitCommonOMPParallelDirective(*this, S, OMPD_for, CodeGen,
3221 emitEmptyBoundParameters);
3222 }
3223 // Check for outer lastprivate conditional update.
3224 checkForLastprivateConditionalUpdate(*this, S);
Alexey Bataev4acb8592014-07-07 13:01:15 +00003225}
3226
Alexander Musmane4e893b2014-09-23 09:33:00 +00003227void CodeGenFunction::EmitOMPParallelForSimdDirective(
Alexey Bataev3b5b5c42015-06-18 10:10:12 +00003228 const OMPParallelForSimdDirective &S) {
3229 // Emit directive as a combined directive that consists of two implicit
3230 // directives: 'parallel' with 'for' directive.
Alexey Bataevc99042b2018-03-15 18:10:54 +00003231 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3232 Action.Enter(CGF);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003233 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
3234 emitDispatchForLoopBounds);
Alexey Bataev3b5b5c42015-06-18 10:10:12 +00003235 };
Alexey Bataev46978742020-01-30 10:46:11 -05003236 {
3237 auto LPCRegion =
3238 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
3239 emitCommonOMPParallelDirective(*this, S, OMPD_simd, CodeGen,
3240 emitEmptyBoundParameters);
3241 }
3242 // Check for outer lastprivate conditional update.
3243 checkForLastprivateConditionalUpdate(*this, S);
Alexander Musmane4e893b2014-09-23 09:33:00 +00003244}
3245
cchen47d60942019-12-05 13:43:48 -05003246void CodeGenFunction::EmitOMPParallelMasterDirective(
3247 const OMPParallelMasterDirective &S) {
3248 // Emit directive as a combined directive that consists of two implicit
3249 // directives: 'parallel' with 'master' directive.
3250 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3251 Action.Enter(CGF);
3252 OMPPrivateScope PrivateScope(CGF);
3253 bool Copyins = CGF.EmitOMPCopyinClause(S);
3254 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
3255 if (Copyins) {
3256 // Emit implicit barrier to synchronize threads and avoid data races on
3257 // propagation master's thread values of threadprivate variables to local
3258 // instances of that variables of all other implicit threads.
3259 CGF.CGM.getOpenMPRuntime().emitBarrierCall(
3260 CGF, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
3261 /*ForceSimpleCall=*/true);
3262 }
3263 CGF.EmitOMPPrivateClause(S, PrivateScope);
3264 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
3265 (void)PrivateScope.Privatize();
3266 emitMaster(CGF, S);
3267 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
3268 };
Alexey Bataev46978742020-01-30 10:46:11 -05003269 {
3270 auto LPCRegion =
3271 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
3272 emitCommonOMPParallelDirective(*this, S, OMPD_master, CodeGen,
3273 emitEmptyBoundParameters);
3274 emitPostUpdateForReductionClause(*this, S,
3275 [](CodeGenFunction &) { return nullptr; });
3276 }
3277 // Check for outer lastprivate conditional update.
3278 checkForLastprivateConditionalUpdate(*this, S);
cchen47d60942019-12-05 13:43:48 -05003279}
3280
Alexey Bataev84d0b3e2014-07-08 08:12:03 +00003281void CodeGenFunction::EmitOMPParallelSectionsDirective(
Alexey Bataev68adb7d2015-04-14 03:29:22 +00003282 const OMPParallelSectionsDirective &S) {
3283 // Emit directive as a combined directive that consists of two implicit
3284 // directives: 'parallel' with 'sections' directive.
Alexey Bataevc99042b2018-03-15 18:10:54 +00003285 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3286 Action.Enter(CGF);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003287 CGF.EmitSections(S);
3288 };
Alexey Bataev46978742020-01-30 10:46:11 -05003289 {
3290 auto LPCRegion =
3291 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
3292 emitCommonOMPParallelDirective(*this, S, OMPD_sections, CodeGen,
3293 emitEmptyBoundParameters);
3294 }
3295 // Check for outer lastprivate conditional update.
3296 checkForLastprivateConditionalUpdate(*this, S);
Alexey Bataev84d0b3e2014-07-08 08:12:03 +00003297}
3298
Alexey Bataev475a7442018-01-12 19:39:11 +00003299void CodeGenFunction::EmitOMPTaskBasedDirective(
3300 const OMPExecutableDirective &S, const OpenMPDirectiveKind CapturedRegion,
3301 const RegionCodeGenTy &BodyGen, const TaskGenTy &TaskGen,
3302 OMPTaskDataTy &Data) {
Alexey Bataev62b63b12015-03-10 07:28:44 +00003303 // Emit outlined function for task construct.
Alexey Bataev475a7442018-01-12 19:39:11 +00003304 const CapturedStmt *CS = S.getCapturedStmt(CapturedRegion);
Alexey Bataevddf3db92018-04-13 17:31:06 +00003305 auto I = CS->getCapturedDecl()->param_begin();
3306 auto PartId = std::next(I);
3307 auto TaskT = std::next(I, 4);
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003308 // Check if the task is final
3309 if (const auto *Clause = S.getSingleClause<OMPFinalClause>()) {
3310 // If the condition constant folds and can be elided, try to avoid emitting
3311 // the condition and the dead arm of the if/else.
Alexey Bataevddf3db92018-04-13 17:31:06 +00003312 const Expr *Cond = Clause->getCondition();
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003313 bool CondConstant;
3314 if (ConstantFoldsToSimpleInteger(Cond, CondConstant))
3315 Data.Final.setInt(CondConstant);
3316 else
3317 Data.Final.setPointer(EvaluateExprAsBool(Cond));
3318 } else {
3319 // By default the task is not final.
3320 Data.Final.setInt(/*IntVal=*/false);
3321 }
Alexey Bataev1e1e2862016-05-10 12:21:02 +00003322 // Check if the task has 'priority' clause.
3323 if (const auto *Clause = S.getSingleClause<OMPPriorityClause>()) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00003324 const Expr *Prio = Clause->getPriority();
Alexey Bataev5140e742016-07-19 04:21:09 +00003325 Data.Priority.setInt(/*IntVal=*/true);
Alexey Bataevad537bb2016-05-30 09:06:50 +00003326 Data.Priority.setPointer(EmitScalarConversion(
3327 EmitScalarExpr(Prio), Prio->getType(),
3328 getContext().getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1),
3329 Prio->getExprLoc()));
Alexey Bataev1e1e2862016-05-10 12:21:02 +00003330 }
Alexey Bataev62b63b12015-03-10 07:28:44 +00003331 // The first function argument for tasks is a thread id, the second one is a
3332 // part id (0 for tied tasks, >=0 for untied task).
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003333 llvm::DenseSet<const VarDecl *> EmittedAsPrivate;
3334 // Get list of private variables.
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00003335 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003336 auto IRef = C->varlist_begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00003337 for (const Expr *IInit : C->private_copies()) {
3338 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003339 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
Alexey Bataev7292c292016-04-25 12:22:29 +00003340 Data.PrivateVars.push_back(*IRef);
3341 Data.PrivateCopies.push_back(IInit);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003342 }
3343 ++IRef;
3344 }
3345 }
3346 EmittedAsPrivate.clear();
3347 // Get list of firstprivate variables.
Benjamin Kramerfc600dc2015-08-30 15:12:28 +00003348 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003349 auto IRef = C->varlist_begin();
3350 auto IElemInitRef = C->inits().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00003351 for (const Expr *IInit : C->private_copies()) {
3352 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003353 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
Alexey Bataev7292c292016-04-25 12:22:29 +00003354 Data.FirstprivateVars.push_back(*IRef);
3355 Data.FirstprivateCopies.push_back(IInit);
3356 Data.FirstprivateInits.push_back(*IElemInitRef);
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003357 }
Richard Trieucc3949d2016-02-18 22:34:54 +00003358 ++IRef;
3359 ++IElemInitRef;
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003360 }
3361 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00003362 // Get list of lastprivate variables (for taskloops).
3363 llvm::DenseMap<const VarDecl *, const DeclRefExpr *> LastprivateDstsOrigs;
3364 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) {
3365 auto IRef = C->varlist_begin();
3366 auto ID = C->destination_exprs().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00003367 for (const Expr *IInit : C->private_copies()) {
3368 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*IRef)->getDecl());
Alexey Bataevf93095a2016-05-05 08:46:22 +00003369 if (EmittedAsPrivate.insert(OrigVD->getCanonicalDecl()).second) {
3370 Data.LastprivateVars.push_back(*IRef);
3371 Data.LastprivateCopies.push_back(IInit);
3372 }
3373 LastprivateDstsOrigs.insert(
3374 {cast<VarDecl>(cast<DeclRefExpr>(*ID)->getDecl()),
3375 cast<DeclRefExpr>(*IRef)});
3376 ++IRef;
3377 ++ID;
3378 }
3379 }
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003380 SmallVector<const Expr *, 4> LHSs;
3381 SmallVector<const Expr *, 4> RHSs;
3382 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) {
3383 auto IPriv = C->privates().begin();
3384 auto IRed = C->reduction_ops().begin();
3385 auto ILHS = C->lhs_exprs().begin();
3386 auto IRHS = C->rhs_exprs().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00003387 for (const Expr *Ref : C->varlists()) {
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003388 Data.ReductionVars.emplace_back(Ref);
3389 Data.ReductionCopies.emplace_back(*IPriv);
3390 Data.ReductionOps.emplace_back(*IRed);
3391 LHSs.emplace_back(*ILHS);
3392 RHSs.emplace_back(*IRHS);
3393 std::advance(IPriv, 1);
3394 std::advance(IRed, 1);
3395 std::advance(ILHS, 1);
3396 std::advance(IRHS, 1);
3397 }
3398 }
3399 Data.Reductions = CGM.getOpenMPRuntime().emitTaskReductionInit(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003400 *this, S.getBeginLoc(), LHSs, RHSs, Data);
Alexey Bataev1d2353d2015-06-24 11:01:36 +00003401 // Build list of dependences.
Alexey Bataev7292c292016-04-25 12:22:29 +00003402 for (const auto *C : S.getClausesOfKind<OMPDependClause>())
Alexey Bataevddf3db92018-04-13 17:31:06 +00003403 for (const Expr *IRef : C->varlists())
Alexey Bataev43a919f2018-04-13 17:48:43 +00003404 Data.Dependences.emplace_back(C->getDependencyKind(), IRef);
Alexey Bataev475a7442018-01-12 19:39:11 +00003405 auto &&CodeGen = [&Data, &S, CS, &BodyGen, &LastprivateDstsOrigs,
3406 CapturedRegion](CodeGenFunction &CGF,
3407 PrePostActionTy &Action) {
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003408 // Set proper addresses for generated private copies.
Alexey Bataev7292c292016-04-25 12:22:29 +00003409 OMPPrivateScope Scope(CGF);
Alexey Bataevb3998a02020-03-09 08:55:57 -04003410 llvm::SmallVector<std::pair<const VarDecl *, Address>, 16> FirstprivatePtrs;
Alexey Bataevf93095a2016-05-05 08:46:22 +00003411 if (!Data.PrivateVars.empty() || !Data.FirstprivateVars.empty() ||
3412 !Data.LastprivateVars.empty()) {
James Y Knight9871db02019-02-05 16:42:33 +00003413 llvm::FunctionType *CopyFnTy = llvm::FunctionType::get(
3414 CGF.Builder.getVoidTy(), {CGF.Builder.getInt8PtrTy()}, true);
Alexey Bataev3c595a62017-08-14 15:01:03 +00003415 enum { PrivatesParam = 2, CopyFnParam = 3 };
Alexey Bataevddf3db92018-04-13 17:31:06 +00003416 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
3417 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam)));
3418 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
3419 CS->getCapturedDecl()->getParam(PrivatesParam)));
Alexey Bataev48591dd2016-04-20 04:01:36 +00003420 // Map privates.
3421 llvm::SmallVector<std::pair<const VarDecl *, Address>, 16> PrivatePtrs;
3422 llvm::SmallVector<llvm::Value *, 16> CallArgs;
3423 CallArgs.push_back(PrivatesPtr);
Alexey Bataevddf3db92018-04-13 17:31:06 +00003424 for (const Expr *E : Data.PrivateVars) {
3425 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev48591dd2016-04-20 04:01:36 +00003426 Address PrivatePtr = CGF.CreateMemTemp(
3427 CGF.getContext().getPointerType(E->getType()), ".priv.ptr.addr");
Alexey Bataevddf3db92018-04-13 17:31:06 +00003428 PrivatePtrs.emplace_back(VD, PrivatePtr);
Alexey Bataev48591dd2016-04-20 04:01:36 +00003429 CallArgs.push_back(PrivatePtr.getPointer());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003430 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00003431 for (const Expr *E : Data.FirstprivateVars) {
3432 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev48591dd2016-04-20 04:01:36 +00003433 Address PrivatePtr =
3434 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()),
3435 ".firstpriv.ptr.addr");
Alexey Bataevddf3db92018-04-13 17:31:06 +00003436 PrivatePtrs.emplace_back(VD, PrivatePtr);
Alexey Bataevb3998a02020-03-09 08:55:57 -04003437 FirstprivatePtrs.emplace_back(VD, PrivatePtr);
Alexey Bataev48591dd2016-04-20 04:01:36 +00003438 CallArgs.push_back(PrivatePtr.getPointer());
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003439 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00003440 for (const Expr *E : Data.LastprivateVars) {
3441 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataevf93095a2016-05-05 08:46:22 +00003442 Address PrivatePtr =
3443 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()),
3444 ".lastpriv.ptr.addr");
Alexey Bataevddf3db92018-04-13 17:31:06 +00003445 PrivatePtrs.emplace_back(VD, PrivatePtr);
Alexey Bataevf93095a2016-05-05 08:46:22 +00003446 CallArgs.push_back(PrivatePtr.getPointer());
3447 }
James Y Knight9871db02019-02-05 16:42:33 +00003448 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
3449 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
Alexey Bataevddf3db92018-04-13 17:31:06 +00003450 for (const auto &Pair : LastprivateDstsOrigs) {
3451 const auto *OrigVD = cast<VarDecl>(Pair.second->getDecl());
Bruno Ricci5fc4db72018-12-21 14:10:18 +00003452 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(OrigVD),
3453 /*RefersToEnclosingVariableOrCapture=*/
3454 CGF.CapturedStmtInfo->lookup(OrigVD) != nullptr,
3455 Pair.second->getType(), VK_LValue,
3456 Pair.second->getExprLoc());
Alexey Bataevf93095a2016-05-05 08:46:22 +00003457 Scope.addPrivate(Pair.first, [&CGF, &DRE]() {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08003458 return CGF.EmitLValue(&DRE).getAddress(CGF);
Alexey Bataevf93095a2016-05-05 08:46:22 +00003459 });
3460 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00003461 for (const auto &Pair : PrivatePtrs) {
Alexey Bataev48591dd2016-04-20 04:01:36 +00003462 Address Replacement(CGF.Builder.CreateLoad(Pair.second),
3463 CGF.getContext().getDeclAlign(Pair.first));
3464 Scope.addPrivate(Pair.first, [Replacement]() { return Replacement; });
3465 }
Alexey Bataev3ae88e22015-05-22 08:56:35 +00003466 }
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003467 if (Data.Reductions) {
Alexey Bataevb3998a02020-03-09 08:55:57 -04003468 OMPPrivateScope FirstprivateScope(CGF);
3469 for (const auto &Pair : FirstprivatePtrs) {
3470 Address Replacement(CGF.Builder.CreateLoad(Pair.second),
3471 CGF.getContext().getDeclAlign(Pair.first));
3472 FirstprivateScope.addPrivate(Pair.first,
3473 [Replacement]() { return Replacement; });
3474 }
3475 (void)FirstprivateScope.Privatize();
Alexey Bataev475a7442018-01-12 19:39:11 +00003476 OMPLexicalScope LexScope(CGF, S, CapturedRegion);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003477 ReductionCodeGen RedCG(Data.ReductionVars, Data.ReductionCopies,
3478 Data.ReductionOps);
3479 llvm::Value *ReductionsPtr = CGF.Builder.CreateLoad(
3480 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(9)));
3481 for (unsigned Cnt = 0, E = Data.ReductionVars.size(); Cnt < E; ++Cnt) {
3482 RedCG.emitSharedLValue(CGF, Cnt);
3483 RedCG.emitAggregateType(CGF, Cnt);
Alexey Bataev2e0cbe502018-03-08 15:24:08 +00003484 // FIXME: This must removed once the runtime library is fixed.
3485 // Emit required threadprivate variables for
Raphael Isemannb23ccec2018-12-10 12:37:46 +00003486 // initializer/combiner/finalizer.
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003487 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
Alexey Bataev2e0cbe502018-03-08 15:24:08 +00003488 RedCG, Cnt);
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003489 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003490 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003491 Replacement =
3492 Address(CGF.EmitScalarConversion(
3493 Replacement.getPointer(), CGF.getContext().VoidPtrTy,
3494 CGF.getContext().getPointerType(
3495 Data.ReductionCopies[Cnt]->getType()),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003496 Data.ReductionCopies[Cnt]->getExprLoc()),
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003497 Replacement.getAlignment());
3498 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
3499 Scope.addPrivate(RedCG.getBaseDecl(Cnt),
3500 [Replacement]() { return Replacement; });
Alexey Bataevbe5a8b42017-07-17 13:30:36 +00003501 }
3502 }
Alexey Bataev88202be2017-07-27 13:20:36 +00003503 // Privatize all private variables except for in_reduction items.
Alexey Bataev48591dd2016-04-20 04:01:36 +00003504 (void)Scope.Privatize();
Alexey Bataev88202be2017-07-27 13:20:36 +00003505 SmallVector<const Expr *, 4> InRedVars;
3506 SmallVector<const Expr *, 4> InRedPrivs;
3507 SmallVector<const Expr *, 4> InRedOps;
3508 SmallVector<const Expr *, 4> TaskgroupDescriptors;
3509 for (const auto *C : S.getClausesOfKind<OMPInReductionClause>()) {
3510 auto IPriv = C->privates().begin();
3511 auto IRed = C->reduction_ops().begin();
3512 auto ITD = C->taskgroup_descriptors().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00003513 for (const Expr *Ref : C->varlists()) {
Alexey Bataev88202be2017-07-27 13:20:36 +00003514 InRedVars.emplace_back(Ref);
3515 InRedPrivs.emplace_back(*IPriv);
3516 InRedOps.emplace_back(*IRed);
3517 TaskgroupDescriptors.emplace_back(*ITD);
3518 std::advance(IPriv, 1);
3519 std::advance(IRed, 1);
3520 std::advance(ITD, 1);
3521 }
3522 }
3523 // Privatize in_reduction items here, because taskgroup descriptors must be
3524 // privatized earlier.
3525 OMPPrivateScope InRedScope(CGF);
3526 if (!InRedVars.empty()) {
3527 ReductionCodeGen RedCG(InRedVars, InRedPrivs, InRedOps);
3528 for (unsigned Cnt = 0, E = InRedVars.size(); Cnt < E; ++Cnt) {
3529 RedCG.emitSharedLValue(CGF, Cnt);
3530 RedCG.emitAggregateType(CGF, Cnt);
3531 // The taskgroup descriptor variable is always implicit firstprivate and
Raphael Isemannb23ccec2018-12-10 12:37:46 +00003532 // privatized already during processing of the firstprivates.
Alexey Bataev2e0cbe502018-03-08 15:24:08 +00003533 // FIXME: This must removed once the runtime library is fixed.
3534 // Emit required threadprivate variables for
Raphael Isemannb23ccec2018-12-10 12:37:46 +00003535 // initializer/combiner/finalizer.
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003536 CGF.CGM.getOpenMPRuntime().emitTaskReductionFixups(CGF, S.getBeginLoc(),
Alexey Bataev2e0cbe502018-03-08 15:24:08 +00003537 RedCG, Cnt);
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003538 llvm::Value *ReductionsPtr =
3539 CGF.EmitLoadOfScalar(CGF.EmitLValue(TaskgroupDescriptors[Cnt]),
3540 TaskgroupDescriptors[Cnt]->getExprLoc());
Alexey Bataev88202be2017-07-27 13:20:36 +00003541 Address Replacement = CGF.CGM.getOpenMPRuntime().getTaskReductionItem(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003542 CGF, S.getBeginLoc(), ReductionsPtr, RedCG.getSharedLValue(Cnt));
Alexey Bataev88202be2017-07-27 13:20:36 +00003543 Replacement = Address(
3544 CGF.EmitScalarConversion(
3545 Replacement.getPointer(), CGF.getContext().VoidPtrTy,
3546 CGF.getContext().getPointerType(InRedPrivs[Cnt]->getType()),
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003547 InRedPrivs[Cnt]->getExprLoc()),
Alexey Bataev88202be2017-07-27 13:20:36 +00003548 Replacement.getAlignment());
3549 Replacement = RedCG.adjustPrivateAddress(CGF, Cnt, Replacement);
3550 InRedScope.addPrivate(RedCG.getBaseDecl(Cnt),
3551 [Replacement]() { return Replacement; });
Alexey Bataev88202be2017-07-27 13:20:36 +00003552 }
3553 }
3554 (void)InRedScope.Privatize();
Alexey Bataev48591dd2016-04-20 04:01:36 +00003555
3556 Action.Enter(CGF);
Alexey Bataev7292c292016-04-25 12:22:29 +00003557 BodyGen(CGF);
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00003558 };
James Y Knight9871db02019-02-05 16:42:33 +00003559 llvm::Function *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
Alexey Bataev7292c292016-04-25 12:22:29 +00003560 S, *I, *PartId, *TaskT, S.getDirectiveKind(), CodeGen, Data.Tied,
3561 Data.NumberOfParts);
Alexey Bataev5bbcead2019-10-14 17:17:41 +00003562 OMPLexicalScope Scope(*this, S, llvm::None,
Alexey Bataev61205822019-12-04 09:50:21 -05003563 !isOpenMPParallelDirective(S.getDirectiveKind()) &&
3564 !isOpenMPSimdDirective(S.getDirectiveKind()));
Alexey Bataev7292c292016-04-25 12:22:29 +00003565 TaskGen(*this, OutlinedFn, Data);
3566}
3567
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003568static ImplicitParamDecl *
3569createImplicitFirstprivateForType(ASTContext &C, OMPTaskDataTy &Data,
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003570 QualType Ty, CapturedDecl *CD,
3571 SourceLocation Loc) {
3572 auto *OrigVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, Ty,
3573 ImplicitParamDecl::Other);
3574 auto *OrigRef = DeclRefExpr::Create(
3575 C, NestedNameSpecifierLoc(), SourceLocation(), OrigVD,
3576 /*RefersToEnclosingVariableOrCapture=*/false, Loc, Ty, VK_LValue);
3577 auto *PrivateVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, Ty,
3578 ImplicitParamDecl::Other);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003579 auto *PrivateRef = DeclRefExpr::Create(
3580 C, NestedNameSpecifierLoc(), SourceLocation(), PrivateVD,
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003581 /*RefersToEnclosingVariableOrCapture=*/false, Loc, Ty, VK_LValue);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003582 QualType ElemType = C.getBaseElementType(Ty);
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003583 auto *InitVD = ImplicitParamDecl::Create(C, CD, Loc, /*Id=*/nullptr, ElemType,
3584 ImplicitParamDecl::Other);
3585 auto *InitRef = DeclRefExpr::Create(
3586 C, NestedNameSpecifierLoc(), SourceLocation(), InitVD,
3587 /*RefersToEnclosingVariableOrCapture=*/false, Loc, ElemType, VK_LValue);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003588 PrivateVD->setInitStyle(VarDecl::CInit);
3589 PrivateVD->setInit(ImplicitCastExpr::Create(C, ElemType, CK_LValueToRValue,
3590 InitRef, /*BasePath=*/nullptr,
3591 VK_RValue));
3592 Data.FirstprivateVars.emplace_back(OrigRef);
3593 Data.FirstprivateCopies.emplace_back(PrivateRef);
3594 Data.FirstprivateInits.emplace_back(InitRef);
3595 return OrigVD;
3596}
3597
3598void CodeGenFunction::EmitOMPTargetTaskBasedDirective(
3599 const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen,
3600 OMPTargetDataInfo &InputInfo) {
3601 // Emit outlined function for task construct.
Alexey Bataevddf3db92018-04-13 17:31:06 +00003602 const CapturedStmt *CS = S.getCapturedStmt(OMPD_task);
3603 Address CapturedStruct = GenerateCapturedStmtArgument(*CS);
3604 QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
3605 auto I = CS->getCapturedDecl()->param_begin();
3606 auto PartId = std::next(I);
3607 auto TaskT = std::next(I, 4);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003608 OMPTaskDataTy Data;
3609 // The task is not final.
3610 Data.Final.setInt(/*IntVal=*/false);
3611 // Get list of firstprivate variables.
3612 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) {
3613 auto IRef = C->varlist_begin();
3614 auto IElemInitRef = C->inits().begin();
3615 for (auto *IInit : C->private_copies()) {
3616 Data.FirstprivateVars.push_back(*IRef);
3617 Data.FirstprivateCopies.push_back(IInit);
3618 Data.FirstprivateInits.push_back(*IElemInitRef);
3619 ++IRef;
3620 ++IElemInitRef;
3621 }
3622 }
3623 OMPPrivateScope TargetScope(*this);
3624 VarDecl *BPVD = nullptr;
3625 VarDecl *PVD = nullptr;
3626 VarDecl *SVD = nullptr;
3627 if (InputInfo.NumberOfTargetItems > 0) {
3628 auto *CD = CapturedDecl::Create(
3629 getContext(), getContext().getTranslationUnitDecl(), /*NumParams=*/0);
3630 llvm::APInt ArrSize(/*numBits=*/32, InputInfo.NumberOfTargetItems);
3631 QualType BaseAndPointersType = getContext().getConstantArrayType(
Richard Smith772e2662019-10-04 01:25:59 +00003632 getContext().VoidPtrTy, ArrSize, nullptr, ArrayType::Normal,
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003633 /*IndexTypeQuals=*/0);
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003634 BPVD = createImplicitFirstprivateForType(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003635 getContext(), Data, BaseAndPointersType, CD, S.getBeginLoc());
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003636 PVD = createImplicitFirstprivateForType(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003637 getContext(), Data, BaseAndPointersType, CD, S.getBeginLoc());
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003638 QualType SizesType = getContext().getConstantArrayType(
Alexey Bataeva90fc662019-06-25 16:00:43 +00003639 getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1),
Richard Smith772e2662019-10-04 01:25:59 +00003640 ArrSize, nullptr, ArrayType::Normal,
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003641 /*IndexTypeQuals=*/0);
Alexey Bataeva9b9cc02018-01-23 18:12:38 +00003642 SVD = createImplicitFirstprivateForType(getContext(), Data, SizesType, CD,
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003643 S.getBeginLoc());
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003644 TargetScope.addPrivate(
3645 BPVD, [&InputInfo]() { return InputInfo.BasePointersArray; });
3646 TargetScope.addPrivate(PVD,
3647 [&InputInfo]() { return InputInfo.PointersArray; });
3648 TargetScope.addPrivate(SVD,
3649 [&InputInfo]() { return InputInfo.SizesArray; });
3650 }
3651 (void)TargetScope.Privatize();
3652 // Build list of dependences.
3653 for (const auto *C : S.getClausesOfKind<OMPDependClause>())
Alexey Bataevddf3db92018-04-13 17:31:06 +00003654 for (const Expr *IRef : C->varlists())
Alexey Bataev43a919f2018-04-13 17:48:43 +00003655 Data.Dependences.emplace_back(C->getDependencyKind(), IRef);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003656 auto &&CodeGen = [&Data, &S, CS, &BodyGen, BPVD, PVD, SVD,
3657 &InputInfo](CodeGenFunction &CGF, PrePostActionTy &Action) {
3658 // Set proper addresses for generated private copies.
3659 OMPPrivateScope Scope(CGF);
3660 if (!Data.FirstprivateVars.empty()) {
James Y Knight9871db02019-02-05 16:42:33 +00003661 llvm::FunctionType *CopyFnTy = llvm::FunctionType::get(
3662 CGF.Builder.getVoidTy(), {CGF.Builder.getInt8PtrTy()}, true);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003663 enum { PrivatesParam = 2, CopyFnParam = 3 };
Alexey Bataevddf3db92018-04-13 17:31:06 +00003664 llvm::Value *CopyFn = CGF.Builder.CreateLoad(
3665 CGF.GetAddrOfLocalVar(CS->getCapturedDecl()->getParam(CopyFnParam)));
3666 llvm::Value *PrivatesPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(
3667 CS->getCapturedDecl()->getParam(PrivatesParam)));
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003668 // Map privates.
3669 llvm::SmallVector<std::pair<const VarDecl *, Address>, 16> PrivatePtrs;
3670 llvm::SmallVector<llvm::Value *, 16> CallArgs;
3671 CallArgs.push_back(PrivatesPtr);
Alexey Bataevddf3db92018-04-13 17:31:06 +00003672 for (const Expr *E : Data.FirstprivateVars) {
3673 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003674 Address PrivatePtr =
3675 CGF.CreateMemTemp(CGF.getContext().getPointerType(E->getType()),
3676 ".firstpriv.ptr.addr");
Alexey Bataevddf3db92018-04-13 17:31:06 +00003677 PrivatePtrs.emplace_back(VD, PrivatePtr);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003678 CallArgs.push_back(PrivatePtr.getPointer());
3679 }
James Y Knight9871db02019-02-05 16:42:33 +00003680 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(
3681 CGF, S.getBeginLoc(), {CopyFnTy, CopyFn}, CallArgs);
Alexey Bataevddf3db92018-04-13 17:31:06 +00003682 for (const auto &Pair : PrivatePtrs) {
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003683 Address Replacement(CGF.Builder.CreateLoad(Pair.second),
3684 CGF.getContext().getDeclAlign(Pair.first));
3685 Scope.addPrivate(Pair.first, [Replacement]() { return Replacement; });
3686 }
3687 }
3688 // Privatize all private variables except for in_reduction items.
3689 (void)Scope.Privatize();
Alexey Bataev8451efa2018-01-15 19:06:12 +00003690 if (InputInfo.NumberOfTargetItems > 0) {
3691 InputInfo.BasePointersArray = CGF.Builder.CreateConstArrayGEP(
James Y Knight751fe282019-02-09 22:22:28 +00003692 CGF.GetAddrOfLocalVar(BPVD), /*Index=*/0);
Alexey Bataev8451efa2018-01-15 19:06:12 +00003693 InputInfo.PointersArray = CGF.Builder.CreateConstArrayGEP(
James Y Knight751fe282019-02-09 22:22:28 +00003694 CGF.GetAddrOfLocalVar(PVD), /*Index=*/0);
Alexey Bataev8451efa2018-01-15 19:06:12 +00003695 InputInfo.SizesArray = CGF.Builder.CreateConstArrayGEP(
James Y Knight751fe282019-02-09 22:22:28 +00003696 CGF.GetAddrOfLocalVar(SVD), /*Index=*/0);
Alexey Bataev8451efa2018-01-15 19:06:12 +00003697 }
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003698
3699 Action.Enter(CGF);
Alexey Bataev475a7442018-01-12 19:39:11 +00003700 OMPLexicalScope LexScope(CGF, S, OMPD_task, /*EmitPreInitStmt=*/false);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003701 BodyGen(CGF);
3702 };
James Y Knight9871db02019-02-05 16:42:33 +00003703 llvm::Function *OutlinedFn = CGM.getOpenMPRuntime().emitTaskOutlinedFunction(
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003704 S, *I, *PartId, *TaskT, S.getDirectiveKind(), CodeGen, /*Tied=*/true,
3705 Data.NumberOfParts);
3706 llvm::APInt TrueOrFalse(32, S.hasClausesOfKind<OMPNowaitClause>() ? 1 : 0);
3707 IntegerLiteral IfCond(getContext(), TrueOrFalse,
3708 getContext().getIntTypeForBitwidth(32, /*Signed=*/0),
3709 SourceLocation());
3710
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003711 CGM.getOpenMPRuntime().emitTaskCall(*this, S.getBeginLoc(), S, OutlinedFn,
Alexey Bataevd2202ca2017-12-27 17:58:32 +00003712 SharedsTy, CapturedStruct, &IfCond, Data);
3713}
3714
Alexey Bataev7292c292016-04-25 12:22:29 +00003715void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &S) {
3716 // Emit outlined function for task construct.
Alexey Bataev475a7442018-01-12 19:39:11 +00003717 const CapturedStmt *CS = S.getCapturedStmt(OMPD_task);
Alexey Bataevddf3db92018-04-13 17:31:06 +00003718 Address CapturedStruct = GenerateCapturedStmtArgument(*CS);
3719 QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
Alexey Bataev1d677132015-04-22 13:57:31 +00003720 const Expr *IfCond = nullptr;
Alexey Bataev7371aa32015-09-03 08:45:56 +00003721 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
3722 if (C->getNameModifier() == OMPD_unknown ||
3723 C->getNameModifier() == OMPD_task) {
3724 IfCond = C->getCondition();
3725 break;
3726 }
Alexey Bataev1d677132015-04-22 13:57:31 +00003727 }
Alexey Bataev7292c292016-04-25 12:22:29 +00003728
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003729 OMPTaskDataTy Data;
3730 // Check if we should emit tied or untied task.
3731 Data.Tied = !S.getSingleClause<OMPUntiedClause>();
Alexey Bataev7292c292016-04-25 12:22:29 +00003732 auto &&BodyGen = [CS](CodeGenFunction &CGF, PrePostActionTy &) {
3733 CGF.EmitStmt(CS->getCapturedStmt());
3734 };
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003735 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
James Y Knight9871db02019-02-05 16:42:33 +00003736 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003737 const OMPTaskDataTy &Data) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003738 CGF.CGM.getOpenMPRuntime().emitTaskCall(CGF, S.getBeginLoc(), S, OutlinedFn,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00003739 SharedsTy, CapturedStruct, IfCond,
3740 Data);
Alexey Bataev7292c292016-04-25 12:22:29 +00003741 };
Alexey Bataev46978742020-01-30 10:46:11 -05003742 auto LPCRegion =
3743 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev475a7442018-01-12 19:39:11 +00003744 EmitOMPTaskBasedDirective(S, OMPD_task, BodyGen, TaskGen, Data);
Alexey Bataev9c2e8ee2014-07-11 11:25:16 +00003745}
3746
Alexey Bataev9f797f32015-02-05 05:57:51 +00003747void CodeGenFunction::EmitOMPTaskyieldDirective(
3748 const OMPTaskyieldDirective &S) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003749 CGM.getOpenMPRuntime().emitTaskyieldCall(*this, S.getBeginLoc());
Alexey Bataev68446b72014-07-18 07:47:19 +00003750}
3751
Alexey Bataev8f7c1b02014-12-05 04:09:23 +00003752void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003753 CGM.getOpenMPRuntime().emitBarrierCall(*this, S.getBeginLoc(), OMPD_barrier);
Alexey Bataev4d1dfea2014-07-18 09:11:51 +00003754}
3755
Alexey Bataev8b8e2022015-04-27 05:22:09 +00003756void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003757 CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc());
Alexey Bataev2df347a2014-07-18 10:17:07 +00003758}
3759
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003760void CodeGenFunction::EmitOMPTaskgroupDirective(
3761 const OMPTaskgroupDirective &S) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00003762 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
3763 Action.Enter(CGF);
Alexey Bataev3b1b8952017-07-25 15:53:26 +00003764 if (const Expr *E = S.getReductionRef()) {
3765 SmallVector<const Expr *, 4> LHSs;
3766 SmallVector<const Expr *, 4> RHSs;
3767 OMPTaskDataTy Data;
3768 for (const auto *C : S.getClausesOfKind<OMPTaskReductionClause>()) {
3769 auto IPriv = C->privates().begin();
3770 auto IRed = C->reduction_ops().begin();
3771 auto ILHS = C->lhs_exprs().begin();
3772 auto IRHS = C->rhs_exprs().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00003773 for (const Expr *Ref : C->varlists()) {
Alexey Bataev3b1b8952017-07-25 15:53:26 +00003774 Data.ReductionVars.emplace_back(Ref);
3775 Data.ReductionCopies.emplace_back(*IPriv);
3776 Data.ReductionOps.emplace_back(*IRed);
3777 LHSs.emplace_back(*ILHS);
3778 RHSs.emplace_back(*IRHS);
3779 std::advance(IPriv, 1);
3780 std::advance(IRed, 1);
3781 std::advance(ILHS, 1);
3782 std::advance(IRHS, 1);
3783 }
3784 }
3785 llvm::Value *ReductionDesc =
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003786 CGF.CGM.getOpenMPRuntime().emitTaskReductionInit(CGF, S.getBeginLoc(),
Alexey Bataev3b1b8952017-07-25 15:53:26 +00003787 LHSs, RHSs, Data);
3788 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
3789 CGF.EmitVarDecl(*VD);
3790 CGF.EmitStoreOfScalar(ReductionDesc, CGF.GetAddrOfLocalVar(VD),
3791 /*Volatile=*/false, E->getType());
3792 }
Alexey Bataev475a7442018-01-12 19:39:11 +00003793 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003794 };
Alexey Bataev475a7442018-01-12 19:39:11 +00003795 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003796 CGM.getOpenMPRuntime().emitTaskgroupRegion(*this, CodeGen, S.getBeginLoc());
Alexey Bataevc30dd2d2015-06-18 12:14:09 +00003797}
3798
Alexey Bataevcc37cc12014-11-20 04:34:54 +00003799void CodeGenFunction::EmitOMPFlushDirective(const OMPFlushDirective &S) {
Alexey Bataeve8e05de2020-02-07 12:22:23 -05003800 llvm::AtomicOrdering AO = S.getSingleClause<OMPFlushClause>()
3801 ? llvm::AtomicOrdering::NotAtomic
3802 : llvm::AtomicOrdering::AcquireRelease;
Alexey Bataevddf3db92018-04-13 17:31:06 +00003803 CGM.getOpenMPRuntime().emitFlush(
3804 *this,
3805 [&S]() -> ArrayRef<const Expr *> {
3806 if (const auto *FlushClause = S.getSingleClause<OMPFlushClause>())
3807 return llvm::makeArrayRef(FlushClause->varlist_begin(),
3808 FlushClause->varlist_end());
3809 return llvm::None;
3810 }(),
Alexey Bataeve8e05de2020-02-07 12:22:23 -05003811 S.getBeginLoc(), AO);
Alexey Bataev6125da92014-07-21 11:26:11 +00003812}
3813
Alexey Bataeve46f0fe2020-03-04 14:37:51 -05003814void CodeGenFunction::EmitOMPDepobjDirective(const OMPDepobjDirective &S) {
3815 const auto *DO = S.getSingleClause<OMPDepobjClause>();
3816 LValue DOLVal = EmitLValue(DO->getDepobj());
3817 if (const auto *DC = S.getSingleClause<OMPDependClause>()) {
3818 SmallVector<std::pair<OpenMPDependClauseKind, const Expr *>, 4>
3819 Dependencies;
3820 for (const Expr *IRef : DC->varlists())
3821 Dependencies.emplace_back(DC->getDependencyKind(), IRef);
3822 Address DepAddr = CGM.getOpenMPRuntime().emitDependClause(
Alexey Bataev63093342020-03-09 17:18:19 -04003823 *this, Dependencies, /*ForDepobj=*/true, DC->getBeginLoc()).second;
Alexey Bataeve46f0fe2020-03-04 14:37:51 -05003824 EmitStoreOfScalar(DepAddr.getPointer(), DOLVal);
Alexey Bataevb27ff4d2020-03-04 16:15:28 -05003825 return;
3826 }
3827 if (const auto *DC = S.getSingleClause<OMPDestroyClause>()) {
3828 CGM.getOpenMPRuntime().emitDestroyClause(*this, DOLVal, DC->getBeginLoc());
3829 return;
Alexey Bataeve46f0fe2020-03-04 14:37:51 -05003830 }
Alexey Bataev8d7b1182020-03-05 13:45:28 -05003831 if (const auto *UC = S.getSingleClause<OMPUpdateClause>()) {
3832 CGM.getOpenMPRuntime().emitUpdateClause(
3833 *this, DOLVal, UC->getDependencyKind(), UC->getBeginLoc());
3834 return;
3835 }
Alexey Bataeve46f0fe2020-03-04 14:37:51 -05003836}
Alexey Bataevc112e942020-02-28 09:52:15 -05003837
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003838void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
3839 const CodeGenLoopTy &CodeGenLoop,
3840 Expr *IncExpr) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003841 // Emit the loop iteration variable.
Alexey Bataevddf3db92018-04-13 17:31:06 +00003842 const auto *IVExpr = cast<DeclRefExpr>(S.getIterationVariable());
3843 const auto *IVDecl = cast<VarDecl>(IVExpr->getDecl());
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003844 EmitVarDecl(*IVDecl);
3845
3846 // Emit the iterations count variable.
3847 // If it is not a variable, Sema decided to calculate iterations count on each
3848 // iteration (e.g., it is foldable into a constant).
Alexey Bataevddf3db92018-04-13 17:31:06 +00003849 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003850 EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
3851 // Emit calculation of the iterations count.
3852 EmitIgnoredExpr(S.getCalcLastIteration());
3853 }
3854
Alexey Bataevddf3db92018-04-13 17:31:06 +00003855 CGOpenMPRuntime &RT = CGM.getOpenMPRuntime();
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003856
Carlo Bertolli962bb802017-01-03 18:24:42 +00003857 bool HasLastprivateClause = false;
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003858 // Check pre-condition.
3859 {
Alexey Bataev5a3af132016-03-29 08:58:54 +00003860 OMPLoopScope PreInitScope(*this, S);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003861 // Skip the entire loop if we don't meet the precondition.
3862 // If the condition constant folds and can be elided, avoid emitting the
3863 // whole loop.
3864 bool CondConstant;
3865 llvm::BasicBlock *ContBlock = nullptr;
3866 if (ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
3867 if (!CondConstant)
3868 return;
3869 } else {
Alexey Bataevddf3db92018-04-13 17:31:06 +00003870 llvm::BasicBlock *ThenBlock = createBasicBlock("omp.precond.then");
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003871 ContBlock = createBasicBlock("omp.precond.end");
3872 emitPreCond(*this, S, S.getPreCond(), ThenBlock, ContBlock,
3873 getProfileCount(&S));
3874 EmitBlock(ThenBlock);
3875 incrementProfileCounter(&S);
3876 }
3877
Alexey Bataev617db5f2017-12-04 15:38:33 +00003878 emitAlignedClause(*this, S);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003879 // Emit 'then' code.
3880 {
3881 // Emit helper vars inits.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003882
3883 LValue LB = EmitOMPHelperVar(
3884 *this, cast<DeclRefExpr>(
3885 (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
3886 ? S.getCombinedLowerBoundVariable()
3887 : S.getLowerBoundVariable())));
3888 LValue UB = EmitOMPHelperVar(
3889 *this, cast<DeclRefExpr>(
3890 (isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
3891 ? S.getCombinedUpperBoundVariable()
3892 : S.getUpperBoundVariable())));
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003893 LValue ST =
3894 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getStrideVariable()));
3895 LValue IL =
3896 EmitOMPHelperVar(*this, cast<DeclRefExpr>(S.getIsLastIterVariable()));
3897
3898 OMPPrivateScope LoopScope(*this);
Carlo Bertolli962bb802017-01-03 18:24:42 +00003899 if (EmitOMPFirstprivateClause(S, LoopScope)) {
Alexey Bataev617db5f2017-12-04 15:38:33 +00003900 // Emit implicit barrier to synchronize threads and avoid data races
3901 // on initialization of firstprivate variables and post-update of
Carlo Bertolli962bb802017-01-03 18:24:42 +00003902 // lastprivate variables.
3903 CGM.getOpenMPRuntime().emitBarrierCall(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003904 *this, S.getBeginLoc(), OMPD_unknown, /*EmitChecks=*/false,
Alexey Bataev617db5f2017-12-04 15:38:33 +00003905 /*ForceSimpleCall=*/true);
Carlo Bertolli962bb802017-01-03 18:24:42 +00003906 }
3907 EmitOMPPrivateClause(S, LoopScope);
Alexey Bataev617db5f2017-12-04 15:38:33 +00003908 if (isOpenMPSimdDirective(S.getDirectiveKind()) &&
Alexey Bataev999277a2017-12-06 14:31:09 +00003909 !isOpenMPParallelDirective(S.getDirectiveKind()) &&
3910 !isOpenMPTeamsDirective(S.getDirectiveKind()))
Alexey Bataev617db5f2017-12-04 15:38:33 +00003911 EmitOMPReductionClauseInit(S, LoopScope);
Carlo Bertolli962bb802017-01-03 18:24:42 +00003912 HasLastprivateClause = EmitOMPLastprivateClauseInit(S, LoopScope);
Alexey Bataev5dff95c2016-04-22 03:56:56 +00003913 EmitOMPPrivateLoopCounters(S, LoopScope);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003914 (void)LoopScope.Privatize();
Alexey Bataev60705422018-10-30 15:50:12 +00003915 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
3916 CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(*this, S);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003917
3918 // Detect the distribute schedule kind and chunk.
3919 llvm::Value *Chunk = nullptr;
3920 OpenMPDistScheduleClauseKind ScheduleKind = OMPC_DIST_SCHEDULE_unknown;
Alexey Bataevddf3db92018-04-13 17:31:06 +00003921 if (const auto *C = S.getSingleClause<OMPDistScheduleClause>()) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003922 ScheduleKind = C->getDistScheduleKind();
Alexey Bataevddf3db92018-04-13 17:31:06 +00003923 if (const Expr *Ch = C->getChunkSize()) {
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003924 Chunk = EmitScalarExpr(Ch);
3925 Chunk = EmitScalarConversion(Chunk, Ch->getType(),
Alexey Bataev617db5f2017-12-04 15:38:33 +00003926 S.getIterationVariable()->getType(),
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003927 S.getBeginLoc());
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003928 }
Gheorghe-Teodor Bercea02650d42018-09-27 19:22:56 +00003929 } else {
3930 // Default behaviour for dist_schedule clause.
3931 CGM.getOpenMPRuntime().getDefaultDistScheduleAndChunk(
3932 *this, S, ScheduleKind, Chunk);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003933 }
3934 const unsigned IVSize = getContext().getTypeSize(IVExpr->getType());
3935 const bool IVSigned = IVExpr->getType()->hasSignedIntegerRepresentation();
3936
3937 // OpenMP [2.10.8, distribute Construct, Description]
3938 // If dist_schedule is specified, kind must be static. If specified,
3939 // iterations are divided into chunks of size chunk_size, chunks are
3940 // assigned to the teams of the league in a round-robin fashion in the
3941 // order of the team number. When no chunk_size is specified, the
3942 // iteration space is divided into chunks that are approximately equal
3943 // in size, and at most one chunk is distributed to each team of the
3944 // league. The size of the chunks is unspecified in this case.
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00003945 bool StaticChunked = RT.isStaticChunked(
3946 ScheduleKind, /* Chunked */ Chunk != nullptr) &&
3947 isOpenMPLoopBoundSharingDirective(S.getDirectiveKind());
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003948 if (RT.isStaticNonchunked(ScheduleKind,
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00003949 /* Chunked */ Chunk != nullptr) ||
3950 StaticChunked) {
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003951 CGOpenMPRuntime::StaticRTInput StaticInit(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08003952 IVSize, IVSigned, /* Ordered = */ false, IL.getAddress(*this),
3953 LB.getAddress(*this), UB.getAddress(*this), ST.getAddress(*this),
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00003954 StaticChunked ? Chunk : nullptr);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00003955 RT.emitDistributeStaticInit(*this, S.getBeginLoc(), ScheduleKind,
Alexey Bataev0f87dbe2017-08-14 17:56:13 +00003956 StaticInit);
Alexey Bataevddf3db92018-04-13 17:31:06 +00003957 JumpDest LoopExit =
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003958 getJumpDestInCurrentScope(createBasicBlock("omp.loop.exit"));
3959 // UB = min(UB, GlobalUB);
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003960 EmitIgnoredExpr(isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
3961 ? S.getCombinedEnsureUpperBound()
3962 : S.getEnsureUpperBound());
Carlo Bertollifc35ad22016-03-07 16:04:49 +00003963 // IV = LB;
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003964 EmitIgnoredExpr(isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
3965 ? S.getCombinedInit()
3966 : S.getInit());
3967
Alexey Bataevddf3db92018-04-13 17:31:06 +00003968 const Expr *Cond =
3969 isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
3970 ? S.getCombinedCond()
3971 : S.getCond();
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00003972
Gheorghe-Teodor Berceae9256762018-10-29 15:45:47 +00003973 if (StaticChunked)
3974 Cond = S.getCombinedDistCond();
3975
3976 // For static unchunked schedules generate:
3977 //
3978 // 1. For distribute alone, codegen
3979 // while (idx <= UB) {
3980 // BODY;
3981 // ++idx;
3982 // }
3983 //
3984 // 2. When combined with 'for' (e.g. as in 'distribute parallel for')
3985 // while (idx <= UB) {
3986 // <CodeGen rest of pragma>(LB, UB);
3987 // idx += ST;
3988 // }
3989 //
3990 // For static chunk one schedule generate:
3991 //
3992 // while (IV <= GlobalUB) {
3993 // <CodeGen rest of pragma>(LB, UB);
3994 // LB += ST;
3995 // UB += ST;
3996 // UB = min(UB, GlobalUB);
3997 // IV = LB;
3998 // }
3999 //
Alexey Bataev779a1802019-12-06 12:21:31 -05004000 emitCommonSimdLoop(
4001 *this, S,
4002 [&S](CodeGenFunction &CGF, PrePostActionTy &) {
4003 if (isOpenMPSimdDirective(S.getDirectiveKind()))
4004 CGF.EmitOMPSimdInit(S, /*IsMonotonic=*/true);
4005 },
4006 [&S, &LoopScope, Cond, IncExpr, LoopExit, &CodeGenLoop,
4007 StaticChunked](CodeGenFunction &CGF, PrePostActionTy &) {
4008 CGF.EmitOMPInnerLoop(
4009 S, LoopScope.requiresCleanups(), Cond, IncExpr,
4010 [&S, LoopExit, &CodeGenLoop](CodeGenFunction &CGF) {
4011 CodeGenLoop(CGF, S, LoopExit);
4012 },
4013 [&S, StaticChunked](CodeGenFunction &CGF) {
4014 if (StaticChunked) {
4015 CGF.EmitIgnoredExpr(S.getCombinedNextLowerBound());
4016 CGF.EmitIgnoredExpr(S.getCombinedNextUpperBound());
4017 CGF.EmitIgnoredExpr(S.getCombinedEnsureUpperBound());
4018 CGF.EmitIgnoredExpr(S.getCombinedInit());
4019 }
4020 });
4021 });
Carlo Bertollifc35ad22016-03-07 16:04:49 +00004022 EmitBlock(LoopExit.getBlock());
4023 // Tell the runtime we are done.
Alexey Bataevc33ba8c2020-01-17 14:05:40 -05004024 RT.emitForStaticFinish(*this, S.getEndLoc(), S.getDirectiveKind());
Carlo Bertollifc35ad22016-03-07 16:04:49 +00004025 } else {
4026 // Emit the outer loop, which requests its work chunk [LB..UB] from
4027 // runtime and runs the inner loop to process it.
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00004028 const OMPLoopArguments LoopArguments = {
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004029 LB.getAddress(*this), UB.getAddress(*this), ST.getAddress(*this),
4030 IL.getAddress(*this), Chunk};
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00004031 EmitOMPDistributeOuterLoop(ScheduleKind, S, LoopScope, LoopArguments,
4032 CodeGenLoop);
Carlo Bertollifc35ad22016-03-07 16:04:49 +00004033 }
Alexey Bataev617db5f2017-12-04 15:38:33 +00004034 if (isOpenMPSimdDirective(S.getDirectiveKind())) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00004035 EmitOMPSimdFinal(S, [IL, &S](CodeGenFunction &CGF) {
Alexey Bataev617db5f2017-12-04 15:38:33 +00004036 return CGF.Builder.CreateIsNotNull(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004037 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
Alexey Bataev617db5f2017-12-04 15:38:33 +00004038 });
4039 }
Carlo Bertollibeda2142018-02-22 19:38:14 +00004040 if (isOpenMPSimdDirective(S.getDirectiveKind()) &&
4041 !isOpenMPParallelDirective(S.getDirectiveKind()) &&
4042 !isOpenMPTeamsDirective(S.getDirectiveKind())) {
Jonas Hahnfeld5aaaece2018-10-02 19:12:47 +00004043 EmitOMPReductionClauseFinal(S, OMPD_simd);
Carlo Bertollibeda2142018-02-22 19:38:14 +00004044 // Emit post-update of the reduction variables if IsLastIter != 0.
4045 emitPostUpdateForReductionClause(
Alexey Bataevddf3db92018-04-13 17:31:06 +00004046 *this, S, [IL, &S](CodeGenFunction &CGF) {
Carlo Bertollibeda2142018-02-22 19:38:14 +00004047 return CGF.Builder.CreateIsNotNull(
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004048 CGF.EmitLoadOfScalar(IL, S.getBeginLoc()));
Carlo Bertollibeda2142018-02-22 19:38:14 +00004049 });
Alexey Bataev617db5f2017-12-04 15:38:33 +00004050 }
Carlo Bertolli962bb802017-01-03 18:24:42 +00004051 // Emit final copy of the lastprivate variables if IsLastIter != 0.
Alexey Bataev617db5f2017-12-04 15:38:33 +00004052 if (HasLastprivateClause) {
Carlo Bertolli962bb802017-01-03 18:24:42 +00004053 EmitOMPLastprivateClauseFinal(
4054 S, /*NoFinals=*/false,
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004055 Builder.CreateIsNotNull(EmitLoadOfScalar(IL, S.getBeginLoc())));
Alexey Bataev617db5f2017-12-04 15:38:33 +00004056 }
Carlo Bertollifc35ad22016-03-07 16:04:49 +00004057 }
4058
4059 // We're now done with the loop, so jump to the continuation block.
4060 if (ContBlock) {
4061 EmitBranch(ContBlock);
4062 EmitBlock(ContBlock, true);
4063 }
4064 }
4065}
4066
Carlo Bertolli6200a3d2015-12-14 14:51:25 +00004067void CodeGenFunction::EmitOMPDistributeDirective(
4068 const OMPDistributeDirective &S) {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004069 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00004070 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
Carlo Bertollifc35ad22016-03-07 16:04:49 +00004071 };
Alexey Bataev475a7442018-01-12 19:39:11 +00004072 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataev10a54312017-11-27 16:54:08 +00004073 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_distribute, CodeGen);
Carlo Bertolli6200a3d2015-12-14 14:51:25 +00004074}
4075
Alexey Bataev5f600d62015-09-29 03:48:57 +00004076static llvm::Function *emitOutlinedOrderedFunction(CodeGenModule &CGM,
Alexey Bataevc33ba8c2020-01-17 14:05:40 -05004077 const CapturedStmt *S,
4078 SourceLocation Loc) {
Alexey Bataev5f600d62015-09-29 03:48:57 +00004079 CodeGenFunction CGF(CGM, /*suppressNewContext=*/true);
4080 CodeGenFunction::CGCapturedStmtInfo CapStmtInfo;
4081 CGF.CapturedStmtInfo = &CapStmtInfo;
Alexey Bataevc33ba8c2020-01-17 14:05:40 -05004082 llvm::Function *Fn = CGF.GenerateOpenMPCapturedStmtFunction(*S, Loc);
Alexey Bataevc0f879b2018-04-10 20:10:53 +00004083 Fn->setDoesNotRecurse();
Alexey Bataev5f600d62015-09-29 03:48:57 +00004084 return Fn;
4085}
4086
Alexey Bataev98eb6e32015-04-22 11:15:40 +00004087void CodeGenFunction::EmitOMPOrderedDirective(const OMPOrderedDirective &S) {
Alexey Bataev475a7442018-01-12 19:39:11 +00004088 if (S.hasClausesOfKind<OMPDependClause>()) {
4089 assert(!S.getAssociatedStmt() &&
4090 "No associated statement must be in ordered depend construct.");
Alexey Bataev8b427062016-05-25 12:36:08 +00004091 for (const auto *DC : S.getClausesOfKind<OMPDependClause>())
4092 CGM.getOpenMPRuntime().emitDoacrossOrdered(*this, DC);
Alexey Bataev8ef31412015-12-18 07:58:25 +00004093 return;
Alexey Bataev8b427062016-05-25 12:36:08 +00004094 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00004095 const auto *C = S.getSingleClause<OMPSIMDClause>();
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004096 auto &&CodeGen = [&S, C, this](CodeGenFunction &CGF,
4097 PrePostActionTy &Action) {
Alexey Bataev475a7442018-01-12 19:39:11 +00004098 const CapturedStmt *CS = S.getInnermostCapturedStmt();
Alexey Bataev5f600d62015-09-29 03:48:57 +00004099 if (C) {
Alexey Bataev5f600d62015-09-29 03:48:57 +00004100 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
4101 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
Alexey Bataevc33ba8c2020-01-17 14:05:40 -05004102 llvm::Function *OutlinedFn =
4103 emitOutlinedOrderedFunction(CGM, CS, S.getBeginLoc());
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004104 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, S.getBeginLoc(),
Alexey Bataev3c595a62017-08-14 15:01:03 +00004105 OutlinedFn, CapturedVars);
Alexey Bataev5f600d62015-09-29 03:48:57 +00004106 } else {
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004107 Action.Enter(CGF);
Alexey Bataev475a7442018-01-12 19:39:11 +00004108 CGF.EmitStmt(CS->getCapturedStmt());
Alexey Bataev5f600d62015-09-29 03:48:57 +00004109 }
Alexey Bataev98eb6e32015-04-22 11:15:40 +00004110 };
Alexey Bataev475a7442018-01-12 19:39:11 +00004111 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004112 CGM.getOpenMPRuntime().emitOrderedRegion(*this, CodeGen, S.getBeginLoc(), !C);
Alexey Bataev9fb6e642014-07-22 06:45:04 +00004113}
4114
Alexey Bataevb57056f2015-01-22 06:17:56 +00004115static llvm::Value *convertToScalarValue(CodeGenFunction &CGF, RValue Val,
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004116 QualType SrcType, QualType DestType,
4117 SourceLocation Loc) {
Alexey Bataevb57056f2015-01-22 06:17:56 +00004118 assert(CGF.hasScalarEvaluationKind(DestType) &&
4119 "DestType must have scalar evaluation kind.");
4120 assert(!Val.isAggregate() && "Must be a scalar or complex.");
Alexey Bataevddf3db92018-04-13 17:31:06 +00004121 return Val.isScalar() ? CGF.EmitScalarConversion(Val.getScalarVal(), SrcType,
4122 DestType, Loc)
4123 : CGF.EmitComplexToScalarConversion(
4124 Val.getComplexVal(), SrcType, DestType, Loc);
Alexey Bataevb57056f2015-01-22 06:17:56 +00004125}
4126
4127static CodeGenFunction::ComplexPairTy
4128convertToComplexValue(CodeGenFunction &CGF, RValue Val, QualType SrcType,
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004129 QualType DestType, SourceLocation Loc) {
Alexey Bataevb57056f2015-01-22 06:17:56 +00004130 assert(CGF.getEvaluationKind(DestType) == TEK_Complex &&
4131 "DestType must have complex evaluation kind.");
4132 CodeGenFunction::ComplexPairTy ComplexVal;
4133 if (Val.isScalar()) {
4134 // Convert the input element to the element type of the complex.
Alexey Bataevddf3db92018-04-13 17:31:06 +00004135 QualType DestElementType =
4136 DestType->castAs<ComplexType>()->getElementType();
4137 llvm::Value *ScalarVal = CGF.EmitScalarConversion(
4138 Val.getScalarVal(), SrcType, DestElementType, Loc);
Alexey Bataevb57056f2015-01-22 06:17:56 +00004139 ComplexVal = CodeGenFunction::ComplexPairTy(
4140 ScalarVal, llvm::Constant::getNullValue(ScalarVal->getType()));
4141 } else {
4142 assert(Val.isComplex() && "Must be a scalar or complex.");
Alexey Bataevddf3db92018-04-13 17:31:06 +00004143 QualType SrcElementType = SrcType->castAs<ComplexType>()->getElementType();
4144 QualType DestElementType =
4145 DestType->castAs<ComplexType>()->getElementType();
Alexey Bataevb57056f2015-01-22 06:17:56 +00004146 ComplexVal.first = CGF.EmitScalarConversion(
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004147 Val.getComplexVal().first, SrcElementType, DestElementType, Loc);
Alexey Bataevb57056f2015-01-22 06:17:56 +00004148 ComplexVal.second = CGF.EmitScalarConversion(
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004149 Val.getComplexVal().second, SrcElementType, DestElementType, Loc);
Alexey Bataevb57056f2015-01-22 06:17:56 +00004150 }
4151 return ComplexVal;
4152}
4153
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004154static void emitSimpleAtomicStore(CodeGenFunction &CGF, llvm::AtomicOrdering AO,
Alexey Bataev5e018f92015-04-23 06:35:10 +00004155 LValue LVal, RValue RVal) {
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004156 if (LVal.isGlobalReg())
Alexey Bataev5e018f92015-04-23 06:35:10 +00004157 CGF.EmitStoreThroughGlobalRegLValue(RVal, LVal);
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004158 else
4159 CGF.EmitAtomicStore(RVal, LVal, AO, LVal.isVolatile(), /*isInit=*/false);
4160}
4161
4162static RValue emitSimpleAtomicLoad(CodeGenFunction &CGF,
4163 llvm::AtomicOrdering AO, LValue LVal,
4164 SourceLocation Loc) {
4165 if (LVal.isGlobalReg())
4166 return CGF.EmitLoadOfLValue(LVal, Loc);
4167 return CGF.EmitAtomicLoad(
4168 LVal, Loc, llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO),
4169 LVal.isVolatile());
Alexey Bataev5e018f92015-04-23 06:35:10 +00004170}
4171
Alexey Bataev8524d152016-01-21 12:35:58 +00004172void CodeGenFunction::emitOMPSimpleStore(LValue LVal, RValue RVal,
4173 QualType RValTy, SourceLocation Loc) {
4174 switch (getEvaluationKind(LVal.getType())) {
Alexey Bataev5e018f92015-04-23 06:35:10 +00004175 case TEK_Scalar:
Alexey Bataev8524d152016-01-21 12:35:58 +00004176 EmitStoreThroughLValue(RValue::get(convertToScalarValue(
4177 *this, RVal, RValTy, LVal.getType(), Loc)),
4178 LVal);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004179 break;
4180 case TEK_Complex:
Alexey Bataev8524d152016-01-21 12:35:58 +00004181 EmitStoreOfComplex(
4182 convertToComplexValue(*this, RVal, RValTy, LVal.getType(), Loc), LVal,
Alexey Bataev5e018f92015-04-23 06:35:10 +00004183 /*isInit=*/false);
4184 break;
4185 case TEK_Aggregate:
4186 llvm_unreachable("Must be a scalar or complex.");
4187 }
4188}
4189
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004190static void emitOMPAtomicReadExpr(CodeGenFunction &CGF, llvm::AtomicOrdering AO,
Alexey Bataevb57056f2015-01-22 06:17:56 +00004191 const Expr *X, const Expr *V,
4192 SourceLocation Loc) {
4193 // v = x;
4194 assert(V->isLValue() && "V of 'omp atomic read' is not lvalue");
4195 assert(X->isLValue() && "X of 'omp atomic read' is not lvalue");
4196 LValue XLValue = CGF.EmitLValue(X);
4197 LValue VLValue = CGF.EmitLValue(V);
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004198 RValue Res = emitSimpleAtomicLoad(CGF, AO, XLValue, Loc);
4199 // OpenMP, 2.17.7, atomic Construct
4200 // If the read or capture clause is specified and the acquire, acq_rel, or
4201 // seq_cst clause is specified then the strong flush on exit from the atomic
4202 // operation is also an acquire flush.
4203 switch (AO) {
4204 case llvm::AtomicOrdering::Acquire:
4205 case llvm::AtomicOrdering::AcquireRelease:
4206 case llvm::AtomicOrdering::SequentiallyConsistent:
4207 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
4208 llvm::AtomicOrdering::Acquire);
4209 break;
4210 case llvm::AtomicOrdering::Monotonic:
4211 case llvm::AtomicOrdering::Release:
4212 break;
4213 case llvm::AtomicOrdering::NotAtomic:
4214 case llvm::AtomicOrdering::Unordered:
4215 llvm_unreachable("Unexpected ordering.");
4216 }
Alexey Bataev8524d152016-01-21 12:35:58 +00004217 CGF.emitOMPSimpleStore(VLValue, Res, X->getType().getNonReferenceType(), Loc);
Alexey Bataevf117f2c2020-01-28 11:19:45 -05004218 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, V);
Alexey Bataevb57056f2015-01-22 06:17:56 +00004219}
4220
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004221static void emitOMPAtomicWriteExpr(CodeGenFunction &CGF,
4222 llvm::AtomicOrdering AO, const Expr *X,
4223 const Expr *E, SourceLocation Loc) {
Alexey Bataevb8329262015-02-27 06:33:30 +00004224 // x = expr;
4225 assert(X->isLValue() && "X of 'omp atomic write' is not lvalue");
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004226 emitSimpleAtomicStore(CGF, AO, CGF.EmitLValue(X), CGF.EmitAnyExpr(E));
Alexey Bataevf117f2c2020-01-28 11:19:45 -05004227 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, X);
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004228 // OpenMP, 2.17.7, atomic Construct
4229 // If the write, update, or capture clause is specified and the release,
4230 // acq_rel, or seq_cst clause is specified then the strong flush on entry to
4231 // the atomic operation is also a release flush.
4232 switch (AO) {
4233 case llvm::AtomicOrdering::Release:
4234 case llvm::AtomicOrdering::AcquireRelease:
4235 case llvm::AtomicOrdering::SequentiallyConsistent:
4236 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
4237 llvm::AtomicOrdering::Release);
4238 break;
4239 case llvm::AtomicOrdering::Acquire:
4240 case llvm::AtomicOrdering::Monotonic:
4241 break;
4242 case llvm::AtomicOrdering::NotAtomic:
4243 case llvm::AtomicOrdering::Unordered:
4244 llvm_unreachable("Unexpected ordering.");
4245 }
Alexey Bataevb8329262015-02-27 06:33:30 +00004246}
4247
Benjamin Kramer439ee9d2015-05-01 13:59:53 +00004248static std::pair<bool, RValue> emitOMPAtomicRMW(CodeGenFunction &CGF, LValue X,
4249 RValue Update,
4250 BinaryOperatorKind BO,
4251 llvm::AtomicOrdering AO,
4252 bool IsXLHSInRHSPart) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00004253 ASTContext &Context = CGF.getContext();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004254 // Allow atomicrmw only if 'x' and 'update' are integer values, lvalue for 'x'
Alexey Bataevb4505a72015-03-30 05:20:59 +00004255 // expression is simple and atomic is allowed for the given type for the
4256 // target platform.
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004257 if (BO == BO_Comma || !Update.isScalar() ||
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004258 !Update.getScalarVal()->getType()->isIntegerTy() || !X.isSimple() ||
4259 (!isa<llvm::ConstantInt>(Update.getScalarVal()) &&
4260 (Update.getScalarVal()->getType() !=
4261 X.getAddress(CGF).getElementType())) ||
4262 !X.getAddress(CGF).getElementType()->isIntegerTy() ||
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004263 !Context.getTargetInfo().hasBuiltinAtomic(
4264 Context.getTypeSize(X.getType()), Context.toBits(X.getAlignment())))
Alexey Bataev5e018f92015-04-23 06:35:10 +00004265 return std::make_pair(false, RValue::get(nullptr));
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004266
4267 llvm::AtomicRMWInst::BinOp RMWOp;
4268 switch (BO) {
4269 case BO_Add:
4270 RMWOp = llvm::AtomicRMWInst::Add;
4271 break;
4272 case BO_Sub:
4273 if (!IsXLHSInRHSPart)
Alexey Bataev5e018f92015-04-23 06:35:10 +00004274 return std::make_pair(false, RValue::get(nullptr));
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004275 RMWOp = llvm::AtomicRMWInst::Sub;
4276 break;
4277 case BO_And:
4278 RMWOp = llvm::AtomicRMWInst::And;
4279 break;
4280 case BO_Or:
4281 RMWOp = llvm::AtomicRMWInst::Or;
4282 break;
4283 case BO_Xor:
4284 RMWOp = llvm::AtomicRMWInst::Xor;
4285 break;
4286 case BO_LT:
4287 RMWOp = X.getType()->hasSignedIntegerRepresentation()
4288 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Min
4289 : llvm::AtomicRMWInst::Max)
4290 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMin
4291 : llvm::AtomicRMWInst::UMax);
4292 break;
4293 case BO_GT:
4294 RMWOp = X.getType()->hasSignedIntegerRepresentation()
4295 ? (IsXLHSInRHSPart ? llvm::AtomicRMWInst::Max
4296 : llvm::AtomicRMWInst::Min)
4297 : (IsXLHSInRHSPart ? llvm::AtomicRMWInst::UMax
4298 : llvm::AtomicRMWInst::UMin);
4299 break;
Alexey Bataev5e018f92015-04-23 06:35:10 +00004300 case BO_Assign:
4301 RMWOp = llvm::AtomicRMWInst::Xchg;
4302 break;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004303 case BO_Mul:
4304 case BO_Div:
4305 case BO_Rem:
4306 case BO_Shl:
4307 case BO_Shr:
4308 case BO_LAnd:
4309 case BO_LOr:
Alexey Bataev5e018f92015-04-23 06:35:10 +00004310 return std::make_pair(false, RValue::get(nullptr));
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004311 case BO_PtrMemD:
4312 case BO_PtrMemI:
4313 case BO_LE:
4314 case BO_GE:
4315 case BO_EQ:
4316 case BO_NE:
Richard Smithc70f1d62017-12-14 15:16:18 +00004317 case BO_Cmp:
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004318 case BO_AddAssign:
4319 case BO_SubAssign:
4320 case BO_AndAssign:
4321 case BO_OrAssign:
4322 case BO_XorAssign:
4323 case BO_MulAssign:
4324 case BO_DivAssign:
4325 case BO_RemAssign:
4326 case BO_ShlAssign:
4327 case BO_ShrAssign:
4328 case BO_Comma:
4329 llvm_unreachable("Unsupported atomic update operation");
4330 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00004331 llvm::Value *UpdateVal = Update.getScalarVal();
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004332 if (auto *IC = dyn_cast<llvm::ConstantInt>(UpdateVal)) {
4333 UpdateVal = CGF.Builder.CreateIntCast(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004334 IC, X.getAddress(CGF).getElementType(),
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004335 X.getType()->hasSignedIntegerRepresentation());
4336 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00004337 llvm::Value *Res =
Akira Hatanakaf139ae32019-12-03 15:17:01 -08004338 CGF.Builder.CreateAtomicRMW(RMWOp, X.getPointer(CGF), UpdateVal, AO);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004339 return std::make_pair(true, RValue::get(Res));
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004340}
4341
Alexey Bataev5e018f92015-04-23 06:35:10 +00004342std::pair<bool, RValue> CodeGenFunction::EmitOMPAtomicSimpleUpdateExpr(
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004343 LValue X, RValue E, BinaryOperatorKind BO, bool IsXLHSInRHSPart,
4344 llvm::AtomicOrdering AO, SourceLocation Loc,
Alexey Bataevddf3db92018-04-13 17:31:06 +00004345 const llvm::function_ref<RValue(RValue)> CommonGen) {
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004346 // Update expressions are allowed to have the following forms:
4347 // x binop= expr; -> xrval + expr;
4348 // x++, ++x -> xrval + 1;
4349 // x--, --x -> xrval - 1;
4350 // x = x binop expr; -> xrval binop expr
4351 // x = expr Op x; - > expr binop xrval;
Alexey Bataev5e018f92015-04-23 06:35:10 +00004352 auto Res = emitOMPAtomicRMW(*this, X, E, BO, AO, IsXLHSInRHSPart);
4353 if (!Res.first) {
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004354 if (X.isGlobalReg()) {
4355 // Emit an update expression: 'xrval' binop 'expr' or 'expr' binop
4356 // 'xrval'.
4357 EmitStoreThroughLValue(CommonGen(EmitLoadOfLValue(X, Loc)), X);
4358 } else {
4359 // Perform compare-and-swap procedure.
4360 EmitAtomicUpdate(X, AO, CommonGen, X.getType().isVolatileQualified());
Alexey Bataevb4505a72015-03-30 05:20:59 +00004361 }
4362 }
Alexey Bataev5e018f92015-04-23 06:35:10 +00004363 return Res;
Alexey Bataevb4505a72015-03-30 05:20:59 +00004364}
4365
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004366static void emitOMPAtomicUpdateExpr(CodeGenFunction &CGF,
4367 llvm::AtomicOrdering AO, const Expr *X,
4368 const Expr *E, const Expr *UE,
4369 bool IsXLHSInRHSPart, SourceLocation Loc) {
Alexey Bataevb4505a72015-03-30 05:20:59 +00004370 assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) &&
4371 "Update expr in 'atomic update' must be a binary operator.");
Alexey Bataevddf3db92018-04-13 17:31:06 +00004372 const auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts());
Alexey Bataevb4505a72015-03-30 05:20:59 +00004373 // Update expressions are allowed to have the following forms:
4374 // x binop= expr; -> xrval + expr;
4375 // x++, ++x -> xrval + 1;
4376 // x--, --x -> xrval - 1;
4377 // x = x binop expr; -> xrval binop expr
4378 // x = expr Op x; - > expr binop xrval;
Alexey Bataev794ba0d2015-04-10 10:43:45 +00004379 assert(X->isLValue() && "X of 'omp atomic update' is not lvalue");
Alexey Bataevb4505a72015-03-30 05:20:59 +00004380 LValue XLValue = CGF.EmitLValue(X);
4381 RValue ExprRValue = CGF.EmitAnyExpr(E);
Alexey Bataevddf3db92018-04-13 17:31:06 +00004382 const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
4383 const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
4384 const OpaqueValueExpr *XRValExpr = IsXLHSInRHSPart ? LHS : RHS;
4385 const OpaqueValueExpr *ERValExpr = IsXLHSInRHSPart ? RHS : LHS;
4386 auto &&Gen = [&CGF, UE, ExprRValue, XRValExpr, ERValExpr](RValue XRValue) {
4387 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
4388 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
4389 return CGF.EmitAnyExpr(UE);
4390 };
Alexey Bataev5e018f92015-04-23 06:35:10 +00004391 (void)CGF.EmitOMPAtomicSimpleUpdateExpr(
4392 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
Alexey Bataevf117f2c2020-01-28 11:19:45 -05004393 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, X);
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004394 // OpenMP, 2.17.7, atomic Construct
4395 // If the write, update, or capture clause is specified and the release,
4396 // acq_rel, or seq_cst clause is specified then the strong flush on entry to
4397 // the atomic operation is also a release flush.
4398 switch (AO) {
4399 case llvm::AtomicOrdering::Release:
4400 case llvm::AtomicOrdering::AcquireRelease:
4401 case llvm::AtomicOrdering::SequentiallyConsistent:
4402 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
4403 llvm::AtomicOrdering::Release);
4404 break;
4405 case llvm::AtomicOrdering::Acquire:
4406 case llvm::AtomicOrdering::Monotonic:
4407 break;
4408 case llvm::AtomicOrdering::NotAtomic:
4409 case llvm::AtomicOrdering::Unordered:
4410 llvm_unreachable("Unexpected ordering.");
4411 }
Alexey Bataev5e018f92015-04-23 06:35:10 +00004412}
4413
4414static RValue convertToType(CodeGenFunction &CGF, RValue Value,
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004415 QualType SourceType, QualType ResType,
4416 SourceLocation Loc) {
Alexey Bataev5e018f92015-04-23 06:35:10 +00004417 switch (CGF.getEvaluationKind(ResType)) {
4418 case TEK_Scalar:
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004419 return RValue::get(
4420 convertToScalarValue(CGF, Value, SourceType, ResType, Loc));
Alexey Bataev5e018f92015-04-23 06:35:10 +00004421 case TEK_Complex: {
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004422 auto Res = convertToComplexValue(CGF, Value, SourceType, ResType, Loc);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004423 return RValue::getComplex(Res.first, Res.second);
4424 }
4425 case TEK_Aggregate:
4426 break;
4427 }
4428 llvm_unreachable("Must be a scalar or complex.");
4429}
4430
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004431static void emitOMPAtomicCaptureExpr(CodeGenFunction &CGF,
4432 llvm::AtomicOrdering AO,
Alexey Bataev5e018f92015-04-23 06:35:10 +00004433 bool IsPostfixUpdate, const Expr *V,
4434 const Expr *X, const Expr *E,
4435 const Expr *UE, bool IsXLHSInRHSPart,
4436 SourceLocation Loc) {
4437 assert(X->isLValue() && "X of 'omp atomic capture' is not lvalue");
4438 assert(V->isLValue() && "V of 'omp atomic capture' is not lvalue");
4439 RValue NewVVal;
4440 LValue VLValue = CGF.EmitLValue(V);
4441 LValue XLValue = CGF.EmitLValue(X);
4442 RValue ExprRValue = CGF.EmitAnyExpr(E);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004443 QualType NewVValType;
4444 if (UE) {
4445 // 'x' is updated with some additional value.
4446 assert(isa<BinaryOperator>(UE->IgnoreImpCasts()) &&
4447 "Update expr in 'atomic capture' must be a binary operator.");
Alexey Bataevddf3db92018-04-13 17:31:06 +00004448 const auto *BOUE = cast<BinaryOperator>(UE->IgnoreImpCasts());
Alexey Bataev5e018f92015-04-23 06:35:10 +00004449 // Update expressions are allowed to have the following forms:
4450 // x binop= expr; -> xrval + expr;
4451 // x++, ++x -> xrval + 1;
4452 // x--, --x -> xrval - 1;
4453 // x = x binop expr; -> xrval binop expr
4454 // x = expr Op x; - > expr binop xrval;
Alexey Bataevddf3db92018-04-13 17:31:06 +00004455 const auto *LHS = cast<OpaqueValueExpr>(BOUE->getLHS()->IgnoreImpCasts());
4456 const auto *RHS = cast<OpaqueValueExpr>(BOUE->getRHS()->IgnoreImpCasts());
4457 const OpaqueValueExpr *XRValExpr = IsXLHSInRHSPart ? LHS : RHS;
Alexey Bataev5e018f92015-04-23 06:35:10 +00004458 NewVValType = XRValExpr->getType();
Alexey Bataevddf3db92018-04-13 17:31:06 +00004459 const OpaqueValueExpr *ERValExpr = IsXLHSInRHSPart ? RHS : LHS;
Alexey Bataev5e018f92015-04-23 06:35:10 +00004460 auto &&Gen = [&CGF, &NewVVal, UE, ExprRValue, XRValExpr, ERValExpr,
Alexey Bataevddf3db92018-04-13 17:31:06 +00004461 IsPostfixUpdate](RValue XRValue) {
Alexey Bataev5e018f92015-04-23 06:35:10 +00004462 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
4463 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, XRValue);
4464 RValue Res = CGF.EmitAnyExpr(UE);
4465 NewVVal = IsPostfixUpdate ? XRValue : Res;
4466 return Res;
4467 };
4468 auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr(
4469 XLValue, ExprRValue, BOUE->getOpcode(), IsXLHSInRHSPart, AO, Loc, Gen);
Alexey Bataevf117f2c2020-01-28 11:19:45 -05004470 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, X);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004471 if (Res.first) {
4472 // 'atomicrmw' instruction was generated.
4473 if (IsPostfixUpdate) {
4474 // Use old value from 'atomicrmw'.
4475 NewVVal = Res.second;
4476 } else {
4477 // 'atomicrmw' does not provide new value, so evaluate it using old
4478 // value of 'x'.
4479 CodeGenFunction::OpaqueValueMapping MapExpr(CGF, ERValExpr, ExprRValue);
4480 CodeGenFunction::OpaqueValueMapping MapX(CGF, XRValExpr, Res.second);
4481 NewVVal = CGF.EmitAnyExpr(UE);
4482 }
4483 }
4484 } else {
4485 // 'x' is simply rewritten with some 'expr'.
4486 NewVValType = X->getType().getNonReferenceType();
4487 ExprRValue = convertToType(CGF, ExprRValue, E->getType(),
Filipe Cabecinhas7af183d2015-08-11 04:19:28 +00004488 X->getType().getNonReferenceType(), Loc);
Alexey Bataevddf3db92018-04-13 17:31:06 +00004489 auto &&Gen = [&NewVVal, ExprRValue](RValue XRValue) {
Alexey Bataev5e018f92015-04-23 06:35:10 +00004490 NewVVal = XRValue;
4491 return ExprRValue;
4492 };
4493 // Try to perform atomicrmw xchg, otherwise simple exchange.
4494 auto Res = CGF.EmitOMPAtomicSimpleUpdateExpr(
4495 XLValue, ExprRValue, /*BO=*/BO_Assign, /*IsXLHSInRHSPart=*/false, AO,
4496 Loc, Gen);
Alexey Bataevf117f2c2020-01-28 11:19:45 -05004497 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, X);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004498 if (Res.first) {
4499 // 'atomicrmw' instruction was generated.
4500 NewVVal = IsPostfixUpdate ? Res.second : ExprRValue;
4501 }
4502 }
4503 // Emit post-update store to 'v' of old/new 'x' value.
Alexey Bataev8524d152016-01-21 12:35:58 +00004504 CGF.emitOMPSimpleStore(VLValue, NewVVal, NewVValType, Loc);
Alexey Bataevf117f2c2020-01-28 11:19:45 -05004505 CGF.CGM.getOpenMPRuntime().checkAndEmitLastprivateConditional(CGF, V);
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004506 // OpenMP, 2.17.7, atomic Construct
4507 // If the write, update, or capture clause is specified and the release,
4508 // acq_rel, or seq_cst clause is specified then the strong flush on entry to
4509 // the atomic operation is also a release flush.
4510 // If the read or capture clause is specified and the acquire, acq_rel, or
4511 // seq_cst clause is specified then the strong flush on exit from the atomic
4512 // operation is also an acquire flush.
4513 switch (AO) {
4514 case llvm::AtomicOrdering::Release:
4515 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
4516 llvm::AtomicOrdering::Release);
4517 break;
4518 case llvm::AtomicOrdering::Acquire:
4519 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
4520 llvm::AtomicOrdering::Acquire);
4521 break;
4522 case llvm::AtomicOrdering::AcquireRelease:
4523 case llvm::AtomicOrdering::SequentiallyConsistent:
4524 CGF.CGM.getOpenMPRuntime().emitFlush(CGF, llvm::None, Loc,
4525 llvm::AtomicOrdering::AcquireRelease);
4526 break;
4527 case llvm::AtomicOrdering::Monotonic:
4528 break;
4529 case llvm::AtomicOrdering::NotAtomic:
4530 case llvm::AtomicOrdering::Unordered:
4531 llvm_unreachable("Unexpected ordering.");
4532 }
Alexey Bataevb4505a72015-03-30 05:20:59 +00004533}
4534
Alexey Bataevddf3db92018-04-13 17:31:06 +00004535static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004536 llvm::AtomicOrdering AO, bool IsPostfixUpdate,
Alexey Bataev5e018f92015-04-23 06:35:10 +00004537 const Expr *X, const Expr *V, const Expr *E,
4538 const Expr *UE, bool IsXLHSInRHSPart,
4539 SourceLocation Loc) {
Alexey Bataevb57056f2015-01-22 06:17:56 +00004540 switch (Kind) {
4541 case OMPC_read:
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004542 emitOMPAtomicReadExpr(CGF, AO, X, V, Loc);
Alexey Bataevb57056f2015-01-22 06:17:56 +00004543 break;
4544 case OMPC_write:
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004545 emitOMPAtomicWriteExpr(CGF, AO, X, E, Loc);
Alexey Bataevb8329262015-02-27 06:33:30 +00004546 break;
Alexey Bataevb4505a72015-03-30 05:20:59 +00004547 case OMPC_unknown:
Alexey Bataevb57056f2015-01-22 06:17:56 +00004548 case OMPC_update:
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004549 emitOMPAtomicUpdateExpr(CGF, AO, X, E, UE, IsXLHSInRHSPart, Loc);
Alexey Bataevb4505a72015-03-30 05:20:59 +00004550 break;
Alexey Bataevb57056f2015-01-22 06:17:56 +00004551 case OMPC_capture:
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004552 emitOMPAtomicCaptureExpr(CGF, AO, IsPostfixUpdate, V, X, E, UE,
Alexey Bataev5e018f92015-04-23 06:35:10 +00004553 IsXLHSInRHSPart, Loc);
4554 break;
Alexey Bataevb57056f2015-01-22 06:17:56 +00004555 case OMPC_if:
4556 case OMPC_final:
4557 case OMPC_num_threads:
4558 case OMPC_private:
4559 case OMPC_firstprivate:
4560 case OMPC_lastprivate:
4561 case OMPC_reduction:
Alexey Bataev169d96a2017-07-18 20:17:46 +00004562 case OMPC_task_reduction:
Alexey Bataevfa312f32017-07-21 18:48:21 +00004563 case OMPC_in_reduction:
Alexey Bataevb57056f2015-01-22 06:17:56 +00004564 case OMPC_safelen:
Alexey Bataev66b15b52015-08-21 11:14:16 +00004565 case OMPC_simdlen:
Alexey Bataev9cc10fc2019-03-12 18:52:33 +00004566 case OMPC_allocator:
Alexey Bataeve04483e2019-03-27 14:14:31 +00004567 case OMPC_allocate:
Alexey Bataevb57056f2015-01-22 06:17:56 +00004568 case OMPC_collapse:
4569 case OMPC_default:
4570 case OMPC_seq_cst:
Alexey Bataevea9166b2020-02-06 16:30:23 -05004571 case OMPC_acq_rel:
Alexey Bataev04a830f2020-02-10 14:30:39 -05004572 case OMPC_acquire:
Alexey Bataev95598342020-02-10 15:49:05 -05004573 case OMPC_release:
Alexey Bataev9a8defc2020-02-11 11:10:43 -05004574 case OMPC_relaxed:
Alexey Bataevb57056f2015-01-22 06:17:56 +00004575 case OMPC_shared:
4576 case OMPC_linear:
4577 case OMPC_aligned:
4578 case OMPC_copyin:
4579 case OMPC_copyprivate:
4580 case OMPC_flush:
Alexey Bataevc112e942020-02-28 09:52:15 -05004581 case OMPC_depobj:
Alexey Bataevb57056f2015-01-22 06:17:56 +00004582 case OMPC_proc_bind:
4583 case OMPC_schedule:
4584 case OMPC_ordered:
4585 case OMPC_nowait:
4586 case OMPC_untied:
4587 case OMPC_threadprivate:
Alexey Bataev1c2cfbc2015-06-23 14:25:19 +00004588 case OMPC_depend:
Alexey Bataevb57056f2015-01-22 06:17:56 +00004589 case OMPC_mergeable:
Michael Wonge710d542015-08-07 16:16:36 +00004590 case OMPC_device:
Alexey Bataev346265e2015-09-25 10:37:12 +00004591 case OMPC_threads:
Alexey Bataevd14d1e62015-09-28 06:39:35 +00004592 case OMPC_simd:
Kelvin Li0bff7af2015-11-23 05:32:03 +00004593 case OMPC_map:
Kelvin Li099bb8c2015-11-24 20:50:12 +00004594 case OMPC_num_teams:
Kelvin Lia15fb1a2015-11-27 18:47:36 +00004595 case OMPC_thread_limit:
Alexey Bataeva0569352015-12-01 10:17:31 +00004596 case OMPC_priority:
Alexey Bataev1fd4aed2015-12-07 12:52:51 +00004597 case OMPC_grainsize:
Alexey Bataevb825de12015-12-07 10:51:44 +00004598 case OMPC_nogroup:
Alexey Bataev382967a2015-12-08 12:06:20 +00004599 case OMPC_num_tasks:
Alexey Bataev28c75412015-12-15 08:19:24 +00004600 case OMPC_hint:
Carlo Bertollib4adf552016-01-15 18:50:31 +00004601 case OMPC_dist_schedule:
Arpith Chacko Jacob3cf89042016-01-26 16:37:23 +00004602 case OMPC_defaultmap:
Alexey Bataeve48a5fc2016-04-12 05:28:34 +00004603 case OMPC_uniform:
Samuel Antao661c0902016-05-26 17:39:58 +00004604 case OMPC_to:
Samuel Antaoec172c62016-05-26 17:49:04 +00004605 case OMPC_from:
Carlo Bertolli2404b172016-07-13 15:37:16 +00004606 case OMPC_use_device_ptr:
Carlo Bertolli70594e92016-07-13 17:16:49 +00004607 case OMPC_is_device_ptr:
Kelvin Li1408f912018-09-26 04:28:39 +00004608 case OMPC_unified_address:
Alexey Bataev94c50642018-10-01 14:26:31 +00004609 case OMPC_unified_shared_memory:
Patrick Lyster6bdf63b2018-10-03 20:07:58 +00004610 case OMPC_reverse_offload:
Patrick Lyster3fe9e392018-10-11 14:41:10 +00004611 case OMPC_dynamic_allocators:
Patrick Lyster7a2a27c2018-11-02 12:18:11 +00004612 case OMPC_atomic_default_mem_order:
Alexey Bataev729e2422019-08-23 16:11:14 +00004613 case OMPC_device_type:
Alexey Bataevdba792c2019-09-23 18:13:31 +00004614 case OMPC_match:
Alexey Bataevb6e70842019-12-16 15:54:17 -05004615 case OMPC_nontemporal:
Alexey Bataevcb8e6912020-01-31 16:09:26 -05004616 case OMPC_order:
Alexey Bataev375437a2020-03-02 14:21:20 -05004617 case OMPC_destroy:
Alexey Bataev0f0564b2020-03-17 09:17:42 -04004618 case OMPC_detach:
Alexey Bataev06dea732020-03-20 09:41:22 -04004619 case OMPC_inclusive:
Alexey Bataev63828a32020-03-23 10:41:08 -04004620 case OMPC_exclusive:
Alexey Bataevb57056f2015-01-22 06:17:56 +00004621 llvm_unreachable("Clause is not allowed in 'omp atomic'.");
4622 }
4623}
4624
4625void CodeGenFunction::EmitOMPAtomicDirective(const OMPAtomicDirective &S) {
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004626 llvm::AtomicOrdering AO = llvm::AtomicOrdering::Monotonic;
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05004627 bool MemOrderingSpecified = false;
4628 if (S.getSingleClause<OMPSeqCstClause>()) {
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004629 AO = llvm::AtomicOrdering::SequentiallyConsistent;
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05004630 MemOrderingSpecified = true;
4631 } else if (S.getSingleClause<OMPAcqRelClause>()) {
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004632 AO = llvm::AtomicOrdering::AcquireRelease;
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05004633 MemOrderingSpecified = true;
4634 } else if (S.getSingleClause<OMPAcquireClause>()) {
Alexey Bataev04a830f2020-02-10 14:30:39 -05004635 AO = llvm::AtomicOrdering::Acquire;
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05004636 MemOrderingSpecified = true;
4637 } else if (S.getSingleClause<OMPReleaseClause>()) {
Alexey Bataev95598342020-02-10 15:49:05 -05004638 AO = llvm::AtomicOrdering::Release;
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05004639 MemOrderingSpecified = true;
4640 } else if (S.getSingleClause<OMPRelaxedClause>()) {
Alexey Bataev9a8defc2020-02-11 11:10:43 -05004641 AO = llvm::AtomicOrdering::Monotonic;
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05004642 MemOrderingSpecified = true;
4643 }
Alexey Bataevb57056f2015-01-22 06:17:56 +00004644 OpenMPClauseKind Kind = OMPC_unknown;
Alexey Bataevddf3db92018-04-13 17:31:06 +00004645 for (const OMPClause *C : S.clauses()) {
Alexey Bataev9a8defc2020-02-11 11:10:43 -05004646 // Find first clause (skip seq_cst|acq_rel|aqcuire|release|relaxed clause,
4647 // if it is first).
Alexey Bataevea9166b2020-02-06 16:30:23 -05004648 if (C->getClauseKind() != OMPC_seq_cst &&
Alexey Bataev04a830f2020-02-10 14:30:39 -05004649 C->getClauseKind() != OMPC_acq_rel &&
Alexey Bataev95598342020-02-10 15:49:05 -05004650 C->getClauseKind() != OMPC_acquire &&
Alexey Bataev9a8defc2020-02-11 11:10:43 -05004651 C->getClauseKind() != OMPC_release &&
4652 C->getClauseKind() != OMPC_relaxed) {
Alexey Bataevb57056f2015-01-22 06:17:56 +00004653 Kind = C->getClauseKind();
4654 break;
4655 }
4656 }
Alexey Bataev2d4f80f2020-02-11 15:15:21 -05004657 if (!MemOrderingSpecified) {
4658 llvm::AtomicOrdering DefaultOrder =
4659 CGM.getOpenMPRuntime().getDefaultMemoryOrdering();
4660 if (DefaultOrder == llvm::AtomicOrdering::Monotonic ||
4661 DefaultOrder == llvm::AtomicOrdering::SequentiallyConsistent ||
4662 (DefaultOrder == llvm::AtomicOrdering::AcquireRelease &&
4663 Kind == OMPC_capture)) {
4664 AO = DefaultOrder;
4665 } else if (DefaultOrder == llvm::AtomicOrdering::AcquireRelease) {
4666 if (Kind == OMPC_unknown || Kind == OMPC_update || Kind == OMPC_write) {
4667 AO = llvm::AtomicOrdering::Release;
4668 } else if (Kind == OMPC_read) {
4669 assert(Kind == OMPC_read && "Unexpected atomic kind.");
4670 AO = llvm::AtomicOrdering::Acquire;
4671 }
4672 }
4673 }
Alexey Bataev10fec572015-03-11 04:48:56 +00004674
Alexey Bataevddf3db92018-04-13 17:31:06 +00004675 const Stmt *CS = S.getInnermostCapturedStmt()->IgnoreContainers();
Bill Wendling7c44da22018-10-31 03:48:47 +00004676 if (const auto *FE = dyn_cast<FullExpr>(CS))
4677 enterFullExpression(FE);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004678 // Processing for statements under 'atomic capture'.
4679 if (const auto *Compound = dyn_cast<CompoundStmt>(CS)) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00004680 for (const Stmt *C : Compound->body()) {
Bill Wendling7c44da22018-10-31 03:48:47 +00004681 if (const auto *FE = dyn_cast<FullExpr>(C))
4682 enterFullExpression(FE);
Alexey Bataev5e018f92015-04-23 06:35:10 +00004683 }
4684 }
Alexey Bataev10fec572015-03-11 04:48:56 +00004685
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004686 auto &&CodeGen = [&S, Kind, AO, CS](CodeGenFunction &CGF,
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004687 PrePostActionTy &) {
Alexey Bataev33c56402015-12-14 09:26:19 +00004688 CGF.EmitStopPoint(CS);
Alexey Bataeve8e05de2020-02-07 12:22:23 -05004689 emitOMPAtomicExpr(CGF, Kind, AO, S.isPostfixUpdate(), S.getX(), S.getV(),
4690 S.getExpr(), S.getUpdateExpr(), S.isXLHSInRHSPart(),
4691 S.getBeginLoc());
Alexey Bataev6f1ffc02015-04-10 04:50:10 +00004692 };
Alexey Bataev475a7442018-01-12 19:39:11 +00004693 OMPLexicalScope Scope(*this, S, OMPD_unknown);
Alexey Bataev81c7ea02015-07-03 09:56:58 +00004694 CGM.getOpenMPRuntime().emitInlinedDirective(*this, OMPD_atomic, CodeGen);
Alexey Bataev0162e452014-07-22 10:10:35 +00004695}
4696
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004697static void emitCommonOMPTargetDirective(CodeGenFunction &CGF,
4698 const OMPExecutableDirective &S,
4699 const RegionCodeGenTy &CodeGen) {
4700 assert(isOpenMPTargetExecutionDirective(S.getDirectiveKind()));
4701 CodeGenModule &CGM = CGF.CGM;
Samuel Antaobed3c462015-10-02 16:14:20 +00004702
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00004703 // On device emit this construct as inlined code.
4704 if (CGM.getLangOpts().OpenMPIsDevice) {
4705 OMPLexicalScope Scope(CGF, S, OMPD_target);
4706 CGM.getOpenMPRuntime().emitInlinedDirective(
4707 CGF, OMPD_target, [&S](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev4ac68a22018-05-16 15:08:32 +00004708 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
Alexey Bataev4f4bf7c2018-03-15 15:47:20 +00004709 });
4710 return;
4711 }
4712
Alexey Bataev46978742020-01-30 10:46:11 -05004713 auto LPCRegion =
4714 CGOpenMPRuntime::LastprivateConditionalRAII::disable(CGF, S);
Samuel Antaoee8fb302016-01-06 13:42:12 +00004715 llvm::Function *Fn = nullptr;
4716 llvm::Constant *FnID = nullptr;
Samuel Antaobed3c462015-10-02 16:14:20 +00004717
Samuel Antaobed3c462015-10-02 16:14:20 +00004718 const Expr *IfCond = nullptr;
Arpith Chacko Jacobfe4890a2017-01-18 20:40:48 +00004719 // Check for the at most one if clause associated with the target region.
4720 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
4721 if (C->getNameModifier() == OMPD_unknown ||
4722 C->getNameModifier() == OMPD_target) {
4723 IfCond = C->getCondition();
4724 break;
4725 }
Samuel Antaobed3c462015-10-02 16:14:20 +00004726 }
4727
4728 // Check if we have any device clause associated with the directive.
Alexey Bataevf3c857f2020-03-18 17:52:41 -04004729 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device(
4730 nullptr, OMPC_DEVICE_unknown);
4731 if (auto *C = S.getSingleClause<OMPDeviceClause>())
4732 Device.setPointerAndInt(C->getDevice(), C->getModifier());
Samuel Antaobed3c462015-10-02 16:14:20 +00004733
Samuel Antaoee8fb302016-01-06 13:42:12 +00004734 // Check if we have an if clause whose conditional always evaluates to false
4735 // or if we do not have any targets specified. If so the target region is not
4736 // an offload entry point.
4737 bool IsOffloadEntry = true;
4738 if (IfCond) {
4739 bool Val;
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004740 if (CGF.ConstantFoldsToSimpleInteger(IfCond, Val) && !Val)
Samuel Antaoee8fb302016-01-06 13:42:12 +00004741 IsOffloadEntry = false;
4742 }
4743 if (CGM.getLangOpts().OMPTargetTriples.empty())
4744 IsOffloadEntry = false;
4745
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004746 assert(CGF.CurFuncDecl && "No parent declaration for target region!");
Samuel Antaoee8fb302016-01-06 13:42:12 +00004747 StringRef ParentName;
4748 // In case we have Ctors/Dtors we use the complete type variant to produce
4749 // the mangling of the device outlined kernel.
Alexey Bataevddf3db92018-04-13 17:31:06 +00004750 if (const auto *D = dyn_cast<CXXConstructorDecl>(CGF.CurFuncDecl))
Samuel Antaoee8fb302016-01-06 13:42:12 +00004751 ParentName = CGM.getMangledName(GlobalDecl(D, Ctor_Complete));
Alexey Bataevddf3db92018-04-13 17:31:06 +00004752 else if (const auto *D = dyn_cast<CXXDestructorDecl>(CGF.CurFuncDecl))
Samuel Antaoee8fb302016-01-06 13:42:12 +00004753 ParentName = CGM.getMangledName(GlobalDecl(D, Dtor_Complete));
4754 else
4755 ParentName =
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004756 CGM.getMangledName(GlobalDecl(cast<FunctionDecl>(CGF.CurFuncDecl)));
Samuel Antaoee8fb302016-01-06 13:42:12 +00004757
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004758 // Emit target region as a standalone region.
4759 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(S, ParentName, Fn, FnID,
4760 IsOffloadEntry, CodeGen);
Alexey Bataev8451efa2018-01-15 19:06:12 +00004761 OMPLexicalScope Scope(CGF, S, OMPD_task);
Alexey Bataevec7946e2019-09-23 14:06:51 +00004762 auto &&SizeEmitter =
4763 [IsOffloadEntry](CodeGenFunction &CGF,
4764 const OMPLoopDirective &D) -> llvm::Value * {
4765 if (IsOffloadEntry) {
4766 OMPLoopScope(CGF, D);
4767 // Emit calculation of the iterations count.
4768 llvm::Value *NumIterations = CGF.EmitScalarExpr(D.getNumIterations());
4769 NumIterations = CGF.Builder.CreateIntCast(NumIterations, CGF.Int64Ty,
4770 /*isSigned=*/false);
4771 return NumIterations;
4772 }
4773 return nullptr;
Alexey Bataev7bb33532019-01-07 21:30:43 +00004774 };
Alexey Bataevec7946e2019-09-23 14:06:51 +00004775 CGM.getOpenMPRuntime().emitTargetCall(CGF, S, Fn, FnID, IfCond, Device,
4776 SizeEmitter);
Alexey Bataev0bd520b2014-09-19 08:19:49 +00004777}
4778
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004779static void emitTargetRegion(CodeGenFunction &CGF, const OMPTargetDirective &S,
4780 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00004781 Action.Enter(CGF);
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004782 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
4783 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
4784 CGF.EmitOMPPrivateClause(S, PrivateScope);
4785 (void)PrivateScope.Privatize();
Alexey Bataev60705422018-10-30 15:50:12 +00004786 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
4787 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004788
Alexey Bataev475a7442018-01-12 19:39:11 +00004789 CGF.EmitStmt(S.getCapturedStmt(OMPD_target)->getCapturedStmt());
Arpith Chacko Jacob43a8b7b2017-01-16 15:26:02 +00004790}
4791
4792void CodeGenFunction::EmitOMPTargetDeviceFunction(CodeGenModule &CGM,
4793 StringRef ParentName,
4794 const OMPTargetDirective &S) {
4795 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4796 emitTargetRegion(CGF, S, Action);
4797 };
4798 llvm::Function *Fn;
4799 llvm::Constant *Addr;
4800 // Emit target region as a standalone region.
4801 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
4802 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
4803 assert(Fn && Addr && "Target device function emission failed.");
4804}
4805
4806void CodeGenFunction::EmitOMPTargetDirective(const OMPTargetDirective &S) {
4807 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4808 emitTargetRegion(CGF, S, Action);
4809 };
4810 emitCommonOMPTargetDirective(*this, S, CodeGen);
4811}
4812
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004813static void emitCommonOMPTeamsDirective(CodeGenFunction &CGF,
4814 const OMPExecutableDirective &S,
4815 OpenMPDirectiveKind InnermostKind,
4816 const RegionCodeGenTy &CodeGen) {
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00004817 const CapturedStmt *CS = S.getCapturedStmt(OMPD_teams);
James Y Knight9871db02019-02-05 16:42:33 +00004818 llvm::Function *OutlinedFn =
Alexey Bataevddf3db92018-04-13 17:31:06 +00004819 CGF.CGM.getOpenMPRuntime().emitTeamsOutlinedFunction(
4820 S, *CS->getCapturedDecl()->param_begin(), InnermostKind, CodeGen);
Samuel Antaob68e2db2016-03-03 16:20:23 +00004821
Alexey Bataevddf3db92018-04-13 17:31:06 +00004822 const auto *NT = S.getSingleClause<OMPNumTeamsClause>();
4823 const auto *TL = S.getSingleClause<OMPThreadLimitClause>();
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004824 if (NT || TL) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00004825 const Expr *NumTeams = NT ? NT->getNumTeams() : nullptr;
4826 const Expr *ThreadLimit = TL ? TL->getThreadLimit() : nullptr;
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004827
Carlo Bertollic6872252016-04-04 15:55:02 +00004828 CGF.CGM.getOpenMPRuntime().emitNumTeamsClause(CGF, NumTeams, ThreadLimit,
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004829 S.getBeginLoc());
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004830 }
4831
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00004832 OMPTeamsScope Scope(CGF, S);
Alexey Bataev14fa1c62016-03-29 05:34:15 +00004833 llvm::SmallVector<llvm::Value *, 16> CapturedVars;
4834 CGF.GenerateOpenMPCapturedVars(*CS, CapturedVars);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00004835 CGF.CGM.getOpenMPRuntime().emitTeamsCall(CGF, S, S.getBeginLoc(), OutlinedFn,
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004836 CapturedVars);
4837}
4838
4839void CodeGenFunction::EmitOMPTeamsDirective(const OMPTeamsDirective &S) {
Kelvin Li51336dd2016-12-15 17:55:32 +00004840 // Emit teams region as a standalone region.
Alexey Bataevc99042b2018-03-15 18:10:54 +00004841 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00004842 Action.Enter(CGF);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004843 OMPPrivateScope PrivateScope(CGF);
Carlo Bertolli6ad7b5a2016-03-03 22:09:40 +00004844 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
4845 CGF.EmitOMPPrivateClause(S, PrivateScope);
Arpith Chacko Jacobfc711b12017-02-16 16:48:49 +00004846 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004847 (void)PrivateScope.Privatize();
Alexey Bataev475a7442018-01-12 19:39:11 +00004848 CGF.EmitStmt(S.getCapturedStmt(OMPD_teams)->getCapturedStmt());
Arpith Chacko Jacobfc711b12017-02-16 16:48:49 +00004849 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
Carlo Bertolli430d8ec2016-03-03 20:34:23 +00004850 };
Alexey Bataev2139ed62017-11-16 18:20:21 +00004851 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute, CodeGen);
Alexey Bataevddf3db92018-04-13 17:31:06 +00004852 emitPostUpdateForReductionClause(*this, S,
4853 [](CodeGenFunction &) { return nullptr; });
Alexey Bataev13314bf2014-10-09 04:18:56 +00004854}
Alexey Bataev6d4ed052015-07-01 06:57:41 +00004855
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00004856static void emitTargetTeamsRegion(CodeGenFunction &CGF, PrePostActionTy &Action,
4857 const OMPTargetTeamsDirective &S) {
4858 auto *CS = S.getCapturedStmt(OMPD_teams);
4859 Action.Enter(CGF);
Alexey Bataevf9fc42e2017-11-22 14:25:55 +00004860 // Emit teams region as a standalone region.
4861 auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00004862 Action.Enter(CGF);
Alexey Bataevf9fc42e2017-11-22 14:25:55 +00004863 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
4864 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
4865 CGF.EmitOMPPrivateClause(S, PrivateScope);
4866 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4867 (void)PrivateScope.Privatize();
Alexey Bataev60705422018-10-30 15:50:12 +00004868 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
4869 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00004870 CGF.EmitStmt(CS->getCapturedStmt());
Alexey Bataevf9fc42e2017-11-22 14:25:55 +00004871 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00004872 };
4873 emitCommonOMPTeamsDirective(CGF, S, OMPD_teams, CodeGen);
Alexey Bataevddf3db92018-04-13 17:31:06 +00004874 emitPostUpdateForReductionClause(CGF, S,
4875 [](CodeGenFunction &) { return nullptr; });
Arpith Chacko Jacob99a1e0e2017-01-25 02:18:43 +00004876}
4877
4878void CodeGenFunction::EmitOMPTargetTeamsDeviceFunction(
4879 CodeGenModule &CGM, StringRef ParentName,
4880 const OMPTargetTeamsDirective &S) {
4881 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4882 emitTargetTeamsRegion(CGF, Action, S);
4883 };
4884 llvm::Function *Fn;
4885 llvm::Constant *Addr;
4886 // Emit target region as a standalone region.
4887 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
4888 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
4889 assert(Fn && Addr && "Target device function emission failed.");
4890}
4891
4892void CodeGenFunction::EmitOMPTargetTeamsDirective(
4893 const OMPTargetTeamsDirective &S) {
4894 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4895 emitTargetTeamsRegion(CGF, Action, S);
4896 };
4897 emitCommonOMPTargetDirective(*this, S, CodeGen);
4898}
4899
Alexey Bataevdfa430f2017-12-08 15:03:50 +00004900static void
4901emitTargetTeamsDistributeRegion(CodeGenFunction &CGF, PrePostActionTy &Action,
4902 const OMPTargetTeamsDistributeDirective &S) {
4903 Action.Enter(CGF);
4904 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
4905 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
4906 };
4907
4908 // Emit teams region as a standalone region.
4909 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00004910 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00004911 Action.Enter(CGF);
Alexey Bataevdfa430f2017-12-08 15:03:50 +00004912 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
4913 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4914 (void)PrivateScope.Privatize();
4915 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
4916 CodeGenDistribute);
4917 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
4918 };
4919 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute, CodeGen);
4920 emitPostUpdateForReductionClause(CGF, S,
4921 [](CodeGenFunction &) { return nullptr; });
4922}
4923
4924void CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction(
4925 CodeGenModule &CGM, StringRef ParentName,
4926 const OMPTargetTeamsDistributeDirective &S) {
4927 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4928 emitTargetTeamsDistributeRegion(CGF, Action, S);
4929 };
4930 llvm::Function *Fn;
4931 llvm::Constant *Addr;
4932 // Emit target region as a standalone region.
4933 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
4934 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
4935 assert(Fn && Addr && "Target device function emission failed.");
4936}
4937
4938void CodeGenFunction::EmitOMPTargetTeamsDistributeDirective(
4939 const OMPTargetTeamsDistributeDirective &S) {
4940 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4941 emitTargetTeamsDistributeRegion(CGF, Action, S);
4942 };
4943 emitCommonOMPTargetDirective(*this, S, CodeGen);
4944}
4945
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00004946static void emitTargetTeamsDistributeSimdRegion(
4947 CodeGenFunction &CGF, PrePostActionTy &Action,
4948 const OMPTargetTeamsDistributeSimdDirective &S) {
4949 Action.Enter(CGF);
4950 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
4951 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
4952 };
4953
4954 // Emit teams region as a standalone region.
4955 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00004956 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00004957 Action.Enter(CGF);
Alexey Bataevfbe17fb2017-12-13 19:45:06 +00004958 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
4959 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
4960 (void)PrivateScope.Privatize();
4961 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
4962 CodeGenDistribute);
4963 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
4964 };
4965 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_simd, CodeGen);
4966 emitPostUpdateForReductionClause(CGF, S,
4967 [](CodeGenFunction &) { return nullptr; });
4968}
4969
4970void CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction(
4971 CodeGenModule &CGM, StringRef ParentName,
4972 const OMPTargetTeamsDistributeSimdDirective &S) {
4973 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4974 emitTargetTeamsDistributeSimdRegion(CGF, Action, S);
4975 };
4976 llvm::Function *Fn;
4977 llvm::Constant *Addr;
4978 // Emit target region as a standalone region.
4979 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
4980 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
4981 assert(Fn && Addr && "Target device function emission failed.");
4982}
4983
4984void CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDirective(
4985 const OMPTargetTeamsDistributeSimdDirective &S) {
4986 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
4987 emitTargetTeamsDistributeSimdRegion(CGF, Action, S);
4988 };
4989 emitCommonOMPTargetDirective(*this, S, CodeGen);
4990}
4991
Carlo Bertolliba1487b2017-10-04 14:12:09 +00004992void CodeGenFunction::EmitOMPTeamsDistributeDirective(
4993 const OMPTeamsDistributeDirective &S) {
4994
4995 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
4996 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
4997 };
4998
4999 // Emit teams region as a standalone region.
5000 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00005001 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00005002 Action.Enter(CGF);
Carlo Bertolliba1487b2017-10-04 14:12:09 +00005003 OMPPrivateScope PrivateScope(CGF);
5004 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5005 (void)PrivateScope.Privatize();
5006 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
5007 CodeGenDistribute);
5008 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
5009 };
Alexey Bataev95c6dd42017-11-29 15:14:16 +00005010 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute, CodeGen);
Carlo Bertolliba1487b2017-10-04 14:12:09 +00005011 emitPostUpdateForReductionClause(*this, S,
5012 [](CodeGenFunction &) { return nullptr; });
5013}
5014
Alexey Bataev999277a2017-12-06 14:31:09 +00005015void CodeGenFunction::EmitOMPTeamsDistributeSimdDirective(
5016 const OMPTeamsDistributeSimdDirective &S) {
5017 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
5018 CGF.EmitOMPDistributeLoop(S, emitOMPLoopBodyWithStopPoint, S.getInc());
5019 };
5020
5021 // Emit teams region as a standalone region.
5022 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00005023 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00005024 Action.Enter(CGF);
Alexey Bataev999277a2017-12-06 14:31:09 +00005025 OMPPrivateScope PrivateScope(CGF);
5026 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5027 (void)PrivateScope.Privatize();
5028 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_simd,
5029 CodeGenDistribute);
5030 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
5031 };
5032 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_simd, CodeGen);
5033 emitPostUpdateForReductionClause(*this, S,
5034 [](CodeGenFunction &) { return nullptr; });
5035}
5036
Carlo Bertolli62fae152017-11-20 20:46:39 +00005037void CodeGenFunction::EmitOMPTeamsDistributeParallelForDirective(
5038 const OMPTeamsDistributeParallelForDirective &S) {
5039 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
5040 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
5041 S.getDistInc());
5042 };
5043
5044 // Emit teams region as a standalone region.
5045 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00005046 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00005047 Action.Enter(CGF);
Carlo Bertolli62fae152017-11-20 20:46:39 +00005048 OMPPrivateScope PrivateScope(CGF);
5049 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5050 (void)PrivateScope.Privatize();
Alexey Bataev10a54312017-11-27 16:54:08 +00005051 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_distribute,
5052 CodeGenDistribute);
Carlo Bertolli62fae152017-11-20 20:46:39 +00005053 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
5054 };
5055 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_parallel_for, CodeGen);
5056 emitPostUpdateForReductionClause(*this, S,
5057 [](CodeGenFunction &) { return nullptr; });
5058}
5059
Carlo Bertolli56a2aa42017-12-04 20:57:19 +00005060void CodeGenFunction::EmitOMPTeamsDistributeParallelForSimdDirective(
5061 const OMPTeamsDistributeParallelForSimdDirective &S) {
5062 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
5063 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
5064 S.getDistInc());
5065 };
5066
5067 // Emit teams region as a standalone region.
5068 auto &&CodeGen = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00005069 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00005070 Action.Enter(CGF);
Carlo Bertolli56a2aa42017-12-04 20:57:19 +00005071 OMPPrivateScope PrivateScope(CGF);
5072 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5073 (void)PrivateScope.Privatize();
5074 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(
5075 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false);
5076 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
5077 };
Alexey Bataev0b978942019-12-11 15:26:38 -05005078 emitCommonOMPTeamsDirective(*this, S, OMPD_distribute_parallel_for_simd,
5079 CodeGen);
Carlo Bertolli56a2aa42017-12-04 20:57:19 +00005080 emitPostUpdateForReductionClause(*this, S,
5081 [](CodeGenFunction &) { return nullptr; });
5082}
5083
Carlo Bertolli52978c32018-01-03 21:12:44 +00005084static void emitTargetTeamsDistributeParallelForRegion(
5085 CodeGenFunction &CGF, const OMPTargetTeamsDistributeParallelForDirective &S,
5086 PrePostActionTy &Action) {
Carlo Bertolli79712092018-02-28 20:48:35 +00005087 Action.Enter(CGF);
Carlo Bertolli52978c32018-01-03 21:12:44 +00005088 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
5089 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
5090 S.getDistInc());
5091 };
5092
5093 // Emit teams region as a standalone region.
5094 auto &&CodeGenTeams = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00005095 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00005096 Action.Enter(CGF);
Carlo Bertolli52978c32018-01-03 21:12:44 +00005097 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5098 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5099 (void)PrivateScope.Privatize();
5100 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(
5101 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false);
5102 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
5103 };
5104
5105 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_parallel_for,
5106 CodeGenTeams);
5107 emitPostUpdateForReductionClause(CGF, S,
5108 [](CodeGenFunction &) { return nullptr; });
5109}
5110
5111void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction(
5112 CodeGenModule &CGM, StringRef ParentName,
5113 const OMPTargetTeamsDistributeParallelForDirective &S) {
5114 // Emit SPMD target teams distribute parallel for region as a standalone
5115 // region.
5116 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5117 emitTargetTeamsDistributeParallelForRegion(CGF, S, Action);
5118 };
5119 llvm::Function *Fn;
5120 llvm::Constant *Addr;
5121 // Emit target region as a standalone region.
5122 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
5123 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
5124 assert(Fn && Addr && "Target device function emission failed.");
5125}
5126
5127void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDirective(
5128 const OMPTargetTeamsDistributeParallelForDirective &S) {
5129 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5130 emitTargetTeamsDistributeParallelForRegion(CGF, S, Action);
5131 };
5132 emitCommonOMPTargetDirective(*this, S, CodeGen);
5133}
5134
Alexey Bataev647dd842018-01-15 20:59:40 +00005135static void emitTargetTeamsDistributeParallelForSimdRegion(
5136 CodeGenFunction &CGF,
5137 const OMPTargetTeamsDistributeParallelForSimdDirective &S,
5138 PrePostActionTy &Action) {
Carlo Bertolli79712092018-02-28 20:48:35 +00005139 Action.Enter(CGF);
Alexey Bataev647dd842018-01-15 20:59:40 +00005140 auto &&CodeGenDistribute = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
5141 CGF.EmitOMPDistributeLoop(S, emitInnerParallelForWhenCombined,
5142 S.getDistInc());
5143 };
5144
5145 // Emit teams region as a standalone region.
5146 auto &&CodeGenTeams = [&S, &CodeGenDistribute](CodeGenFunction &CGF,
Alexey Bataevc99042b2018-03-15 18:10:54 +00005147 PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00005148 Action.Enter(CGF);
Alexey Bataev647dd842018-01-15 20:59:40 +00005149 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5150 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5151 (void)PrivateScope.Privatize();
5152 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(
5153 CGF, OMPD_distribute, CodeGenDistribute, /*HasCancel=*/false);
5154 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_teams);
5155 };
5156
5157 emitCommonOMPTeamsDirective(CGF, S, OMPD_distribute_parallel_for_simd,
5158 CodeGenTeams);
5159 emitPostUpdateForReductionClause(CGF, S,
5160 [](CodeGenFunction &) { return nullptr; });
5161}
5162
5163void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction(
5164 CodeGenModule &CGM, StringRef ParentName,
5165 const OMPTargetTeamsDistributeParallelForSimdDirective &S) {
5166 // Emit SPMD target teams distribute parallel for simd region as a standalone
5167 // region.
5168 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5169 emitTargetTeamsDistributeParallelForSimdRegion(CGF, S, Action);
5170 };
5171 llvm::Function *Fn;
5172 llvm::Constant *Addr;
5173 // Emit target region as a standalone region.
5174 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
5175 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
5176 assert(Fn && Addr && "Target device function emission failed.");
5177}
5178
5179void CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForSimdDirective(
5180 const OMPTargetTeamsDistributeParallelForSimdDirective &S) {
5181 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5182 emitTargetTeamsDistributeParallelForSimdRegion(CGF, S, Action);
5183 };
5184 emitCommonOMPTargetDirective(*this, S, CodeGen);
5185}
5186
Alexey Bataev6d4ed052015-07-01 06:57:41 +00005187void CodeGenFunction::EmitOMPCancellationPointDirective(
5188 const OMPCancellationPointDirective &S) {
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005189 CGM.getOpenMPRuntime().emitCancellationPointCall(*this, S.getBeginLoc(),
Alexey Bataev0f34da12015-07-02 04:17:07 +00005190 S.getCancelRegion());
Alexey Bataev6d4ed052015-07-01 06:57:41 +00005191}
5192
Alexey Bataev80909872015-07-02 11:25:17 +00005193void CodeGenFunction::EmitOMPCancelDirective(const OMPCancelDirective &S) {
Alexey Bataev87933c72015-09-18 08:07:34 +00005194 const Expr *IfCond = nullptr;
5195 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
5196 if (C->getNameModifier() == OMPD_unknown ||
5197 C->getNameModifier() == OMPD_cancel) {
5198 IfCond = C->getCondition();
5199 break;
5200 }
5201 }
Johannes Doerfert10fedd92019-12-26 11:23:38 -06005202 if (llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder()) {
5203 // TODO: This check is necessary as we only generate `omp parallel` through
5204 // the OpenMPIRBuilder for now.
5205 if (S.getCancelRegion() == OMPD_parallel) {
5206 llvm::Value *IfCondition = nullptr;
5207 if (IfCond)
5208 IfCondition = EmitScalarExpr(IfCond,
5209 /*IgnoreResultAssign=*/true);
5210 return Builder.restoreIP(
5211 OMPBuilder->CreateCancel(Builder, IfCondition, S.getCancelRegion()));
5212 }
5213 }
5214
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005215 CGM.getOpenMPRuntime().emitCancelCall(*this, S.getBeginLoc(), IfCond,
Alexey Bataev7d5d33e2015-07-06 05:50:32 +00005216 S.getCancelRegion());
Alexey Bataev80909872015-07-02 11:25:17 +00005217}
5218
Alexey Bataev81c7ea02015-07-03 09:56:58 +00005219CodeGenFunction::JumpDest
5220CodeGenFunction::getOMPCancelDestination(OpenMPDirectiveKind Kind) {
Alexey Bataev957d8562016-11-17 15:12:05 +00005221 if (Kind == OMPD_parallel || Kind == OMPD_task ||
Alexey Bataeve0ca4792020-02-12 16:12:53 -05005222 Kind == OMPD_target_parallel || Kind == OMPD_taskloop ||
5223 Kind == OMPD_master_taskloop || Kind == OMPD_parallel_master_taskloop)
Alexey Bataev81c7ea02015-07-03 09:56:58 +00005224 return ReturnBlock;
Alexey Bataev25e5b442015-09-15 12:52:43 +00005225 assert(Kind == OMPD_for || Kind == OMPD_section || Kind == OMPD_sections ||
Alexey Bataev957d8562016-11-17 15:12:05 +00005226 Kind == OMPD_parallel_sections || Kind == OMPD_parallel_for ||
5227 Kind == OMPD_distribute_parallel_for ||
Alexey Bataevdcb4b8fb2017-11-22 20:19:50 +00005228 Kind == OMPD_target_parallel_for ||
Alexey Bataev16e79882017-11-22 21:12:03 +00005229 Kind == OMPD_teams_distribute_parallel_for ||
5230 Kind == OMPD_target_teams_distribute_parallel_for);
Alexey Bataev957d8562016-11-17 15:12:05 +00005231 return OMPCancelStack.getExitBlock();
Alexey Bataev81c7ea02015-07-03 09:56:58 +00005232}
Michael Wong65f367f2015-07-21 13:44:28 +00005233
Samuel Antaocc10b852016-07-28 14:23:26 +00005234void CodeGenFunction::EmitOMPUseDevicePtrClause(
5235 const OMPClause &NC, OMPPrivateScope &PrivateScope,
5236 const llvm::DenseMap<const ValueDecl *, Address> &CaptureDeviceAddrMap) {
5237 const auto &C = cast<OMPUseDevicePtrClause>(NC);
5238 auto OrigVarIt = C.varlist_begin();
5239 auto InitIt = C.inits().begin();
Alexey Bataevddf3db92018-04-13 17:31:06 +00005240 for (const Expr *PvtVarIt : C.private_copies()) {
5241 const auto *OrigVD = cast<VarDecl>(cast<DeclRefExpr>(*OrigVarIt)->getDecl());
5242 const auto *InitVD = cast<VarDecl>(cast<DeclRefExpr>(*InitIt)->getDecl());
5243 const auto *PvtVD = cast<VarDecl>(cast<DeclRefExpr>(PvtVarIt)->getDecl());
Samuel Antaocc10b852016-07-28 14:23:26 +00005244
5245 // In order to identify the right initializer we need to match the
5246 // declaration used by the mapping logic. In some cases we may get
5247 // OMPCapturedExprDecl that refers to the original declaration.
5248 const ValueDecl *MatchingVD = OrigVD;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005249 if (const auto *OED = dyn_cast<OMPCapturedExprDecl>(MatchingVD)) {
Samuel Antaocc10b852016-07-28 14:23:26 +00005250 // OMPCapturedExprDecl are used to privative fields of the current
5251 // structure.
Alexey Bataevddf3db92018-04-13 17:31:06 +00005252 const auto *ME = cast<MemberExpr>(OED->getInit());
Samuel Antaocc10b852016-07-28 14:23:26 +00005253 assert(isa<CXXThisExpr>(ME->getBase()) &&
5254 "Base should be the current struct!");
5255 MatchingVD = ME->getMemberDecl();
5256 }
5257
5258 // If we don't have information about the current list item, move on to
5259 // the next one.
5260 auto InitAddrIt = CaptureDeviceAddrMap.find(MatchingVD);
5261 if (InitAddrIt == CaptureDeviceAddrMap.end())
5262 continue;
5263
Alexey Bataevddf3db92018-04-13 17:31:06 +00005264 bool IsRegistered = PrivateScope.addPrivate(OrigVD, [this, OrigVD,
5265 InitAddrIt, InitVD,
5266 PvtVD]() {
Samuel Antaocc10b852016-07-28 14:23:26 +00005267 // Initialize the temporary initialization variable with the address we
5268 // get from the runtime library. We have to cast the source address
5269 // because it is always a void *. References are materialized in the
5270 // privatization scope, so the initialization here disregards the fact
5271 // the original variable is a reference.
5272 QualType AddrQTy =
5273 getContext().getPointerType(OrigVD->getType().getNonReferenceType());
5274 llvm::Type *AddrTy = ConvertTypeForMem(AddrQTy);
5275 Address InitAddr = Builder.CreateBitCast(InitAddrIt->second, AddrTy);
5276 setAddrOfLocalVar(InitVD, InitAddr);
5277
5278 // Emit private declaration, it will be initialized by the value we
5279 // declaration we just added to the local declarations map.
5280 EmitDecl(*PvtVD);
5281
5282 // The initialization variables reached its purpose in the emission
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005283 // of the previous declaration, so we don't need it anymore.
Samuel Antaocc10b852016-07-28 14:23:26 +00005284 LocalDeclMap.erase(InitVD);
5285
5286 // Return the address of the private variable.
5287 return GetAddrOfLocalVar(PvtVD);
5288 });
5289 assert(IsRegistered && "firstprivate var already registered as private");
5290 // Silence the warning about unused variable.
5291 (void)IsRegistered;
5292
5293 ++OrigVarIt;
5294 ++InitIt;
5295 }
5296}
5297
Michael Wong65f367f2015-07-21 13:44:28 +00005298// Generate the instructions for '#pragma omp target data' directive.
5299void CodeGenFunction::EmitOMPTargetDataDirective(
5300 const OMPTargetDataDirective &S) {
Samuel Antaocc10b852016-07-28 14:23:26 +00005301 CGOpenMPRuntime::TargetDataInfo Info(/*RequiresDevicePointerInfo=*/true);
5302
5303 // Create a pre/post action to signal the privatization of the device pointer.
5304 // This action can be replaced by the OpenMP runtime code generation to
5305 // deactivate privatization.
5306 bool PrivatizeDevicePointers = false;
5307 class DevicePointerPrivActionTy : public PrePostActionTy {
5308 bool &PrivatizeDevicePointers;
5309
5310 public:
5311 explicit DevicePointerPrivActionTy(bool &PrivatizeDevicePointers)
5312 : PrePostActionTy(), PrivatizeDevicePointers(PrivatizeDevicePointers) {}
5313 void Enter(CodeGenFunction &CGF) override {
5314 PrivatizeDevicePointers = true;
5315 }
Samuel Antaodf158d52016-04-27 22:58:19 +00005316 };
Samuel Antaocc10b852016-07-28 14:23:26 +00005317 DevicePointerPrivActionTy PrivAction(PrivatizeDevicePointers);
5318
5319 auto &&CodeGen = [&S, &Info, &PrivatizeDevicePointers](
Alexey Bataev475a7442018-01-12 19:39:11 +00005320 CodeGenFunction &CGF, PrePostActionTy &Action) {
Samuel Antaocc10b852016-07-28 14:23:26 +00005321 auto &&InnermostCodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev475a7442018-01-12 19:39:11 +00005322 CGF.EmitStmt(S.getInnermostCapturedStmt()->getCapturedStmt());
Samuel Antaocc10b852016-07-28 14:23:26 +00005323 };
5324
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00005325 // Codegen that selects whether to generate the privatization code or not.
Samuel Antaocc10b852016-07-28 14:23:26 +00005326 auto &&PrivCodeGen = [&S, &Info, &PrivatizeDevicePointers,
5327 &InnermostCodeGen](CodeGenFunction &CGF,
5328 PrePostActionTy &Action) {
5329 RegionCodeGenTy RCG(InnermostCodeGen);
5330 PrivatizeDevicePointers = false;
5331
5332 // Call the pre-action to change the status of PrivatizeDevicePointers if
5333 // needed.
5334 Action.Enter(CGF);
5335
5336 if (PrivatizeDevicePointers) {
5337 OMPPrivateScope PrivateScope(CGF);
5338 // Emit all instances of the use_device_ptr clause.
5339 for (const auto *C : S.getClausesOfKind<OMPUseDevicePtrClause>())
5340 CGF.EmitOMPUseDevicePtrClause(*C, PrivateScope,
5341 Info.CaptureDeviceAddrMap);
5342 (void)PrivateScope.Privatize();
5343 RCG(CGF);
Alexey Bataevddf3db92018-04-13 17:31:06 +00005344 } else {
Samuel Antaocc10b852016-07-28 14:23:26 +00005345 RCG(CGF);
Alexey Bataevddf3db92018-04-13 17:31:06 +00005346 }
Samuel Antaocc10b852016-07-28 14:23:26 +00005347 };
5348
5349 // Forward the provided action to the privatization codegen.
5350 RegionCodeGenTy PrivRCG(PrivCodeGen);
5351 PrivRCG.setAction(Action);
5352
5353 // Notwithstanding the body of the region is emitted as inlined directive,
5354 // we don't use an inline scope as changes in the references inside the
5355 // region are expected to be visible outside, so we do not privative them.
5356 OMPLexicalScope Scope(CGF, S);
5357 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_target_data,
5358 PrivRCG);
5359 };
5360
5361 RegionCodeGenTy RCG(CodeGen);
Samuel Antaodf158d52016-04-27 22:58:19 +00005362
5363 // If we don't have target devices, don't bother emitting the data mapping
5364 // code.
5365 if (CGM.getLangOpts().OMPTargetTriples.empty()) {
Samuel Antaocc10b852016-07-28 14:23:26 +00005366 RCG(*this);
Samuel Antaodf158d52016-04-27 22:58:19 +00005367 return;
5368 }
5369
5370 // Check if we have any if clause associated with the directive.
5371 const Expr *IfCond = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005372 if (const auto *C = S.getSingleClause<OMPIfClause>())
Samuel Antaodf158d52016-04-27 22:58:19 +00005373 IfCond = C->getCondition();
5374
5375 // Check if we have any device clause associated with the directive.
5376 const Expr *Device = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005377 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
Samuel Antaodf158d52016-04-27 22:58:19 +00005378 Device = C->getDevice();
5379
Samuel Antaocc10b852016-07-28 14:23:26 +00005380 // Set the action to signal privatization of device pointers.
5381 RCG.setAction(PrivAction);
5382
5383 // Emit region code.
5384 CGM.getOpenMPRuntime().emitTargetDataCalls(*this, S, IfCond, Device, RCG,
5385 Info);
Michael Wong65f367f2015-07-21 13:44:28 +00005386}
Alexey Bataev49f6e782015-12-01 04:18:41 +00005387
Samuel Antaodf67fc42016-01-19 19:15:56 +00005388void CodeGenFunction::EmitOMPTargetEnterDataDirective(
5389 const OMPTargetEnterDataDirective &S) {
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00005390 // If we don't have target devices, don't bother emitting the data mapping
5391 // code.
5392 if (CGM.getLangOpts().OMPTargetTriples.empty())
5393 return;
5394
5395 // Check if we have any if clause associated with the directive.
5396 const Expr *IfCond = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005397 if (const auto *C = S.getSingleClause<OMPIfClause>())
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00005398 IfCond = C->getCondition();
5399
5400 // Check if we have any device clause associated with the directive.
5401 const Expr *Device = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005402 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
Samuel Antaobd0ae2e2016-04-27 23:07:29 +00005403 Device = C->getDevice();
5404
Alexey Bataev475a7442018-01-12 19:39:11 +00005405 OMPLexicalScope Scope(*this, S, OMPD_task);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00005406 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
Samuel Antaodf67fc42016-01-19 19:15:56 +00005407}
5408
Samuel Antao72590762016-01-19 20:04:50 +00005409void CodeGenFunction::EmitOMPTargetExitDataDirective(
5410 const OMPTargetExitDataDirective &S) {
Samuel Antao8dd66282016-04-27 23:14:30 +00005411 // If we don't have target devices, don't bother emitting the data mapping
5412 // code.
5413 if (CGM.getLangOpts().OMPTargetTriples.empty())
5414 return;
5415
5416 // Check if we have any if clause associated with the directive.
5417 const Expr *IfCond = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005418 if (const auto *C = S.getSingleClause<OMPIfClause>())
Samuel Antao8dd66282016-04-27 23:14:30 +00005419 IfCond = C->getCondition();
5420
5421 // Check if we have any device clause associated with the directive.
5422 const Expr *Device = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005423 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
Samuel Antao8dd66282016-04-27 23:14:30 +00005424 Device = C->getDevice();
5425
Alexey Bataev475a7442018-01-12 19:39:11 +00005426 OMPLexicalScope Scope(*this, S, OMPD_task);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00005427 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
Samuel Antao72590762016-01-19 20:04:50 +00005428}
5429
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00005430static void emitTargetParallelRegion(CodeGenFunction &CGF,
5431 const OMPTargetParallelDirective &S,
5432 PrePostActionTy &Action) {
5433 // Get the captured statement associated with the 'parallel' region.
Alexey Bataevddf3db92018-04-13 17:31:06 +00005434 const CapturedStmt *CS = S.getCapturedStmt(OMPD_parallel);
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00005435 Action.Enter(CGF);
Alexey Bataevc99042b2018-03-15 18:10:54 +00005436 auto &&CodeGen = [&S, CS](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataev63cc8e92018-03-20 14:45:59 +00005437 Action.Enter(CGF);
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005438 CodeGenFunction::OMPPrivateScope PrivateScope(CGF);
5439 (void)CGF.EmitOMPFirstprivateClause(S, PrivateScope);
5440 CGF.EmitOMPPrivateClause(S, PrivateScope);
5441 CGF.EmitOMPReductionClauseInit(S, PrivateScope);
5442 (void)PrivateScope.Privatize();
Alexey Bataev60705422018-10-30 15:50:12 +00005443 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()))
5444 CGF.CGM.getOpenMPRuntime().adjustTargetSpecificDataForLambdas(CGF, S);
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00005445 // TODO: Add support for clauses.
5446 CGF.EmitStmt(CS->getCapturedStmt());
Arpith Chacko Jacob101e8fb2017-02-16 16:20:16 +00005447 CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00005448 };
Carlo Bertollib0ff0a62017-04-25 17:52:12 +00005449 emitCommonOMPParallelDirective(CGF, S, OMPD_parallel, CodeGen,
5450 emitEmptyBoundParameters);
Alexey Bataevddf3db92018-04-13 17:31:06 +00005451 emitPostUpdateForReductionClause(CGF, S,
5452 [](CodeGenFunction &) { return nullptr; });
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00005453}
5454
5455void CodeGenFunction::EmitOMPTargetParallelDeviceFunction(
5456 CodeGenModule &CGM, StringRef ParentName,
5457 const OMPTargetParallelDirective &S) {
5458 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5459 emitTargetParallelRegion(CGF, S, Action);
5460 };
5461 llvm::Function *Fn;
5462 llvm::Constant *Addr;
5463 // Emit target region as a standalone region.
5464 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
5465 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
5466 assert(Fn && Addr && "Target device function emission failed.");
5467}
5468
Arpith Chacko Jacobe955b3d2016-01-26 18:48:41 +00005469void CodeGenFunction::EmitOMPTargetParallelDirective(
5470 const OMPTargetParallelDirective &S) {
Arpith Chacko Jacob19b911c2017-01-18 18:18:53 +00005471 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5472 emitTargetParallelRegion(CGF, S, Action);
5473 };
5474 emitCommonOMPTargetDirective(*this, S, CodeGen);
Arpith Chacko Jacobe955b3d2016-01-26 18:48:41 +00005475}
5476
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00005477static void emitTargetParallelForRegion(CodeGenFunction &CGF,
5478 const OMPTargetParallelForDirective &S,
5479 PrePostActionTy &Action) {
5480 Action.Enter(CGF);
5481 // Emit directive as a combined directive that consists of two implicit
5482 // directives: 'parallel' with 'for' directive.
Alexey Bataevc99042b2018-03-15 18:10:54 +00005483 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5484 Action.Enter(CGF);
Alexey Bataev2139ed62017-11-16 18:20:21 +00005485 CodeGenFunction::OMPCancelStackRAII CancelRegion(
5486 CGF, OMPD_target_parallel_for, S.hasCancel());
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00005487 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
5488 emitDispatchForLoopBounds);
5489 };
5490 emitCommonOMPParallelDirective(CGF, S, OMPD_for, CodeGen,
5491 emitEmptyBoundParameters);
5492}
5493
5494void CodeGenFunction::EmitOMPTargetParallelForDeviceFunction(
5495 CodeGenModule &CGM, StringRef ParentName,
5496 const OMPTargetParallelForDirective &S) {
5497 // Emit SPMD target parallel for region as a standalone region.
5498 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5499 emitTargetParallelForRegion(CGF, S, Action);
5500 };
5501 llvm::Function *Fn;
5502 llvm::Constant *Addr;
5503 // Emit target region as a standalone region.
5504 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
5505 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
5506 assert(Fn && Addr && "Target device function emission failed.");
5507}
5508
Arpith Chacko Jacob05bebb52016-02-03 15:46:42 +00005509void CodeGenFunction::EmitOMPTargetParallelForDirective(
5510 const OMPTargetParallelForDirective &S) {
Alexey Bataevfb0ebec2017-11-08 20:16:14 +00005511 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5512 emitTargetParallelForRegion(CGF, S, Action);
5513 };
5514 emitCommonOMPTargetDirective(*this, S, CodeGen);
Arpith Chacko Jacob05bebb52016-02-03 15:46:42 +00005515}
5516
Alexey Bataev5d7edca2017-11-09 17:32:15 +00005517static void
5518emitTargetParallelForSimdRegion(CodeGenFunction &CGF,
5519 const OMPTargetParallelForSimdDirective &S,
5520 PrePostActionTy &Action) {
5521 Action.Enter(CGF);
5522 // Emit directive as a combined directive that consists of two implicit
5523 // directives: 'parallel' with 'for' directive.
Alexey Bataevc99042b2018-03-15 18:10:54 +00005524 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5525 Action.Enter(CGF);
Alexey Bataev5d7edca2017-11-09 17:32:15 +00005526 CGF.EmitOMPWorksharingLoop(S, S.getEnsureUpperBound(), emitForLoopBounds,
5527 emitDispatchForLoopBounds);
5528 };
5529 emitCommonOMPParallelDirective(CGF, S, OMPD_simd, CodeGen,
5530 emitEmptyBoundParameters);
5531}
5532
5533void CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction(
5534 CodeGenModule &CGM, StringRef ParentName,
5535 const OMPTargetParallelForSimdDirective &S) {
5536 // Emit SPMD target parallel for region as a standalone region.
5537 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5538 emitTargetParallelForSimdRegion(CGF, S, Action);
5539 };
5540 llvm::Function *Fn;
5541 llvm::Constant *Addr;
5542 // Emit target region as a standalone region.
5543 CGM.getOpenMPRuntime().emitTargetOutlinedFunction(
5544 S, ParentName, Fn, Addr, /*IsOffloadEntry=*/true, CodeGen);
5545 assert(Fn && Addr && "Target device function emission failed.");
5546}
5547
5548void CodeGenFunction::EmitOMPTargetParallelForSimdDirective(
5549 const OMPTargetParallelForSimdDirective &S) {
5550 auto &&CodeGen = [&S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5551 emitTargetParallelForSimdRegion(CGF, S, Action);
5552 };
5553 emitCommonOMPTargetDirective(*this, S, CodeGen);
5554}
5555
Alexey Bataev7292c292016-04-25 12:22:29 +00005556/// Emit a helper variable and return corresponding lvalue.
5557static void mapParam(CodeGenFunction &CGF, const DeclRefExpr *Helper,
5558 const ImplicitParamDecl *PVD,
5559 CodeGenFunction::OMPPrivateScope &Privates) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00005560 const auto *VDecl = cast<VarDecl>(Helper->getDecl());
5561 Privates.addPrivate(VDecl,
5562 [&CGF, PVD]() { return CGF.GetAddrOfLocalVar(PVD); });
Alexey Bataev7292c292016-04-25 12:22:29 +00005563}
5564
5565void CodeGenFunction::EmitOMPTaskLoopBasedDirective(const OMPLoopDirective &S) {
5566 assert(isOpenMPTaskLoopDirective(S.getDirectiveKind()));
5567 // Emit outlined function for task construct.
Alexey Bataev475a7442018-01-12 19:39:11 +00005568 const CapturedStmt *CS = S.getCapturedStmt(OMPD_taskloop);
Alexey Bataev172f1462020-03-12 12:52:02 -04005569 Address CapturedStruct = Address::invalid();
5570 {
5571 OMPLexicalScope Scope(*this, S, OMPD_taskloop, /*EmitPreInitStmt=*/false);
5572 CapturedStruct = GenerateCapturedStmtArgument(*CS);
5573 }
Alexey Bataevddf3db92018-04-13 17:31:06 +00005574 QualType SharedsTy = getContext().getRecordType(CS->getCapturedRecordDecl());
Alexey Bataev7292c292016-04-25 12:22:29 +00005575 const Expr *IfCond = nullptr;
5576 for (const auto *C : S.getClausesOfKind<OMPIfClause>()) {
5577 if (C->getNameModifier() == OMPD_unknown ||
5578 C->getNameModifier() == OMPD_taskloop) {
5579 IfCond = C->getCondition();
5580 break;
5581 }
5582 }
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005583
5584 OMPTaskDataTy Data;
5585 // Check if taskloop must be emitted without taskgroup.
5586 Data.Nogroup = S.getSingleClause<OMPNogroupClause>();
Alexey Bataev7292c292016-04-25 12:22:29 +00005587 // TODO: Check if we should emit tied or untied task.
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005588 Data.Tied = true;
5589 // Set scheduling for taskloop
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005590 if (const auto* Clause = S.getSingleClause<OMPGrainsizeClause>()) {
5591 // grainsize clause
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005592 Data.Schedule.setInt(/*IntVal=*/false);
5593 Data.Schedule.setPointer(EmitScalarExpr(Clause->getGrainsize()));
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005594 } else if (const auto* Clause = S.getSingleClause<OMPNumTasksClause>()) {
5595 // num_tasks clause
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005596 Data.Schedule.setInt(/*IntVal=*/true);
5597 Data.Schedule.setPointer(EmitScalarExpr(Clause->getNumTasks()));
Alexey Bataev2b19a6f2016-04-28 09:15:06 +00005598 }
Alexey Bataev7292c292016-04-25 12:22:29 +00005599
5600 auto &&BodyGen = [CS, &S](CodeGenFunction &CGF, PrePostActionTy &) {
5601 // if (PreCond) {
5602 // for (IV in 0..LastIteration) BODY;
5603 // <Final counter/linear vars updates>;
5604 // }
5605 //
5606
5607 // Emit: if (PreCond) - begin.
5608 // If the condition constant folds and can be elided, avoid emitting the
5609 // whole loop.
5610 bool CondConstant;
5611 llvm::BasicBlock *ContBlock = nullptr;
5612 OMPLoopScope PreInitScope(CGF, S);
5613 if (CGF.ConstantFoldsToSimpleInteger(S.getPreCond(), CondConstant)) {
5614 if (!CondConstant)
5615 return;
5616 } else {
Alexey Bataevddf3db92018-04-13 17:31:06 +00005617 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("taskloop.if.then");
Alexey Bataev7292c292016-04-25 12:22:29 +00005618 ContBlock = CGF.createBasicBlock("taskloop.if.end");
5619 emitPreCond(CGF, S, S.getPreCond(), ThenBlock, ContBlock,
5620 CGF.getProfileCount(&S));
5621 CGF.EmitBlock(ThenBlock);
5622 CGF.incrementProfileCounter(&S);
5623 }
5624
Alexey Bataev61205822019-12-04 09:50:21 -05005625 (void)CGF.EmitOMPLinearClauseInit(S);
Alexey Bataev1e73ef32016-04-28 12:14:51 +00005626
Alexey Bataev7292c292016-04-25 12:22:29 +00005627 OMPPrivateScope LoopScope(CGF);
5628 // Emit helper vars inits.
5629 enum { LowerBound = 5, UpperBound, Stride, LastIter };
5630 auto *I = CS->getCapturedDecl()->param_begin();
5631 auto *LBP = std::next(I, LowerBound);
5632 auto *UBP = std::next(I, UpperBound);
5633 auto *STP = std::next(I, Stride);
5634 auto *LIP = std::next(I, LastIter);
5635 mapParam(CGF, cast<DeclRefExpr>(S.getLowerBoundVariable()), *LBP,
5636 LoopScope);
5637 mapParam(CGF, cast<DeclRefExpr>(S.getUpperBoundVariable()), *UBP,
5638 LoopScope);
5639 mapParam(CGF, cast<DeclRefExpr>(S.getStrideVariable()), *STP, LoopScope);
5640 mapParam(CGF, cast<DeclRefExpr>(S.getIsLastIterVariable()), *LIP,
5641 LoopScope);
5642 CGF.EmitOMPPrivateLoopCounters(S, LoopScope);
Alexey Bataev14a388f2019-10-25 10:27:13 -04005643 CGF.EmitOMPLinearClause(S, LoopScope);
Alexey Bataevf93095a2016-05-05 08:46:22 +00005644 bool HasLastprivateClause = CGF.EmitOMPLastprivateClauseInit(S, LoopScope);
Alexey Bataev7292c292016-04-25 12:22:29 +00005645 (void)LoopScope.Privatize();
5646 // Emit the loop iteration variable.
5647 const Expr *IVExpr = S.getIterationVariable();
Alexey Bataevddf3db92018-04-13 17:31:06 +00005648 const auto *IVDecl = cast<VarDecl>(cast<DeclRefExpr>(IVExpr)->getDecl());
Alexey Bataev7292c292016-04-25 12:22:29 +00005649 CGF.EmitVarDecl(*IVDecl);
5650 CGF.EmitIgnoredExpr(S.getInit());
5651
5652 // Emit the iterations count variable.
5653 // If it is not a variable, Sema decided to calculate iterations count on
5654 // each iteration (e.g., it is foldable into a constant).
Alexey Bataevddf3db92018-04-13 17:31:06 +00005655 if (const auto *LIExpr = dyn_cast<DeclRefExpr>(S.getLastIteration())) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005656 CGF.EmitVarDecl(*cast<VarDecl>(LIExpr->getDecl()));
5657 // Emit calculation of the iterations count.
5658 CGF.EmitIgnoredExpr(S.getCalcLastIteration());
5659 }
5660
Alexey Bataev61205822019-12-04 09:50:21 -05005661 {
5662 OMPLexicalScope Scope(CGF, S, OMPD_taskloop, /*EmitPreInitStmt=*/false);
5663 emitCommonSimdLoop(
5664 CGF, S,
5665 [&S](CodeGenFunction &CGF, PrePostActionTy &) {
5666 if (isOpenMPSimdDirective(S.getDirectiveKind()))
5667 CGF.EmitOMPSimdInit(S);
5668 },
5669 [&S, &LoopScope](CodeGenFunction &CGF, PrePostActionTy &) {
5670 CGF.EmitOMPInnerLoop(
5671 S, LoopScope.requiresCleanups(), S.getCond(), S.getInc(),
5672 [&S](CodeGenFunction &CGF) {
5673 CGF.EmitOMPLoopBody(S, CodeGenFunction::JumpDest());
5674 CGF.EmitStopPoint(&S);
5675 },
5676 [](CodeGenFunction &) {});
5677 });
5678 }
Alexey Bataev7292c292016-04-25 12:22:29 +00005679 // Emit: if (PreCond) - end.
5680 if (ContBlock) {
5681 CGF.EmitBranch(ContBlock);
5682 CGF.EmitBlock(ContBlock, true);
5683 }
Alexey Bataevf93095a2016-05-05 08:46:22 +00005684 // Emit final copy of the lastprivate variables if IsLastIter != 0.
5685 if (HasLastprivateClause) {
5686 CGF.EmitOMPLastprivateClauseFinal(
5687 S, isOpenMPSimdDirective(S.getDirectiveKind()),
5688 CGF.Builder.CreateIsNotNull(CGF.EmitLoadOfScalar(
5689 CGF.GetAddrOfLocalVar(*LIP), /*Volatile=*/false,
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005690 (*LIP)->getType(), S.getBeginLoc())));
Alexey Bataevf93095a2016-05-05 08:46:22 +00005691 }
Alexey Bataev14a388f2019-10-25 10:27:13 -04005692 CGF.EmitOMPLinearClauseFinal(S, [LIP, &S](CodeGenFunction &CGF) {
5693 return CGF.Builder.CreateIsNotNull(
5694 CGF.EmitLoadOfScalar(CGF.GetAddrOfLocalVar(*LIP), /*Volatile=*/false,
5695 (*LIP)->getType(), S.getBeginLoc()));
5696 });
Alexey Bataev7292c292016-04-25 12:22:29 +00005697 };
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005698 auto &&TaskGen = [&S, SharedsTy, CapturedStruct,
James Y Knight9871db02019-02-05 16:42:33 +00005699 IfCond](CodeGenFunction &CGF, llvm::Function *OutlinedFn,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005700 const OMPTaskDataTy &Data) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00005701 auto &&CodeGen = [&S, OutlinedFn, SharedsTy, CapturedStruct, IfCond,
5702 &Data](CodeGenFunction &CGF, PrePostActionTy &) {
Alexey Bataev7292c292016-04-25 12:22:29 +00005703 OMPLoopScope PreInitScope(CGF, S);
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005704 CGF.CGM.getOpenMPRuntime().emitTaskLoopCall(CGF, S.getBeginLoc(), S,
Alexey Bataev24b5bae2016-04-28 09:23:51 +00005705 OutlinedFn, SharedsTy,
5706 CapturedStruct, IfCond, Data);
Alexey Bataev7292c292016-04-25 12:22:29 +00005707 };
5708 CGF.CGM.getOpenMPRuntime().emitInlinedDirective(CGF, OMPD_taskloop,
5709 CodeGen);
5710 };
Alexey Bataev475a7442018-01-12 19:39:11 +00005711 if (Data.Nogroup) {
5712 EmitOMPTaskBasedDirective(S, OMPD_taskloop, BodyGen, TaskGen, Data);
5713 } else {
Alexey Bataev33446032017-07-12 18:09:32 +00005714 CGM.getOpenMPRuntime().emitTaskgroupRegion(
5715 *this,
5716 [&S, &BodyGen, &TaskGen, &Data](CodeGenFunction &CGF,
5717 PrePostActionTy &Action) {
5718 Action.Enter(CGF);
Alexey Bataev475a7442018-01-12 19:39:11 +00005719 CGF.EmitOMPTaskBasedDirective(S, OMPD_taskloop, BodyGen, TaskGen,
5720 Data);
Alexey Bataev33446032017-07-12 18:09:32 +00005721 },
Stephen Kellyf2ceec42018-08-09 21:08:08 +00005722 S.getBeginLoc());
Alexey Bataev33446032017-07-12 18:09:32 +00005723 }
Alexey Bataev7292c292016-04-25 12:22:29 +00005724}
5725
Alexey Bataev49f6e782015-12-01 04:18:41 +00005726void CodeGenFunction::EmitOMPTaskLoopDirective(const OMPTaskLoopDirective &S) {
Alexey Bataev46978742020-01-30 10:46:11 -05005727 auto LPCRegion =
5728 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev7292c292016-04-25 12:22:29 +00005729 EmitOMPTaskLoopBasedDirective(S);
Alexey Bataev49f6e782015-12-01 04:18:41 +00005730}
5731
Alexey Bataev0a6ed842015-12-03 09:40:15 +00005732void CodeGenFunction::EmitOMPTaskLoopSimdDirective(
5733 const OMPTaskLoopSimdDirective &S) {
Alexey Bataev46978742020-01-30 10:46:11 -05005734 auto LPCRegion =
5735 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev61205822019-12-04 09:50:21 -05005736 OMPLexicalScope Scope(*this, S);
Alexey Bataev1e73ef32016-04-28 12:14:51 +00005737 EmitOMPTaskLoopBasedDirective(S);
Alexey Bataev0a6ed842015-12-03 09:40:15 +00005738}
Samuel Antao686c70c2016-05-26 17:30:50 +00005739
Alexey Bataev60e51c42019-10-10 20:13:02 +00005740void CodeGenFunction::EmitOMPMasterTaskLoopDirective(
5741 const OMPMasterTaskLoopDirective &S) {
5742 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5743 Action.Enter(CGF);
5744 EmitOMPTaskLoopBasedDirective(S);
5745 };
Alexey Bataev46978742020-01-30 10:46:11 -05005746 auto LPCRegion =
5747 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev60e51c42019-10-10 20:13:02 +00005748 OMPLexicalScope Scope(*this, S, llvm::None, /*EmitPreInitStmt=*/false);
5749 CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getBeginLoc());
5750}
5751
Alexey Bataevb8552ab2019-10-18 16:47:35 +00005752void CodeGenFunction::EmitOMPMasterTaskLoopSimdDirective(
5753 const OMPMasterTaskLoopSimdDirective &S) {
5754 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5755 Action.Enter(CGF);
5756 EmitOMPTaskLoopBasedDirective(S);
5757 };
Alexey Bataev46978742020-01-30 10:46:11 -05005758 auto LPCRegion =
5759 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev61205822019-12-04 09:50:21 -05005760 OMPLexicalScope Scope(*this, S);
Alexey Bataevb8552ab2019-10-18 16:47:35 +00005761 CGM.getOpenMPRuntime().emitMasterRegion(*this, CodeGen, S.getBeginLoc());
5762}
5763
Alexey Bataev5bbcead2019-10-14 17:17:41 +00005764void CodeGenFunction::EmitOMPParallelMasterTaskLoopDirective(
5765 const OMPParallelMasterTaskLoopDirective &S) {
5766 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5767 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
5768 PrePostActionTy &Action) {
5769 Action.Enter(CGF);
5770 CGF.EmitOMPTaskLoopBasedDirective(S);
5771 };
Alexey Bataev18789bf2020-02-13 09:21:15 -05005772 OMPLexicalScope Scope(CGF, S, OMPD_parallel, /*EmitPreInitStmt=*/false);
Alexey Bataev5bbcead2019-10-14 17:17:41 +00005773 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
5774 S.getBeginLoc());
5775 };
Alexey Bataev46978742020-01-30 10:46:11 -05005776 auto LPCRegion =
5777 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev5bbcead2019-10-14 17:17:41 +00005778 emitCommonOMPParallelDirective(*this, S, OMPD_master_taskloop, CodeGen,
5779 emitEmptyBoundParameters);
5780}
5781
Alexey Bataev14a388f2019-10-25 10:27:13 -04005782void CodeGenFunction::EmitOMPParallelMasterTaskLoopSimdDirective(
5783 const OMPParallelMasterTaskLoopSimdDirective &S) {
5784 auto &&CodeGen = [this, &S](CodeGenFunction &CGF, PrePostActionTy &Action) {
5785 auto &&TaskLoopCodeGen = [&S](CodeGenFunction &CGF,
5786 PrePostActionTy &Action) {
5787 Action.Enter(CGF);
5788 CGF.EmitOMPTaskLoopBasedDirective(S);
5789 };
5790 OMPLexicalScope Scope(CGF, S, OMPD_parallel, /*EmitPreInitStmt=*/false);
5791 CGM.getOpenMPRuntime().emitMasterRegion(CGF, TaskLoopCodeGen,
5792 S.getBeginLoc());
5793 };
Alexey Bataev46978742020-01-30 10:46:11 -05005794 auto LPCRegion =
5795 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, S);
Alexey Bataev14a388f2019-10-25 10:27:13 -04005796 emitCommonOMPParallelDirective(*this, S, OMPD_master_taskloop_simd, CodeGen,
5797 emitEmptyBoundParameters);
5798}
5799
Samuel Antao686c70c2016-05-26 17:30:50 +00005800// Generate the instructions for '#pragma omp target update' directive.
5801void CodeGenFunction::EmitOMPTargetUpdateDirective(
5802 const OMPTargetUpdateDirective &S) {
Samuel Antao8d2d7302016-05-26 18:30:22 +00005803 // If we don't have target devices, don't bother emitting the data mapping
5804 // code.
5805 if (CGM.getLangOpts().OMPTargetTriples.empty())
5806 return;
5807
5808 // Check if we have any if clause associated with the directive.
5809 const Expr *IfCond = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005810 if (const auto *C = S.getSingleClause<OMPIfClause>())
Samuel Antao8d2d7302016-05-26 18:30:22 +00005811 IfCond = C->getCondition();
5812
5813 // Check if we have any device clause associated with the directive.
5814 const Expr *Device = nullptr;
Alexey Bataevddf3db92018-04-13 17:31:06 +00005815 if (const auto *C = S.getSingleClause<OMPDeviceClause>())
Samuel Antao8d2d7302016-05-26 18:30:22 +00005816 Device = C->getDevice();
5817
Alexey Bataev475a7442018-01-12 19:39:11 +00005818 OMPLexicalScope Scope(*this, S, OMPD_task);
Alexey Bataevd2202ca2017-12-27 17:58:32 +00005819 CGM.getOpenMPRuntime().emitTargetDataStandAloneCall(*this, S, IfCond, Device);
Samuel Antao686c70c2016-05-26 17:30:50 +00005820}
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00005821
5822void CodeGenFunction::EmitSimpleOMPExecutableDirective(
5823 const OMPExecutableDirective &D) {
5824 if (!D.hasAssociatedStmt() || !D.getAssociatedStmt())
5825 return;
Akira Hatanaka9f37c0e2019-12-03 13:07:22 -08005826 auto &&CodeGen = [&D](CodeGenFunction &CGF, PrePostActionTy &Action) {
Alexey Bataevb3998a02020-03-09 08:55:57 -04005827 OMPPrivateScope GlobalsScope(CGF);
5828 if (isOpenMPTaskingDirective(D.getDirectiveKind())) {
5829 // Capture global firstprivates to avoid crash.
5830 for (const auto *C : D.getClausesOfKind<OMPFirstprivateClause>()) {
5831 for (const Expr *Ref : C->varlists()) {
5832 const auto *DRE = cast<DeclRefExpr>(Ref->IgnoreParenImpCasts());
5833 if (!DRE)
5834 continue;
5835 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
5836 if (!VD || VD->hasLocalStorage())
5837 continue;
5838 if (!CGF.LocalDeclMap.count(VD)) {
5839 LValue GlobLVal = CGF.EmitLValue(Ref);
5840 GlobalsScope.addPrivate(
5841 VD, [&GlobLVal, &CGF]() { return GlobLVal.getAddress(CGF); });
5842 }
5843 }
5844 }
5845 }
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00005846 if (isOpenMPSimdDirective(D.getDirectiveKind())) {
Alexey Bataevb3998a02020-03-09 08:55:57 -04005847 (void)GlobalsScope.Privatize();
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00005848 emitOMPSimdRegion(CGF, cast<OMPLoopDirective>(D), Action);
5849 } else {
5850 if (const auto *LD = dyn_cast<OMPLoopDirective>(&D)) {
Alexey Bataevddf3db92018-04-13 17:31:06 +00005851 for (const Expr *E : LD->counters()) {
Simon Pilgrim93431f92020-01-11 16:00:17 +00005852 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
Alexey Bataev6ab5bb12018-10-29 15:01:58 +00005853 if (!VD->hasLocalStorage() && !CGF.LocalDeclMap.count(VD)) {
5854 LValue GlobLVal = CGF.EmitLValue(E);
Alexey Bataevb3998a02020-03-09 08:55:57 -04005855 GlobalsScope.addPrivate(
Akira Hatanakaf139ae32019-12-03 15:17:01 -08005856 VD, [&GlobLVal, &CGF]() { return GlobLVal.getAddress(CGF); });
Alexey Bataev6ab5bb12018-10-29 15:01:58 +00005857 }
Bjorn Pettersson6c2d83b2018-10-30 08:49:26 +00005858 if (isa<OMPCapturedExprDecl>(VD)) {
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00005859 // Emit only those that were not explicitly referenced in clauses.
5860 if (!CGF.LocalDeclMap.count(VD))
5861 CGF.EmitVarDecl(*VD);
5862 }
5863 }
Alexey Bataevf138fda2018-08-13 19:04:24 +00005864 for (const auto *C : D.getClausesOfKind<OMPOrderedClause>()) {
5865 if (!C->getNumForLoops())
5866 continue;
5867 for (unsigned I = LD->getCollapsedNumber(),
5868 E = C->getLoopNumIterations().size();
5869 I < E; ++I) {
5870 if (const auto *VD = dyn_cast<OMPCapturedExprDecl>(
Mike Rice0ed46662018-09-20 17:19:41 +00005871 cast<DeclRefExpr>(C->getLoopCounter(I))->getDecl())) {
Alexey Bataevf138fda2018-08-13 19:04:24 +00005872 // Emit only those that were not explicitly referenced in clauses.
5873 if (!CGF.LocalDeclMap.count(VD))
5874 CGF.EmitVarDecl(*VD);
5875 }
5876 }
5877 }
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00005878 }
Alexey Bataevb3998a02020-03-09 08:55:57 -04005879 (void)GlobalsScope.Privatize();
Alexey Bataev475a7442018-01-12 19:39:11 +00005880 CGF.EmitStmt(D.getInnermostCapturedStmt()->getCapturedStmt());
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00005881 }
5882 };
Alexey Bataev46978742020-01-30 10:46:11 -05005883 {
5884 auto LPCRegion =
5885 CGOpenMPRuntime::LastprivateConditionalRAII::disable(*this, D);
5886 OMPSimdLexicalScope Scope(*this, D);
5887 CGM.getOpenMPRuntime().emitInlinedDirective(
5888 *this,
5889 isOpenMPSimdDirective(D.getDirectiveKind()) ? OMPD_simd
5890 : D.getDirectiveKind(),
5891 CodeGen);
5892 }
5893 // Check for outer lastprivate conditional update.
5894 checkForLastprivateConditionalUpdate(*this, D);
Alexey Bataeva8a9153a2017-12-29 18:07:07 +00005895}